From fe6ffce51dc16285094be49244b26591956c2dd6 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Sat, 24 Jan 2009 17:54:10 +0000 Subject: [PATCH] Make sure inner scope conditions get a preference over the outer ones --- actionpack/test/fixtures/replies.yml | 10 +++++++++- activerecord/lib/active_record/base.rb | 8 ++++++-- activerecord/test/cases/named_scope_test.rb | 20 ++++++++++++++++++++ activerecord/test/models/post.rb | 6 ++++++ activerecord/test/models/topic.rb | 2 ++ 5 files changed, 43 insertions(+), 3 deletions(-) diff --git a/actionpack/test/fixtures/replies.yml b/actionpack/test/fixtures/replies.yml index a17d2fc42b..2022523eac 100644 --- a/actionpack/test/fixtures/replies.yml +++ b/actionpack/test/fixtures/replies.yml @@ -12,4 +12,12 @@ another: developer_id: 1 content: Nuh uh! created_at: <%= 1.hour.ago.to_s(:db) %> - updated_at: nil \ No newline at end of file + updated_at: nil + +best_reply: + id: 3 + topic_id: 3 + developer_id: 2 + content: No one can know + created_at: <%= 5.hours.ago.to_s(:db) %> + updated_at: nil diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index ebc0b7783f..8db3909d9a 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -2097,7 +2097,11 @@ def with_scope(method_scoping = {}, action = :merge, &block) (hash[method].keys + params.keys).uniq.each do |key| merge = hash[method][key] && params[key] # merge if both scopes have the same key if key == :conditions && merge - hash[method][key] = merge_conditions(params[key], hash[method][key]) + if params[key].is_a?(Hash) && hash[method][key].is_a?(Hash) + hash[method][key] = merge_conditions(hash[method][key].deep_merge(params[key])) + else + hash[method][key] = merge_conditions(params[key], hash[method][key]) + end elsif key == :include && merge hash[method][key] = merge_includes(hash[method][key], params[key]).uniq elsif key == :joins && merge @@ -2107,7 +2111,7 @@ def with_scope(method_scoping = {}, action = :merge, &block) end end else - hash[method] = params.merge(hash[method]) + hash[method] = hash[method].merge(params) end else hash[method] = params diff --git a/activerecord/test/cases/named_scope_test.rb b/activerecord/test/cases/named_scope_test.rb index bab842cf66..e1e27fa130 100644 --- a/activerecord/test/cases/named_scope_test.rb +++ b/activerecord/test/cases/named_scope_test.rb @@ -277,6 +277,26 @@ def test_chaining_with_duplicate_joins post = Post.find(1) assert_equal post.comments.size, Post.scoped(:joins => join).scoped(:joins => join, :conditions => "posts.id = #{post.id}").size end + + def test_chanining_should_use_latest_conditions_when_creating + post1 = Topic.rejected.approved.new + assert post1.approved? + + post2 = Topic.approved.rejected.new + assert ! post2.approved? + end + + def test_chanining_should_use_latest_conditions_when_searching + # Normal hash conditions + assert_equal Topic.all(:conditions => {:approved => true}), Topic.rejected.approved.all + assert_equal Topic.all(:conditions => {:approved => false}), Topic.approved.rejected.all + + # Nested hash conditions with same keys + assert_equal [posts(:sti_comments)], Post.with_special_comments.with_very_special_comments.all + + # Nested hash conditions with different keys + assert_equal [posts(:sti_comments)], Post.with_special_comments.with_post(4).all.uniq + end end class DynamicScopeMatchTest < ActiveRecord::TestCase diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb index e0d8be676a..388fff8fba 100644 --- a/activerecord/test/models/post.rb +++ b/activerecord/test/models/post.rb @@ -17,6 +17,12 @@ def greeting has_one :last_comment, :class_name => 'Comment', :order => 'id desc' + named_scope :with_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'SpecialComment'} } + named_scope :with_very_special_comments, :joins => :comments, :conditions => {:comments => {:type => 'VerySpecialComment'} } + named_scope :with_post, lambda {|post_id| + { :joins => :comments, :conditions => {:comments => {:post_id => post_id} } } + } + has_many :comments, :order => "body" do def find_most_recent find(:first, :order => "id DESC") diff --git a/activerecord/test/models/topic.rb b/activerecord/test/models/topic.rb index 39ca1bf42a..08bb24ed03 100644 --- a/activerecord/test/models/topic.rb +++ b/activerecord/test/models/topic.rb @@ -4,6 +4,8 @@ class Topic < ActiveRecord::Base { :conditions => ['written_on < ?', time] } } named_scope :approved, :conditions => {:approved => true} + named_scope :rejected, :conditions => {:approved => false} + named_scope :by_lifo, :conditions => {:author_name => 'lifo'} named_scope :approved_as_hash_condition, :conditions => {:topics => {:approved => true}} -- GitLab