aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2016-07-18 22:11:35 +0900
committerRyuta Kamizono <kamipo@gmail.com>2016-12-25 04:55:50 +0900
commitd1e0f11b49c9c7598efffbc44a94539b6e982e5c (patch)
treebe9ee3c93723fa5aff2a1dc9867aa25d4fa7907f /activerecord/lib
parent5b874cf42a41b966ca223a278b77fd0b4144ddb6 (diff)
downloadrails-d1e0f11b49c9c7598efffbc44a94539b6e982e5c.tar.gz
rails-d1e0f11b49c9c7598efffbc44a94539b6e982e5c.tar.bz2
rails-d1e0f11b49c9c7598efffbc44a94539b6e982e5c.zip
Delegate to `scope` rather than `merge!` for collection proxy
`merge! association.scope(nullify: false)` is expensive but most methods do not need the merge.
Diffstat (limited to 'activerecord/lib')
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb6
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb32
2 files changed, 24 insertions, 14 deletions
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index 46923f690a..f747491a12 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -313,9 +313,9 @@ module ActiveRecord
record
end
- def scope(opts = {})
- scope = super()
- scope.none! if opts.fetch(:nullify, true) && null_scope?
+ def scope
+ scope = super
+ scope.none! if null_scope?
scope
end
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 9f91f2b536..63f746688c 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -28,12 +28,9 @@ module ActiveRecord
# is computed directly through SQL and does not trigger by itself the
# instantiation of the actual post records.
class CollectionProxy < Relation
- delegate :exists?, :update_all, :arel, to: :scope
-
def initialize(klass, association) #:nodoc:
@association = association
super klass, klass.arel_table, klass.predicate_builder
- merge! association.scope(nullify: false)
end
def target
@@ -956,14 +953,6 @@ module ActiveRecord
@association
end
- # We don't want this object to be put on the scoping stack, because
- # that could create an infinite loop where we call an @association
- # method, which gets the current scope, which is this object, which
- # delegates to @association, and so on.
- def scoping
- @association.scope.scoping { yield }
- end
-
# Returns a <tt>Relation</tt> object for the records in this association
def scope
@association.scope
@@ -1126,6 +1115,19 @@ module ActiveRecord
self
end
+ def respond_to?(name, include_private = false)
+ super || scope.respond_to?(name, include_private)
+ end
+
+ delegate_methods = [
+ QueryMethods,
+ SpawnMethods,
+ ].flat_map { |klass|
+ klass.public_instance_methods(false)
+ } - self.public_instance_methods(false) + [:scoping]
+
+ delegate(*delegate_methods, to: :scope)
+
private
def find_nth_with_limit(index, limit) # :doc:
@@ -1149,6 +1151,14 @@ module ActiveRecord
def exec_queries
load_target
end
+
+ def method_missing(method, *args, &block)
+ if scope.respond_to?(method)
+ scope.public_send(method, *args, &block)
+ else
+ super
+ end
+ end
end
end
end