class ActiveRecord::Associations::CollectionProxy

instantiation of the actual post records.
is computed directly through SQL and does not trigger by itself the
blog.posts.count
The @target object is not loaded until needed. For example,
method_missing.
This class delegates unknown methods to @target via
the @reflection object represents a :has_many macro.
@owner, the collection of its posts as @target, and
the association proxy in blog.posts has the object in blog as
blog = Blog.first
end
has_many :posts
class Blog < ActiveRecord::Base
For example, given
ActiveRecord::Reflection::AssociationReflection.
about is available in @reflection. That’s an instance of the class
object, known as the @target. The kind of association any proxy is
holds the association, known as the @owner, and the actual associated
Association proxies in Active Record are middlemen between the object that

def <<(*records)

# ]
# #
# #,
# #,
# => [
person.pets
person.id # => 1

person.pets.size # => 3
person.pets << [Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo')]
person.pets << Pet.new(name: 'Fancy-Fancy')
person.pets.size # => 0

end
has_many :pets
class Person < ActiveRecord::Base

chained together.
to the association's primary key. Returns +self+, so several appends may be
Adds one or more +records+ to the collection by setting their foreign keys
def <<(*records)
  proxy_association.concat(records) && self
end

def ==(other)

# => false
person.pets == other

other = [Pet.new(id: 1), Pet.new(id: 2)]

# => true
person.pets == other

other = person.pets.to_ary

# ]
# #
# #,
# => [
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

+false+.
to the corresponding element in the other array, otherwise returns
contain the same number of elements and if each element is equal
Equivalent to Array#==. Returns +true+ if the two arrays
def ==(other)
  load_target == other
end

def any?(&block)

# => true
end
pet.group == 'dogs'
person.pets.any? do |pet|

# => false
end
pet.group == 'cats'
person.pets.any? do |pet|

# => [#]
person.pets

criteria is not empty.
is the same, it returns true if the collection based on the
You can also pass a block to define criteria. The behavior

person.pets.any? # => true
person.pets.count # => 0
person.pets << Pet.new(name: 'Snoop')

person.pets.any? # => false
person.pets.count # => 0

end
has_many :pets
class Person < ActiveRecord::Base

Returns +true+ if the collection is not empty.
def any?(&block)
  @association.any?(&block)
end

def build(attributes = {}, &block)

person.pets.count # => 0 # count from database
person.pets.size # => 5 # size of the collection

# ]
# #
# #,
# #,
# => [
person.pets.build([{name: 'Spook'}, {name: 'Choo-Choo'}, {name: 'Brain'}])

# => #
person.pets.build(name: 'Fancy-Fancy')

# => #
person.pets.build

end
has_many :pets
class Person

with the new objects.
You can pass an array of attributes hashes, this will return an array
with +attributes+ and linked to this object, but have not yet been saved.
Returns a new object of the collection type that has been instantiated
def build(attributes = {}, &block)
  @association.build(attributes, &block)
end

def clear

+delete_all+ for more information.
of an array with the deleted objects, so methods can be chained. See
Equivalent to +delete_all+. The difference is that returns +self+, instead
def clear
  delete_all
  self
end

def concat(*records)

person.pets.size # => 5
person.pets.concat([Pet.new(name: 'Brain'), Pet.new(name: 'Benny')])

# ]
# #
# #,
# #,
# => [
person.pets
person.id # => 1

person.pets.size # => 3
person.pets.concat(Pet.new(name: 'Spook'), Pet.new(name: 'Choo-Choo'))
person.pets.concat(Pet.new(name: 'Fancy-Fancy'))
person.pets.size # => 0

end
pets :has_many
class Person < ActiveRecord::Base

so method calls may be chained.
inserts each record, +push+ and +concat+ behave identically. Returns +self+
to the association's primary key. Since << flattens its argument list and
Add one or more records to the collection by setting their foreign keys
def concat(*records)
  @association.concat(*records)
end

def count(column_name = nil, options = {})

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.count # => 3

end
has_many :pets
class Person < ActiveRecord::Base

Count all records using SQL.
def count(column_name = nil, options = {})
  @association.count(column_name, options)
end

def create(attributes = {}, &block)

# ]
# #
# #,
# #,
# => [
person.pets.find(1, 2, 3)

person.pets.count # => 3
person.pets.size # => 3

# ]
# #
# #,
# => [
person.pets.create([{name: 'Spook'}, {name: 'Choo-Choo'}])

# => #
person.pets.create(name: 'Fancy-Fancy')

end
has_many :pets
class Person

passes the validations).
attributes, linked to this object and that has already been saved (if it
Returns a new object of the collection type that has been instantiated with
def create(attributes = {}, &block)
  @association.create(attributes, &block)
end

def create!(attributes = {}, &block)

# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
person.pets.create!(name: nil)

end
validates :name, presence: true
class Pet

end
has_many :pets
class Person

Like +create+, except that if the record is invalid, raises an exception.
def create!(attributes = {}, &block)
  @association.create!(attributes, &block)
end

def delete(*records)

# ]
# #
# #,
# => [
person.pets.delete(2, 3)

# => [#]
person.pets.delete("1")

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets
class Person < ActiveRecord::Base

responding to the +id+ and executes delete on them.
You can pass +Fixnum+ or +String+ values, it finds the records

# => ActiveRecord::RecordNotFound: Couldn't find Pet with id=1
Pet.find(1)

# ]
# #
# #,
# => [
person.pets
person.pets.size # => 2

# => [#]
person.pets.delete(Pet.find(1))

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets, dependent: :delete_all
class Person < ActiveRecord::Base

*without* calling their +destroy+ method.
If it is set to :delete_all, all the +records+ are deleted

# => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 3)
Pet.find(1, 3)

# => [#]
person.pets
person.pets.size # => 1

# ]
# #
# #,
# => [
person.pets.delete(Pet.find(1), Pet.find(3))

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets, dependent: :destroy
class Person < ActiveRecord::Base

their +destroy+ method. See +destroy+ for more information.
If it is set to :destroy all the +records+ are removed by calling

# => #
Pet.find(1)

# ]
# #
# #,
# => [
person.pets
person.pets.size # => 2

# => [#]
person.pets.delete(Pet.find(1))

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets # dependent: :nullify option by default
class Person < ActiveRecord::Base

strategy is +delete_all+.
keys to NULL. For, +has_many+ :through, the default
strategy. The default strategy is :nullify. This sets the foreign
If no :dependent option is given, then it will follow the default

deleted records.
specified by the :dependent option. Returns an array with the
+has_many+ associations, the deletion is done according to the strategy
Deletes the +records+ supplied and removes them from the collection. For
def delete(*records)
  @association.delete(*records)
end

def delete_all

# => ActiveRecord::RecordNotFound
Pet.find(1, 2, 3)

# ]
# #
# #,
# #,
# => [
person.pets.delete_all

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets, dependent: :delete_all
class Person < ActiveRecord::Base

*without* calling their +destroy+ method.
If it is set to :delete_all, all the objects are deleted

# => ActiveRecord::RecordNotFound
Pet.find(1, 2, 3)

# ]
# #
# #,
# #,
# => [
person.pets.delete_all

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets, dependent: :destroy
class Person < ActiveRecord::Base

information.
are removed by calling their +destroy+ method. See +destroy+ for more
If it is set to :destroy all the objects from the collection

# ]
# #
# #,
# #,
# => [
Pet.find(1, 2, 3)

person.pets # => []
person.pets.size # => 0

# ]
# #
# #,
# #,
# => [
person.pets.delete_all

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets # dependent: :nullify option by default
class Person < ActiveRecord::Base

the default strategy is +delete_all+.
sets the foreign keys to NULL. For, +has_many+ :through,
default strategy. The default strategy is :nullify. This
If no :dependent option is given, then it will follow the

option. Returns an array with the deleted records.
the deletion is done according to the strategy specified by the :dependent
Deletes all the records from the collection. For +has_many+ associations,
def delete_all
  @association.delete_all
end

def destroy(*records)

Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (4, 5, 6)

person.pets # => []
person.pets.size # => 0

# ]
# #
# #,
# => [
person.pets.destroy(5, 6)

# ]
# #
# #,
# => [
person.pets
person.pets.size # => 2

# => #
person.pets.destroy("4")

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

responding to the +id+ and then deletes them from the database.
You can pass +Fixnum+ or +String+ values, it finds the records

Pet.find(1, 2, 3) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (1, 2, 3)

person.pets # => []
person.pets.size # => 0

# ]
# #
# #,
# => [
person.pets.destroy(Pet.find(2), Pet.find(3))

# ]
# #
# #,
# => [
person.pets
person.pets.size # => 2

# => [#]
person.pets.destroy(Pet.find(1))

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets
class Person < ActiveRecord::Base

the +:dependent+ option. Returns an array with the removed records.
This method will _always_ remove record from the database ignoring
Destroys the +records+ supplied and removes them from the collection.
def destroy(*records)
  @association.destroy(*records)
end

def destroy_all

Pet.find(1) # => Couldn't find Pet with id=1

person.pets # => []
person.pets.size # => 0

person.pets.destroy_all

# ]
# #
# #,
# #,
# => [
person.pets
person.pets.size # => 3

end
has_many :pets
class Person < ActiveRecord::Base

option.
This will _always_ remove the records ignoring the +:dependent+
Deletes the records of the collection directly from the database.
def destroy_all
  @association.destroy_all
end

def distinct

# => [#]
person.pets.select(:name).distinct

# ]
# #
# #,
# => [
person.pets.select(:name)

end
has_many :pets
class Person < ActiveRecord::Base

Specifies whether the records should be unique or not.
def distinct
  @association.distinct
end

def empty?

person.pets.empty? # => true
person.pets.count # => 0

person.pets.delete_all

person.pets.empty? # => false
person.pets.count # => 1

end
has_many :pets
class Person < ActiveRecord::Base

is better to check collection.length.zero?.
not already been loaded and you are going to fetch the records anyway it
it is equivalent to collection.exists?. If the collection has
to collection.size.zero?. If the collection has not been loaded,
loaded or the :counter_sql option is provided, it is equivalent
Returns +true+ if the collection is empty. If the collection has been
def empty?
  @association.empty?
end

def find(*args, &block)

# ]
# #
# #,
# => [
person.pets.find(2, 3)

# => #
person.pets.find(2) { |pet| pet.name.downcase! }

person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=4
person.pets.find(1) # => #

# ]
# #
# #,
# #,
# => [
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

error if the object can not be found.
rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound
Finds an object in the collection responding to the +id+. Uses the same
def find(*args, &block)
  @association.find(*args, &block)
end

def first(*args)

another_person_without.pets.first(3) # => []
another_person_without.pets.first # => nil
another_person_without.pets # => []

# ]
# #
# #,
# => [
person.pets.first(2)

person.pets.first # => #

# ]
# #
# #,
# #,
# => [
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

form returns an empty array.
If the collection is empty, the first form returns +nil+, and the second
Returns the first record, or the first +n+ records, from the collection.
def first(*args)
  @association.first(*args)
end

def include?(record)

person.pets.include?(Pet.find(21)) # => false
person.pets.include?(Pet.find(20)) # => true

person.pets # => [#]

end
has_many :pets
class Person < ActiveRecord::Base

Returns +true+ if the given object is present in the collection.
def include?(record)
  !!@association.include?(record)
end

def initialize(klass, association) #:nodoc:

:nodoc:
def initialize(klass, association) #:nodoc:
  @association = association
  super klass, klass.arel_table
  self.default_scoped = true
  merge! association.scope(nullify: false)
end

def last(*args)

another_person_without.pets.last(3) # => []
another_person_without.pets.last # => nil
another_person_without.pets # => []

# ]
# #
# #,
# => [
person.pets.last(2)

person.pets.last # => #

# ]
# #
# #,
# #,
# => [
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

form returns an empty array.
If the collection is empty, the first form returns +nil+, and the second
Returns the last record, or the last +n+ records, from the collection.
def last(*args)
  @association.last(*args)
end

def length

# ]
# #
# #,
# #,
# => [
person.pets
# call the collection with no additional queries:
# Because the collection is loaded, you can

# executes something like SELECT "pets".* FROM "pets" WHERE "pets"."person_id" = 1
person.pets.length # => 3

end
has_many :pets
class Person < ActiveRecord::Base

method will take one less query. Otherwise +size+ is more efficient.
equivalent. If not and you are going to need the records anyway this
If the collection has been already loaded, +length+ and +size+ are
Returns the size of the collection calling +size+ on the target.
def length
  @association.length
end

def load_target

def load_target
  @association.load_target
end

def loaded?

person.pets.loaded? # => true
person.pets
person.pets.loaded? # => false

Returns +true+ if the association has been loaded, otherwise +false+.
def loaded?
  @association.loaded?
end

def many?(&block)

# => true
end
pet.group == 'cats'
person.pets.many? do |pet|

# => false
end
pet.group == 'dogs'
person.pets.many? do |pet|

# ]
# #
# #,
# #,
# => [
person.pets

based on the criteria has more than one record.
behavior is the same, it returns true if the collection
You can also pass a block to define criteria. The

person.pets.many? #=> true
person.pets.count #=> 2
person.pets << Pet.new(name: 'Snoopy')

person.pets.many? #=> false
person.pets.count #=> 1

end
has_many :pets
class Person < ActiveRecord::Base

Equivalent to collection.size > 1.
Returns true if the collection has more than one record.
def many?(&block)
  @association.many?(&block)
end

def prepend(*args)

def prepend(*args)
  raise NoMethodError, "prepend on association is not defined. Please use << or append"
end

def proxy_association

def proxy_association
  @association
end

def reload

# => [#]
person.pets(true) # fetches pets from the database

# => [#]
person.pets.reload # fetches pets from the database

# => [#]
person.pets # uses the pets cache

# => [#]
person.pets # fetches pets from the database

end
has_many :pets
class Person < ActiveRecord::Base

Equivalent to collection(true).
Reloads the collection from the database. Returns +self+.
def reload
  proxy_association.reload
  self
end

def replace(other_array)

# => ActiveRecord::AssociationTypeMismatch: Pet expected, got String
person.pets.replace(["doo", "ggie", "gaga"])

an ActiveRecord::AssociationTypeMismatch error:
If the supplied array has an incorrect association type, it raises

# => [#]
person.pets

person.pets.replace(other_pets)

other_pets = [Pet.new(name: 'Puff', group: 'celebrities']

# => [#]
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

and delete/add only records that have changed.
Replaces this collection with +other_array+. This will perform a diff
def replace(other_array)
  @association.replace(other_array)
end

def scope

Returns a Relation object for the records in this association
def scope
  @association.scope
end

def scoping

delegates to @association, and so on.
method, which gets the current scope, which is this object, which
that could create an infinite loop where we call an @association
We don't want this object to be put on the scoping stack, because
def scoping
  @association.scope.scoping { yield }
end

def select(select = nil, &block)

# ]
# #
# #,
# => [
person.pets.select(:name) { |pet| pet.name =~ /oo/ }

# ]
# #
# #,
# => [
person.pets.select { |pet| pet.name =~ /oo/ }

Array#select.
converting them into an array and iterating through them using
This builds an array of objects from the database for the scope,
*Second:* You can pass a block so it can be used just like Array#select.

# => ActiveModel::MissingAttributeError: missing attribute: person_id
person.pets.select(:name).first.person_id

receive:
to access a field that is not in the initialized record you'll
object with only the fields that you've selected. If you attempt
Be careful because this also means you're initializing a model

# ]
# #
# #,
# #,
# => [
person.pets.select([:id, :name])

# ]
# #
# #,
# #,
# => [
person.pets.select(:name)

# ]
# #
# #,
# #,
# => [
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

*First:* Specify a subset of fields to be selected from the result set.

Works in two ways.
def select(select = nil, &block)
  @association.select(select, &block)
end

def size

# collection.size and no SQL count query is executed.
# Because the collection is already loaded, this will behave like
person.pets.size # => 3

# ]
# #
# #,
# #,
# => [
person.pets # This will execute a SELECT * FROM query

# executes something like SELECT COUNT(*) FROM "pets" WHERE "pets"."person_id" = 1
person.pets.size # => 3

end
has_many :pets
class Person < ActiveRecord::Base

+length+ will take one less query. Otherwise +size+ is more efficient.
equivalent. If not and you are going to need the records anyway
If the collection has been already loaded +size+ and +length+ are

it executes a SELECT COUNT(*) query. Else it calls collection.size.
Returns the size of the collection. If the collection hasn't been loaded,
def size
  @association.size
end

def target

def target
  @association.target
end

def to_ary

# ]
# #
# #,
# #,
# => [
# This is not affected by replace
person.pets

# => [#]
other_pets

other_pets.replace([Pet.new(name: 'BooGoo')])

# ]
# #
# #,
# #,
# => [
other_pets = person.pets.to_ary

# ]
# #
# #,
# #,
# => [
person.pets

end
has_many :pets
class Person < ActiveRecord::Base

hasn't been loaded, it fetches the records from the database.
Returns a new array of objects from the collection. If the collection
def to_ary
  load_target.dup
end