提交 f4f8923c 编写于 作者: P Pratik Naik

Merge commit 'fred/pullable'

...@@ -402,6 +402,7 @@ def assert_select_rjs(*args, &block) ...@@ -402,6 +402,7 @@ def assert_select_rjs(*args, &block)
if rjs_type if rjs_type
if rjs_type == :insert if rjs_type == :insert
position = args.shift position = args.shift
id = args.shift
insertion = "insert_#{position}".to_sym insertion = "insert_#{position}".to_sym
raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion] raise ArgumentError, "Unknown RJS insertion type #{position}" unless RJS_STATEMENTS[insertion]
statement = "(#{RJS_STATEMENTS[insertion]})" statement = "(#{RJS_STATEMENTS[insertion]})"
......
...@@ -248,6 +248,14 @@ def test_assert_select_from_rjs_with_multiple_results ...@@ -248,6 +248,14 @@ def test_assert_select_from_rjs_with_multiple_results
end end
end end
def test_assert_select_rjs_for_positioned_insert_should_fail_when_mixing_arguments
render_rjs do |page|
page.insert_html :top, "test1", "<div id=\"1\">foo</div>"
page.insert_html :bottom, "test2", "<div id=\"2\">foo</div>"
end
assert_raises(Assertion) {assert_select_rjs :insert, :top, "test2"}
end
# #
# Test css_select. # Test css_select.
# #
......
...@@ -25,7 +25,7 @@ def persistent_session_id ...@@ -25,7 +25,7 @@ def persistent_session_id
def set_session_value def set_session_value
session[:foo] = "bar" session[:foo] = "bar"
render :text => Marshal.dump(session.to_hash) render :text => Verifier.generate(session.to_hash)
end end
def get_session_value def get_session_value
...@@ -94,8 +94,7 @@ def test_setting_session_value ...@@ -94,8 +94,7 @@ def test_setting_session_value
with_test_route_set do with_test_route_set do
get '/set_session_value' get '/set_session_value'
assert_response :success assert_response :success
session_payload = Verifier.generate(Marshal.load(response.body)) assert_equal ["_myapp_session=#{response.body}; path=/"],
assert_equal ["_myapp_session=#{session_payload}; path=/"],
headers['Set-Cookie'] headers['Set-Cookie']
end end
end end
...@@ -148,8 +147,8 @@ def test_setting_session_value_after_session_reset ...@@ -148,8 +147,8 @@ def test_setting_session_value_after_session_reset
with_test_route_set do with_test_route_set do
get '/set_session_value' get '/set_session_value'
assert_response :success assert_response :success
session_payload = Verifier.generate(Marshal.load(response.body)) session_payload = response.body
assert_equal ["_myapp_session=#{session_payload}; path=/"], assert_equal ["_myapp_session=#{response.body}; path=/"],
headers['Set-Cookie'] headers['Set-Cookie']
get '/call_reset_session' get '/call_reset_session'
......
...@@ -43,7 +43,7 @@ def self.included(base) ...@@ -43,7 +43,7 @@ def self.included(base)
# loading in a more high-level (application developer-friendly) manner. # loading in a more high-level (application developer-friendly) manner.
module ClassMethods module ClassMethods
protected protected
# Eager loads the named associations for the given ActiveRecord record(s). # Eager loads the named associations for the given ActiveRecord record(s).
# #
# In this description, 'association name' shall refer to the name passed # In this description, 'association name' shall refer to the name passed
...@@ -94,8 +94,8 @@ def preload_associations(records, associations, preload_options={}) ...@@ -94,8 +94,8 @@ def preload_associations(records, associations, preload_options={})
raise "parent must be an association name" unless parent.is_a?(String) || parent.is_a?(Symbol) raise "parent must be an association name" unless parent.is_a?(String) || parent.is_a?(Symbol)
preload_associations(records, parent, preload_options) preload_associations(records, parent, preload_options)
reflection = reflections[parent] reflection = reflections[parent]
parents = records.map {|record| record.send(reflection.name)}.flatten parents = records.map {|record| record.send(reflection.name)}.flatten.compact
unless parents.empty? || parents.first.nil? unless parents.empty?
parents.first.class.preload_associations(parents, child) parents.first.class.preload_associations(parents, child)
end end
end end
...@@ -113,7 +113,7 @@ def preload_one_association(records, association, preload_options={}) ...@@ -113,7 +113,7 @@ def preload_one_association(records, association, preload_options={})
# unnecessarily # unnecessarily
records.group_by {|record| class_to_reflection[record.class] ||= record.class.reflections[association]}.each do |reflection, records| records.group_by {|record| class_to_reflection[record.class] ||= record.class.reflections[association]}.each do |reflection, records|
raise ConfigurationError, "Association named '#{ association }' was not found; perhaps you misspelled it?" unless reflection raise ConfigurationError, "Association named '#{ association }' was not found; perhaps you misspelled it?" unless reflection
# 'reflection.macro' can return 'belongs_to', 'has_many', etc. Thus, # 'reflection.macro' can return 'belongs_to', 'has_many', etc. Thus,
# the following could call 'preload_belongs_to_association', # the following could call 'preload_belongs_to_association',
# 'preload_has_many_association', etc. # 'preload_has_many_association', etc.
...@@ -128,7 +128,7 @@ def add_preloaded_records_to_collection(parent_records, reflection_name, associa ...@@ -128,7 +128,7 @@ def add_preloaded_records_to_collection(parent_records, reflection_name, associa
association_proxy.target.push(*[associated_record].flatten) association_proxy.target.push(*[associated_record].flatten)
end end
end end
def add_preloaded_record_to_collection(parent_records, reflection_name, associated_record) def add_preloaded_record_to_collection(parent_records, reflection_name, associated_record)
parent_records.each do |parent_record| parent_records.each do |parent_record|
parent_record.send("set_#{reflection_name}_target", associated_record) parent_record.send("set_#{reflection_name}_target", associated_record)
...@@ -183,18 +183,19 @@ def preload_has_and_belongs_to_many_association(records, reflection, preload_opt ...@@ -183,18 +183,19 @@ def preload_has_and_belongs_to_many_association(records, reflection, preload_opt
conditions = "t0.#{reflection.primary_key_name} #{in_or_equals_for_ids(ids)}" conditions = "t0.#{reflection.primary_key_name} #{in_or_equals_for_ids(ids)}"
conditions << append_conditions(reflection, preload_options) conditions << append_conditions(reflection, preload_options)
associated_records = reflection.klass.find(:all, :conditions => [conditions, ids], associated_records = reflection.klass.with_exclusive_scope do
:include => options[:include], reflection.klass.find(:all, :conditions => [conditions, ids],
:joins => "INNER JOIN #{connection.quote_table_name options[:join_table]} t0 ON #{reflection.klass.quoted_table_name}.#{reflection.klass.primary_key} = t0.#{reflection.association_foreign_key}", :include => options[:include],
:select => "#{options[:select] || table_name+'.*'}, t0.#{reflection.primary_key_name} as the_parent_record_id", :joins => "INNER JOIN #{connection.quote_table_name options[:join_table]} t0 ON #{reflection.klass.quoted_table_name}.#{reflection.klass.primary_key} = t0.#{reflection.association_foreign_key}",
:order => options[:order]) :select => "#{options[:select] || table_name+'.*'}, t0.#{reflection.primary_key_name} as the_parent_record_id",
:order => options[:order])
end
set_association_collection_records(id_to_record_map, reflection.name, associated_records, 'the_parent_record_id') set_association_collection_records(id_to_record_map, reflection.name, associated_records, 'the_parent_record_id')
end end
def preload_has_one_association(records, reflection, preload_options={}) def preload_has_one_association(records, reflection, preload_options={})
return if records.first.send("loaded_#{reflection.name}?") return if records.first.send("loaded_#{reflection.name}?")
id_to_record_map, ids = construct_id_map(records) id_to_record_map, ids = construct_id_map(records)
options = reflection.options options = reflection.options
records.each {|record| record.send("set_#{reflection.name}_target", nil)} records.each {|record| record.send("set_#{reflection.name}_target", nil)}
if options[:through] if options[:through]
...@@ -248,7 +249,7 @@ def preload_has_many_association(records, reflection, preload_options={}) ...@@ -248,7 +249,7 @@ def preload_has_many_association(records, reflection, preload_options={})
reflection.primary_key_name) reflection.primary_key_name)
end end
end end
def preload_through_records(records, reflection, through_association) def preload_through_records(records, reflection, through_association)
through_reflection = reflections[through_association] through_reflection = reflections[through_association]
through_primary_key = through_reflection.primary_key_name through_primary_key = through_reflection.primary_key_name
...@@ -333,11 +334,13 @@ def preload_belongs_to_association(records, reflection, preload_options={}) ...@@ -333,11 +334,13 @@ def preload_belongs_to_association(records, reflection, preload_options={})
end end
conditions = "#{table_name}.#{connection.quote_column_name(primary_key)} #{in_or_equals_for_ids(ids)}" conditions = "#{table_name}.#{connection.quote_column_name(primary_key)} #{in_or_equals_for_ids(ids)}"
conditions << append_conditions(reflection, preload_options) conditions << append_conditions(reflection, preload_options)
associated_records = klass.find(:all, :conditions => [conditions, ids], associated_records = klass.with_exclusive_scope do
klass.find(:all, :conditions => [conditions, ids],
:include => options[:include], :include => options[:include],
:select => options[:select], :select => options[:select],
:joins => options[:joins], :joins => options[:joins],
:order => options[:order]) :order => options[:order])
end
set_association_single_records(id_map, reflection.name, associated_records, primary_key) set_association_single_records(id_map, reflection.name, associated_records, primary_key)
end end
end end
...@@ -355,13 +358,15 @@ def find_associated_records(ids, reflection, preload_options) ...@@ -355,13 +358,15 @@ def find_associated_records(ids, reflection, preload_options)
conditions << append_conditions(reflection, preload_options) conditions << append_conditions(reflection, preload_options)
reflection.klass.find(:all, reflection.klass.with_exclusive_scope do
reflection.klass.find(:all,
:select => (preload_options[:select] || options[:select] || "#{table_name}.*"), :select => (preload_options[:select] || options[:select] || "#{table_name}.*"),
:include => preload_options[:include] || options[:include], :include => preload_options[:include] || options[:include],
:conditions => [conditions, ids], :conditions => [conditions, ids],
:joins => options[:joins], :joins => options[:joins],
:group => preload_options[:group] || options[:group], :group => preload_options[:group] || options[:group],
:order => preload_options[:order] || options[:order]) :order => preload_options[:order] || options[:order])
end
end end
......
...@@ -104,6 +104,14 @@ def test_eager_association_loading_of_stis_with_multiple_references ...@@ -104,6 +104,14 @@ def test_eager_association_loading_of_stis_with_multiple_references
authors.first.posts.first.special_comments.first.post.very_special_comment authors.first.posts.first.special_comments.first.post.very_special_comment
end end
end end
def test_eager_association_loading_where_first_level_returns_nil
authors = Author.find(:all, :include => {:post_about_thinking => :comments}, :order => 'authors.id DESC')
assert_equal [authors(:mary), authors(:david)], authors
assert_no_queries do
authors[1].post_about_thinking.comments.first
end
end
end end
require 'models/vertex' require 'models/vertex'
......
...@@ -771,4 +771,19 @@ def test_eager_loading_with_conditions_on_join_model_preloads ...@@ -771,4 +771,19 @@ def test_eager_loading_with_conditions_on_join_model_preloads
assert_equal author_addresses(:david_address), authors[0].author_address assert_equal author_addresses(:david_address), authors[0].author_address
end end
def test_preload_belongs_to_uses_exclusive_scope
people = Person.males.find(:all, :include => :primary_contact)
assert_not_equal people.length, 0
people.each do |person|
assert_no_queries {assert_not_nil person.primary_contact}
assert_equal Person.find(person.id).primary_contact, person.primary_contact
end
end
def test_preload_has_many_uses_exclusive_scope
people = Person.males.find :all, :include => :agents
people.each do |person|
assert_equal Person.find(person.id).agents, person.agents
end
end
end end
michael: michael:
id: 1 id: 1
first_name: Michael first_name: Michael
primary_contact_id: 2
gender: M
david: david:
id: 2 id: 2
first_name: David first_name: David
\ No newline at end of file primary_contact_id: 3
gender: M
susan:
id: 3
first_name: Susan
primary_contact_id: 2
gender: F
\ No newline at end of file
...@@ -7,4 +7,10 @@ class Person < ActiveRecord::Base ...@@ -7,4 +7,10 @@ class Person < ActiveRecord::Base
has_many :jobs, :through => :references has_many :jobs, :through => :references
has_one :favourite_reference, :class_name => 'Reference', :conditions => ['favourite=?', true] has_one :favourite_reference, :class_name => 'Reference', :conditions => ['favourite=?', true]
has_many :posts_with_comments_sorted_by_comment_id, :through => :readers, :source => :post, :include => :comments, :order => 'comments.id' has_many :posts_with_comments_sorted_by_comment_id, :through => :readers, :source => :post, :include => :comments, :order => 'comments.id'
belongs_to :primary_contact, :class_name => 'Person'
has_many :agents, :class_name => 'Person', :foreign_key => 'primary_contact_id'
named_scope :males, :conditions => { :gender => 'M' }
named_scope :females, :conditions => { :gender => 'F' }
end end
...@@ -298,8 +298,10 @@ def create_table(*args, &block) ...@@ -298,8 +298,10 @@ def create_table(*args, &block)
end end
create_table :people, :force => true do |t| create_table :people, :force => true do |t|
t.string :first_name, :null => false t.string :first_name, :null => false
t.integer :lock_version, :null => false, :default => 0 t.references :primary_contact
t.string :gender, :limit => 1
t.integer :lock_version, :null => false, :default => 0
end end
create_table :pets, :primary_key => :pet_id ,:force => true do |t| create_table :pets, :primary_key => :pet_id ,:force => true do |t|
......
...@@ -24,10 +24,17 @@ def slice(*keys) ...@@ -24,10 +24,17 @@ def slice(*keys)
end end
# Replaces the hash with only the given keys. # Replaces the hash with only the given keys.
# Returns a hash contained the removed key/value pairs
# {:a => 1, :b => 2, :c => 3, :d => 4}.slice!(:a, :b) # => {:c => 3, :d =>4}
def slice!(*keys) def slice!(*keys)
replace(slice(*keys)) keys = keys.map! { |key| convert_key(key) } if respond_to?(:convert_key)
omit = slice(*self.keys - keys)
hash = slice(*keys)
replace(hash)
omit
end end
end end
end end
end end
end end
...@@ -287,10 +287,14 @@ def test_slice ...@@ -287,10 +287,14 @@ def test_slice
# Should return a new hash with only the given keys. # Should return a new hash with only the given keys.
assert_equal expected, original.slice(:a, :b) assert_equal expected, original.slice(:a, :b)
assert_not_equal expected, original assert_not_equal expected, original
end
def test_slice_inplace
original = { :a => 'x', :b => 'y', :c => 10 }
expected = { :c => 10 }
# Should replace the hash with only the given keys. # Should replace the hash with only the given keys.
assert_equal expected, original.slice!(:a, :b) assert_equal expected, original.slice!(:a, :b)
assert_equal expected, original
end end
def test_slice_with_an_array_key def test_slice_with_an_array_key
...@@ -300,10 +304,14 @@ def test_slice_with_an_array_key ...@@ -300,10 +304,14 @@ def test_slice_with_an_array_key
# Should return a new hash with only the given keys when given an array key. # Should return a new hash with only the given keys when given an array key.
assert_equal expected, original.slice([:a, :b], :c) assert_equal expected, original.slice([:a, :b], :c)
assert_not_equal expected, original assert_not_equal expected, original
end
def test_slice_inplace_with_an_array_key
original = { :a => 'x', :b => 'y', :c => 10, [:a, :b] => "an array key" }
expected = { :a => 'x', :b => 'y' }
# Should replace the hash with only the given keys when given an array key. # Should replace the hash with only the given keys when given an array key.
assert_equal expected, original.slice!([:a, :b], :c) assert_equal expected, original.slice!([:a, :b], :c)
assert_equal expected, original
end end
def test_slice_with_splatted_keys def test_slice_with_splatted_keys
...@@ -322,11 +330,17 @@ def test_indifferent_slice ...@@ -322,11 +330,17 @@ def test_indifferent_slice
# Should return a new hash with only the given keys. # Should return a new hash with only the given keys.
assert_equal expected, original.slice(*keys), keys.inspect assert_equal expected, original.slice(*keys), keys.inspect
assert_not_equal expected, original assert_not_equal expected, original
end
end
def test_indifferent_slice_inplace
original = { :a => 'x', :b => 'y', :c => 10 }.with_indifferent_access
expected = { :c => 10 }.with_indifferent_access
[['a', 'b'], [:a, :b]].each do |keys|
# Should replace the hash with only the given keys. # Should replace the hash with only the given keys.
copy = original.dup copy = original.dup
assert_equal expected, copy.slice!(*keys) assert_equal expected, copy.slice!(*keys)
assert_equal expected, copy
end end
end end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册