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
|
# Returns the path component of a URL for the given record. It uses
|
||||||
# <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>.
|
# <tt>polymorphic_url</tt> with <tt>:routing_type => :path</tt>.
|
||||||
def polymorphic_path(record_or_hash_or_array, options = {})
|
def polymorphic_path(record_or_hash_or_array, options = {})
|
||||||
options[:routing_type] = :path
|
polymorphic_url(record_or_hash_or_array, options.merge(:routing_type => :path))
|
||||||
polymorphic_url(record_or_hash_or_array, options)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
%w(edit new).each do |action|
|
%w(edit new).each do |action|
|
||||||
|
|
|
@ -117,6 +117,28 @@ module ActionView
|
||||||
@_content_for[name]
|
@_content_for[name]
|
||||||
end
|
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.
|
# Use an alternate output buffer for the duration of the block.
|
||||||
# Defaults to a new empty string.
|
# Defaults to a new empty string.
|
||||||
def with_output_buffer(buf = nil) #:nodoc:
|
def with_output_buffer(buf = nil) #:nodoc:
|
||||||
|
|
|
@ -234,10 +234,13 @@ class PolymorphicRoutesTest < ActionController::TestCase
|
||||||
with_admin_test_routes do
|
with_admin_test_routes do
|
||||||
@project.save
|
@project.save
|
||||||
@task.save
|
@task.save
|
||||||
|
|
||||||
|
options = {}
|
||||||
object_array = [:admin, @project, @task]
|
object_array = [:admin, @project, @task]
|
||||||
assert_no_difference 'object_array.size' do
|
original_args = [object_array.dup, options.dup]
|
||||||
polymorphic_url(object_array)
|
|
||||||
end
|
assert_no_difference('object_array.size') { polymorphic_path(object_array, options) }
|
||||||
|
assert_equal original_args, [object_array, options]
|
||||||
end
|
end
|
||||||
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)
|
def construct_join_attributes(associate)
|
||||||
# TODO: revist this to allow it for deletion, supposing dependent option is supported
|
# 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
|
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)
|
join_attributes = construct_owner_attributes(@reflection.through_reflection).merge(@reflection.source_reflection.primary_key_name => associate.id)
|
||||||
|
|
||||||
if @reflection.options[:source_type]
|
if @reflection.options[:source_type]
|
||||||
join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name.to_s)
|
join_attributes.merge!(@reflection.source_reflection.options[:foreign_type] => associate.class.base_class.name.to_s)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if @reflection.through_reflection.options[:conditions].is_a?(Hash)
|
||||||
|
join_attributes.merge!(@reflection.through_reflection.options[:conditions])
|
||||||
|
end
|
||||||
|
|
||||||
join_attributes
|
join_attributes
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -101,7 +101,7 @@ module ActiveRecord
|
||||||
table_definition = TableDefinition.new(self)
|
table_definition = TableDefinition.new(self)
|
||||||
table_definition.primary_key(options[:primary_key] || Base.get_primary_key(table_name)) unless options[:id] == false
|
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)
|
if options[:force] && table_exists?(table_name)
|
||||||
drop_table(table_name, options)
|
drop_table(table_name, options)
|
||||||
|
|
|
@ -245,7 +245,7 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
|
|
||||||
def rename_table(name, new_name)
|
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
|
end
|
||||||
|
|
||||||
# See: http://www.sqlite.org/lang_altertable.html
|
# See: http://www.sqlite.org/lang_altertable.html
|
||||||
|
|
|
@ -157,6 +157,12 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
||||||
assert_equal peeps + 1, posts(:thinking).people.count
|
assert_equal peeps + 1, posts(:thinking).people.count
|
||||||
end
|
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
|
def test_associate_with_create_exclamation_and_no_options
|
||||||
peeps = posts(:thinking).people.count
|
peeps = posts(:thinking).people.count
|
||||||
posts(:thinking).people.create!(:first_name => 'foo')
|
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
|
Person.connection.drop_table table_name rescue nil
|
||||||
end
|
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
|
# Sybase, and SQLite3 will not allow you to add a NOT NULL
|
||||||
# column to a table without a default value.
|
# column to a table without a default value.
|
||||||
unless current_adapter?(:SybaseAdapter, :SQLiteAdapter)
|
unless current_adapter?(:SybaseAdapter, :SQLiteAdapter)
|
||||||
|
@ -635,6 +642,32 @@ if ActiveRecord::Base.connection.supports_migrations?
|
||||||
end
|
end
|
||||||
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
|
def test_rename_table
|
||||||
begin
|
begin
|
||||||
ActiveRecord::Base.connection.create_table :octopuses do |t|
|
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) },
|
:after_add => lambda {|owner, reader| log(:added, :after, reader.first_name) },
|
||||||
:before_remove => lambda {|owner, reader| log(:removed, :before, 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) }
|
: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)
|
def self.top(limit)
|
||||||
ranked_by_comments.limit(limit)
|
ranked_by_comments.limit(limit)
|
||||||
|
|
|
@ -364,6 +364,7 @@ ActiveRecord::Schema.define do
|
||||||
create_table :readers, :force => true do |t|
|
create_table :readers, :force => true do |t|
|
||||||
t.integer :post_id, :null => false
|
t.integer :post_id, :null => false
|
||||||
t.integer :person_id, :null => false
|
t.integer :person_id, :null => false
|
||||||
|
t.boolean :skimmer, :default => false
|
||||||
end
|
end
|
||||||
|
|
||||||
create_table :shape_expressions, :force => true do |t|
|
create_table :shape_expressions, :force => true do |t|
|
||||||
|
|
|
@ -129,8 +129,8 @@ module ActiveSupport
|
||||||
#
|
#
|
||||||
# For example, MemCacheStore's #write method supports the +:expires_in+
|
# For example, MemCacheStore's #write method supports the +:expires_in+
|
||||||
# option, which tells the memcached server to automatically expire the
|
# option, which tells the memcached server to automatically expire the
|
||||||
# cache item after a certain period. We can use this option with #fetch
|
# cache item after a certain period. This options is also supported by
|
||||||
# too:
|
# FileStore's #read method. We can use this option with #fetch too:
|
||||||
#
|
#
|
||||||
# cache = ActiveSupport::Cache::MemCacheStore.new
|
# cache = ActiveSupport::Cache::MemCacheStore.new
|
||||||
# cache.fetch("foo", :force => true, :expires_in => 5.seconds) do
|
# 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.
|
# You may also specify additional options via the +options+ argument.
|
||||||
# The specific cache store implementation will decide what to do with
|
# The specific cache store implementation will decide what to do with
|
||||||
# +options+.
|
# +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)
|
def read(key, options = nil)
|
||||||
log("read", key, options)
|
log("read", key, options)
|
||||||
end
|
end
|
||||||
|
@ -223,6 +227,10 @@ module ActiveSupport
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
def expires_in(options)
|
||||||
|
(options && options[:expires_in]) || 0
|
||||||
|
end
|
||||||
|
|
||||||
def log(operation, key, options)
|
def log(operation, key, options)
|
||||||
logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !@silence && !@logger_off
|
logger.debug("Cache #{operation}: #{key}#{options ? " (#{options.inspect})" : ""}") if logger && !@silence && !@logger_off
|
||||||
end
|
end
|
||||||
|
|
|
@ -10,11 +10,23 @@ module ActiveSupport
|
||||||
@cache_path = cache_path
|
@cache_path = cache_path
|
||||||
end
|
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)
|
def read(name, options = nil)
|
||||||
super
|
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
|
end
|
||||||
|
|
||||||
|
# Writes a value to the cache.
|
||||||
def write(name, value, options = nil)
|
def write(name, value, options = nil)
|
||||||
super
|
super
|
||||||
ensure_cache_path(File.dirname(real_file_path(name)))
|
ensure_cache_path(File.dirname(real_file_path(name)))
|
||||||
|
|
|
@ -130,10 +130,6 @@ module ActiveSupport
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def expires_in(options)
|
|
||||||
(options && options[:expires_in]) || 0
|
|
||||||
end
|
|
||||||
|
|
||||||
def raw?(options)
|
def raw?(options)
|
||||||
options && options[:raw]
|
options && options[:raw]
|
||||||
end
|
end
|
||||||
|
|
|
@ -146,6 +146,22 @@ class FileStoreTest < ActiveSupport::TestCase
|
||||||
end
|
end
|
||||||
|
|
||||||
include CacheStoreBehavior
|
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
|
end
|
||||||
|
|
||||||
class MemoryStoreTest < ActiveSupport::TestCase
|
class MemoryStoreTest < ActiveSupport::TestCase
|
||||||
|
|
Loading…
Reference in a new issue