aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/relation/spawn_methods.rb
diff options
context:
space:
mode:
authorJon Leighton <j@jonathanleighton.com>2012-08-03 10:50:49 +0100
committerJon Leighton <j@jonathanleighton.com>2012-08-03 11:05:31 +0100
commitbf2df6e7ba495ac4d2264e0e2558c366f217ee5d (patch)
tree775ae427819b2200b0ae3c85619d4f5cc8f8c203 /activerecord/lib/active_record/relation/spawn_methods.rb
parentc391919180a19a31a04b9483396d0543a4bed961 (diff)
downloadrails-bf2df6e7ba495ac4d2264e0e2558c366f217ee5d.tar.gz
rails-bf2df6e7ba495ac4d2264e0e2558c366f217ee5d.tar.bz2
rails-bf2df6e7ba495ac4d2264e0e2558c366f217ee5d.zip
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
Diffstat (limited to 'activerecord/lib/active_record/relation/spawn_methods.rb')
-rw-r--r--activerecord/lib/active_record/relation/spawn_methods.rb15
1 files changed, 13 insertions, 2 deletions
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+.