aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record/associations/collection_proxy.rb
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record/associations/collection_proxy.rb')
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb64
1 files changed, 17 insertions, 47 deletions
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 811fbfd927..0db0ad8595 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -2,11 +2,8 @@
module ActiveRecord
module Associations
- # Association proxies in Active Record are middlemen between the object that
- # holds the association, known as the <tt>@owner</tt>, and the actual associated
- # object, known as the <tt>@target</tt>. The kind of association any proxy is
- # about is available in <tt>@reflection</tt>. That's an instance of the class
- # ActiveRecord::Reflection::AssociationReflection.
+ # Collection proxies in Active Record are middlemen between an
+ # <tt>association</tt>, and its <tt>target</tt> result set.
#
# For example, given
#
@@ -16,14 +13,14 @@ module ActiveRecord
#
# blog = Blog.first
#
- # the association proxy in <tt>blog.posts</tt> has the object in +blog+ as
- # <tt>@owner</tt>, the collection of its posts as <tt>@target</tt>, and
- # the <tt>@reflection</tt> object represents a <tt>:has_many</tt> macro.
+ # The collection proxy returned by <tt>blog.posts</tt> is built from a
+ # <tt>:has_many</tt> <tt>association</tt>, and delegates to a collection
+ # of posts as the <tt>target</tt>.
#
- # This class delegates unknown methods to <tt>@target</tt> via
- # <tt>method_missing</tt>.
+ # This class delegates unknown methods to the <tt>association</tt>'s
+ # relation class via a delegate cache.
#
- # The <tt>@target</tt> object is not \loaded until needed. For example,
+ # The <tt>target</tt> result set is not loaded until needed. For example,
#
# blog.posts.count
#
@@ -366,34 +363,6 @@ module ActiveRecord
@association.create!(attributes, &block)
end
- # Add one or more records to the collection by setting their foreign keys
- # to the association's primary key. Since #<< flattens its argument list and
- # inserts each record, +push+ and #concat behave identically. Returns +self+
- # so method calls may be chained.
- #
- # class Person < ActiveRecord::Base
- # has_many :pets
- # end
- #
- # person.pets.size # => 0
- # person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
- # person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
- # person.pets.size # => 3
- #
- # person.id # => 1
- # person.pets
- # # => [
- # # #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
- # # #<Pet id: 2, name: "Spook", person_id: 1>,
- # # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
- # # ]
- #
- # person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])
- # person.pets.size # => 5
- def concat(*records)
- @association.concat(*records)
- end
-
# Replaces this collection with +other_array+. This will perform a diff
# and delete/add only records that have changed.
#
@@ -500,7 +469,7 @@ module ActiveRecord
# Pet.find(1, 2, 3)
# # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (1, 2, 3)
def delete_all(dependent = nil)
- @association.delete_all(dependent)
+ @association.delete_all(dependent).tap { reset_scope }
end
# Deletes the records of the collection directly from the database
@@ -527,7 +496,7 @@ module ActiveRecord
#
# Pet.find(1) # => Couldn't find Pet with id=1
def destroy_all
- @association.destroy_all
+ @association.destroy_all.tap { reset_scope }
end
# Deletes the +records+ supplied from the collection according to the strategy
@@ -646,7 +615,7 @@ module ActiveRecord
# # #<Pet id: 3, name: "Choo-Choo", person_id: 1>
# # ]
def delete(*records)
- @association.delete(*records)
+ @association.delete(*records).tap { reset_scope }
end
# Destroys the +records+ supplied and removes them from the collection.
@@ -718,7 +687,7 @@ module ActiveRecord
#
# Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with 'id': (4, 5, 6)
def destroy(*records)
- @association.destroy(*records)
+ @association.destroy(*records).tap { reset_scope }
end
##
@@ -1033,8 +1002,9 @@ module ActiveRecord
end
# Adds one or more +records+ to the collection by setting their foreign keys
- # to the association's primary key. Returns +self+, so several appends may be
- # chained together.
+ # to the association's primary key. Since <tt><<</tt> flattens its argument list and
+ # inserts each record, +push+ and +concat+ behave identically. Returns +self+
+ # so several appends may be chained together.
#
# class Person < ActiveRecord::Base
# has_many :pets
@@ -1057,8 +1027,9 @@ module ActiveRecord
end
alias_method :push, :<<
alias_method :append, :<<
+ alias_method :concat, :<<
- def prepend(*args)
+ def prepend(*args) # :nodoc:
raise NoMethodError, "prepend on association is not defined. Please use <<, push or append"
end
@@ -1130,7 +1101,6 @@ module ActiveRecord
delegate(*delegate_methods, to: :scope)
private
-
def find_nth_with_limit(index, limit)
load_target if find_from_target?
super