1
0
Fork 0
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:
José Valim 2009-06-23 16:52:39 +02:00
commit 0744900861
15 changed files with 134 additions and 14 deletions

View file

@ -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|

View file

@ -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:

View file

@ -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

View 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

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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')

View file

@ -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|

View file

@ -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)

View file

@ -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|

View file

@ -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

View file

@ -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)))

View file

@ -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

View file

@ -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