aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md20
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb15
-rw-r--r--activerecord/test/cases/relation_test.rb4
3 files changed, 37 insertions, 2 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index c78e602af7..8356b49bec 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,25 @@
## Rails 4.0.0 (unreleased) ##
+* Allow Relation#merge to take a proc.
+
+ This was requested by DHH to allow creating of one's own custom
+ association macros.
+
+ For example:
+
+ module Commentable
+ def has_many_comments(extra)
+ has_many :comments, -> { where(:foo).merge(extra) }
+ end
+ end
+
+ class Post < ActiveRecord::Base
+ extend Commentable
+ has_many_comments -> { where(:bar) }
+ end
+
+ *Jon Leighton*
+
* Add CollectionProxy#scope
This can be used to get a Relation from an association.
diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb
index dcd4c78eb7..5394c1b28b 100644
--- a/activerecord/lib/active_record/relation/spawn_methods.rb
+++ b/activerecord/lib/active_record/relation/spawn_methods.rb
@@ -23,6 +23,13 @@ module ActiveRecord
# # Returns the intersection of all published posts with the 5 most recently created posts.
# # (This is just an example. You'd probably want to do this with a single query!)
#
+ # Procs will be evaluated by merge:
+ #
+ # Post.where(published: true).merge(-> { joins(:comments) })
+ # # => Post.where(published: true).joins(:comments)
+ #
+ # This is mainly intended for sharing common conditions between multiple associations.
+ #
def merge(other)
if other.is_a?(Array)
to_a & other
@@ -35,8 +42,12 @@ module ActiveRecord
# Like #merge, but applies changes in place.
def merge!(other)
- klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger
- klass.new(self, other).merge
+ if !other.is_a?(Relation) && other.respond_to?(:to_proc)
+ instance_exec(&other)
+ else
+ klass = other.is_a?(Hash) ? Relation::HashMerger : Relation::Merger
+ klass.new(self, other).merge
+ end
end
# Removes from the query the condition(s) specified in +skips+.
diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb
index 034339e413..5fb54b1ca1 100644
--- a/activerecord/test/cases/relation_test.rb
+++ b/activerecord/test/cases/relation_test.rb
@@ -247,5 +247,9 @@ module ActiveRecord
assert relation.merge!(where: :foo).equal?(relation)
assert_equal [:foo], relation.where_values
end
+
+ test 'merge with a proc' do
+ assert_equal [:foo], relation.merge(-> { where(:foo) }).where_values
+ end
end
end