mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Merge branch 'master' of git://github.com/rails/rails
This commit is contained in:
commit
0744900861
15 changed files with 134 additions and 14 deletions
|
@ -112,8 +112,7 @@ module ActionController
|
|||
# Returns the path component of a URL for the given record. It uses
|
||||
# <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>.
|
||||
def polymorphic_path(record_or_hash_or_array, options = {})
|
||||
options[:routing_type] = :path
|
||||
polymorphic_url(record_or_hash_or_array, options)
|
||||
polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path))
|
||||
end
|
||||
|
||||
%w(edit new).each do |action|
|
||||
|
|
|
@ -117,6 +117,28 @@ module ActionView
|
|||
@_content_for[name]
|
||||
end
|
||||
|
||||
# content_for? simply checks whether any content has been captured yet using content_for
|
||||
# Useful to render parts of your layout differently based on what is in your views.
|
||||
#
|
||||
# ==== Examples
|
||||
#
|
||||
# Perhaps you will use different css in you layout if no content_for :right_column
|
||||
#
|
||||
# <%# This is the layout %>
|
||||
# <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
# <head>
|
||||
# <title>My Website</title>
|
||||
# <%= yield :script %>
|
||||
# </head>
|
||||
# <body class="<%= content_for?(:right_col) ? 'one-column' : 'two-column' %>">
|
||||
# <%= yield %>
|
||||
# <%= yield :right_col %>
|
||||
# </body>
|
||||
# </html>
|
||||
def content_for?(name)
|
||||
@_content_for[name].present?
|
||||
end
|
||||
|
||||
# Use an alternate output buffer for the duration of the block.
|
||||
# Defaults to a new empty string.
|
||||
def with_output_buffer(buf = nil) #:nodoc:
|
||||
|
|
|
@ -234,10 +234,13 @@ class PolymorphicRoutesTest < ActionController::TestCase
|
|||
with_admin_test_routes do
|
||||
@project.save
|
||||
@task.save
|
||||
|
||||
options = {}
|
||||
object_array = [:admin, @project, @task]
|
||||
assert_no_difference 'object_array.size' do
|
||||
polymorphic_url(object_array)
|
||||
end
|
||||
original_args = [object_array.dup, options.dup]
|
||||
|
||||
assert_no_difference('object_array.size') { polymorphic_path(object_array, options) }
|
||||
assert_equal original_args, [object_array, options]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
15
actionpack/test/template/capture_helper_test.rb
Normal file
15
actionpack/test/template/capture_helper_test.rb
Normal file
|
@ -0,0 +1,15 @@
|
|||
require 'abstract_unit'
|
||||
|
||||
class CaptureHelperTest < ActionView::TestCase
|
||||
def setup
|
||||
super
|
||||
@_content_for = Hash.new {|h,k| h[k] = "" }
|
||||
end
|
||||
|
||||
def test_content_for
|
||||
assert ! content_for?(:title)
|
||||
content_for :title, 'title'
|
||||
assert content_for?(:title)
|
||||
assert ! content_for?(:something_else)
|
||||
end
|
||||
end
|
|
@ -94,10 +94,17 @@ module ActiveRecord
|
|||
def construct_join_attributes(associate)
|
||||
# TODO: revist this to allow it for deletion, supposing dependent option is supported
|
||||
raise ActiveRecord::HasManyThroughCantAssociateThroughHasManyReflection.new(@owner, @reflection) if @reflection.source_reflection.macro == :has_many
|
||||
|
||||
join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id)
|
||||
|
||||
if @reflection.options[:source_type]
|
||||
join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name.to_s)
|
||||
end
|
||||
|
||||
if @reflection.through_reflection.options[:conditions].is_a?(Hash)
|
||||
join_attributes.merge!(@reflection.through_reflection.options[:conditions])
|
||||
end
|
||||
|
||||
join_attributes
|
||||
end
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ module ActiveRecord
|
|||
table_definition = TableDefinition.new(self)
|
||||
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
|
||||
|
||||
yield table_definition
|
||||
yield table_definition if block_given?
|
||||
|
||||
if options[:force] && table_exists?(table_name)
|
||||
drop_table(table_name, options)
|
||||
|
|
|
@ -245,7 +245,7 @@ module ActiveRecord
|
|||
end
|
||||
|
||||
def rename_table(name, new_name)
|
||||
execute "ALTER TABLE #{name} RENAME TO #{new_name}"
|
||||
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
|
||||
end
|
||||
|
||||
# See: http://www.sqlite.org/lang_altertable.html
|
||||
|
|
|
@ -157,6 +157,12 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|||
assert_equal peeps + 1, posts(:thinking).people.count
|
||||
end
|
||||
|
||||
def test_associate_with_create_with_through_having_conditions
|
||||
impatient_people = posts(:thinking).impatient_people.count
|
||||
posts(:thinking).impatient_people.create!(:first_name => 'foo')
|
||||
assert_equal impatient_people + 1, posts(:thinking).impatient_people.count
|
||||
end
|
||||
|
||||
def test_associate_with_create_exclamation_and_no_options
|
||||
peeps = posts(:thinking).people.count
|
||||
posts(:thinking).people.create!(:first_name => 'foo')
|
||||
|
|
|
@ -293,6 +293,13 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
Person.connection.drop_table table_name rescue nil
|
||||
end
|
||||
|
||||
def test_create_table_without_a_block
|
||||
table_name = :testings
|
||||
Person.connection.create_table table_name
|
||||
ensure
|
||||
Person.connection.drop_table table_name rescue nil
|
||||
end
|
||||
|
||||
# Sybase, and SQLite3 will not allow you to add a NOT NULL
|
||||
# column to a table without a default value.
|
||||
unless current_adapter?(:SybaseAdapter, :SQLiteAdapter)
|
||||
|
@ -635,6 +642,32 @@ if ActiveRecord::Base.connection.supports_migrations?
|
|||
end
|
||||
end
|
||||
|
||||
if current_adapter?(:SQLiteAdapter)
|
||||
def test_rename_table_for_sqlite_should_work_with_reserved_words
|
||||
begin
|
||||
assert_nothing_raised do
|
||||
ActiveRecord::Base.connection.rename_table :references, :old_references
|
||||
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
||||
t.column :url, :string
|
||||
end
|
||||
end
|
||||
|
||||
assert_nothing_raised { ActiveRecord::Base.connection.rename_table :octopuses, :references }
|
||||
|
||||
# Using explicit id in insert for compatibility across all databases
|
||||
con = ActiveRecord::Base.connection
|
||||
assert_nothing_raised do
|
||||
con.execute "INSERT INTO 'references' (#{con.quote_column_name('id')}, #{con.quote_column_name('url')}) VALUES (1, 'http://rubyonrails.com')"
|
||||
end
|
||||
assert_equal 'http://rubyonrails.com', ActiveRecord::Base.connection.select_value("SELECT url FROM 'references' WHERE id=1")
|
||||
|
||||
ensure
|
||||
ActiveRecord::Base.connection.drop_table :references
|
||||
ActiveRecord::Base.connection.rename_table :old_references, :references
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def test_rename_table
|
||||
begin
|
||||
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
||||
|
|
|
@ -69,6 +69,8 @@ class Post < ActiveRecord::Base
|
|||
:after_add => lambda {|owner, reader| log(:added, :after, reader.first_name) },
|
||||
:before_remove => lambda {|owner, reader| log(:removed, :before, reader.first_name) },
|
||||
:after_remove => lambda {|owner, reader| log(:removed, :after, reader.first_name) }
|
||||
has_many :skimmers, :class_name => 'Reader', :conditions => { :skimmer => true }
|
||||
has_many :impatient_people, :through => :skimmers, :source => :person
|
||||
|
||||
def self.top(limit)
|
||||
ranked_by_comments.limit(limit)
|
||||
|
|
|
@ -364,6 +364,7 @@ ActiveRecord::Schema.define do
|
|||
create_table :readers, :force => true do |t|
|
||||
t.integer :post_id, :null => false
|
||||
t.integer :person_id, :null => false
|
||||
t.boolean :skimmer, :default => false
|
||||
end
|
||||
|
||||
create_table :shape_expressions, :force => true do |t|
|
||||
|
|
|
@ -129,8 +129,8 @@ module ActiveSupport
|
|||
#
|
||||
# For example, MemCacheStore's #write method supports the +:expires_in+
|
||||
# option, which tells the memcached server to automatically expire the
|
||||
# cache item after a certain period. We can use this option with #fetch
|
||||
# too:
|
||||
# cache item after a certain period. This options is also supported by
|
||||
# FileStore's #read method. We can use this option with #fetch too:
|
||||
#
|
||||
# cache = ActiveSupport::Cache::MemCacheStore.new
|
||||
# cache.fetch("foo", :force => true, :expires_in => 5.seconds) do
|
||||
|
@ -169,6 +169,10 @@ module ActiveSupport
|
|||
# You may also specify additional options via the +options+ argument.
|
||||
# The specific cache store implementation will decide what to do with
|
||||
# +options+.
|
||||
#
|
||||
# For example, FileStore supports the +:expires_in+ option, which
|
||||
# makes the method return nil for cache items older than the specified
|
||||
# period.
|
||||
def read(key, options = nil)
|
||||
log("read", key, options)
|
||||
end
|
||||
|
@ -223,6 +227,10 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
private
|
||||
def expires_in(options)
|
||||
(options && options[:expires_in]) || 0
|
||||
end
|
||||
|
||||
def log(operation, key, options)
|
||||
logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !@silence && !@logger_off
|
||||
end
|
||||
|
|
|
@ -10,11 +10,23 @@ module ActiveSupport
|
|||
@cache_path = cache_path
|
||||
end
|
||||
|
||||
# Reads a value from the cache.
|
||||
#
|
||||
# Possible options:
|
||||
# - +:expires_in+ - the number of seconds that this value may stay in
|
||||
# the cache.
|
||||
def read(name, options = nil)
|
||||
super
|
||||
File.open(real_file_path(name), 'rb') { |f| Marshal.load(f) } rescue nil
|
||||
|
||||
file_name = real_file_path(name)
|
||||
expires = expires_in(options)
|
||||
|
||||
if File.exist?(file_name) && (expires <= 0 || Time.now - File.mtime(file_name) < expires)
|
||||
File.open(file_name, 'rb') { |f| Marshal.load(f) }
|
||||
end
|
||||
end
|
||||
|
||||
# Writes a value to the cache.
|
||||
def write(name, value, options = nil)
|
||||
super
|
||||
ensure_cache_path(File.dirname(real_file_path(name)))
|
||||
|
|
|
@ -130,10 +130,6 @@ module ActiveSupport
|
|||
end
|
||||
|
||||
private
|
||||
def expires_in(options)
|
||||
(options && options[:expires_in]) || 0
|
||||
end
|
||||
|
||||
def raw?(options)
|
||||
options && options[:raw]
|
||||
end
|
||||
|
|
|
@ -146,6 +146,22 @@ class FileStoreTest < ActiveSupport::TestCase
|
|||
end
|
||||
|
||||
include CacheStoreBehavior
|
||||
|
||||
def test_expires_in
|
||||
time = Time.local(2008, 4, 24)
|
||||
Time.stubs(:now).returns(time)
|
||||
File.stubs(:mtime).returns(time)
|
||||
|
||||
@cache.write('foo', 'bar')
|
||||
cache_read = lambda { @cache.read('foo', :expires_in => 1.minute) }
|
||||
assert_equal 'bar', cache_read.call
|
||||
|
||||
Time.stubs(:now).returns(time + 30.seconds)
|
||||
assert_equal 'bar', cache_read.call
|
||||
|
||||
Time.stubs(:now).returns(time + 2.minutes)
|
||||
assert_nil cache_read.call
|
||||
end
|
||||
end
|
||||
|
||||
class MemoryStoreTest < ActiveSupport::TestCase
|
||||
|
|
Loading…
Reference in a new issue