class ActiveRecord::Associations::CollectionProxy

Association proxies in Active Record are middlemen between the object that holds the association, known as the @owner, and the actual associated object, known as the @target. The kind of association any proxy is about is available in @reflection. That's an instance of the class ActiveRecord::Reflection::AssociationReflection.

For example, given

class Blog < ActiveRecord::Base
  has_many :posts
end

blog = Blog.first

the association proxy in blog.posts has the object in blog as @owner, the collection of its posts as @target, and the @reflection object represents a :has_many macro.

This class delegates unknown methods to @target via method_missing.

The @target object is not loaded until needed. For example,

blog.posts.count

is computed directly through SQL and does not trigger by itself the instantiation of the actual post records.

Public Instance Methods

<<(*records) click to toggle source

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.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.size # => 0
person.pets << Pet.new(name: 'Fancy-Fancy')
person.pets << [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>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 969
def <<(*records)
  proxy_association.concat(records) && self
end
Also aliased as: push, append
==(other) click to toggle source

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

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets
# => [
#      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
#      #<Pet id: 2, name: "Spook", person_id: 1>
#    ]

other = person.pets.to_ary

person.pets == other
# => true

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

person.pets == other
# => false
# File lib/active_record/associations/collection_proxy.rb, line 907
def ==(other)
  load_target == other
end
any?(&block) click to toggle source

Returns true if the collection is not empty.

class Person < ActiveRecord::Base
  has_many :pets
end

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

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

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

person.pets
# => [#<Pet name: "Snoop", group: "dogs">]

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

person.pets.any? do |pet|
  pet.group == 'dogs'
end
# => true
# File lib/active_record/associations/collection_proxy.rb, line 805
def any?(&block)
  @association.any?(&block)
end
append(*records)
Alias for: <<
arel() click to toggle source
# File lib/active_record/associations/collection_proxy.rb, line 861
def arel
  scope.arel
end
build(attributes = {}, &block) click to toggle source

Returns a new object of the collection type that has been instantiated with attributes and linked to this object, but have not yet been saved. You can pass an array of attributes hashes, this will return an array with the new objects.

class Person
  has_many :pets
end

person.pets.build
# => #<Pet id: nil, name: nil, person_id: 1>

person.pets.build(name: 'Fancy-Fancy')
# => #<Pet id: nil, name: "Fancy-Fancy", person_id: 1>

person.pets.build([{name: 'Spook'}, {name: 'Choo-Choo'}, {name: 'Brain'}])
# => [
#      #<Pet id: nil, name: "Spook", person_id: 1>,
#      #<Pet id: nil, name: "Choo-Choo", person_id: 1>,
#      #<Pet id: nil, name: "Brain", person_id: 1>
#    ]

person.pets.size  # => 5 # size of the collection
person.pets.count # => 0 # count from database
# File lib/active_record/associations/collection_proxy.rb, line 258
def build(attributes = {}, &block)
  @association.build(attributes, &block)
end
Also aliased as: new
clear() click to toggle source

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

# File lib/active_record/associations/collection_proxy.rb, line 982
def clear
  delete_all
  self
end
concat(*records) click to toggle source

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
# File lib/active_record/associations/collection_proxy.rb, line 333
def concat(*records)
  @association.concat(*records)
end
count(column_name = nil, options = {}) click to toggle source

Count all records using SQL.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.count # => 3
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>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 696
def count(column_name = nil, options = {})
  # TODO: Remove options argument as soon we remove support to
  # activerecord-deprecated_finders.
  @association.count(column_name, options)
end
create(attributes = {}, &block) click to toggle source

Returns a new object of the collection type that has been instantiated with attributes, linked to this object and that has already been saved (if it passes the validations).

class Person
  has_many :pets
end

person.pets.create(name: 'Fancy-Fancy')
# => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>

person.pets.create([{name: 'Spook'}, {name: 'Choo-Choo'}])
# => [
#      #<Pet id: 2, name: "Spook", person_id: 1>,
#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

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

person.pets.find(1, 2, 3)
# => [
#       #<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>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 289
def create(attributes = {}, &block)
  @association.create(attributes, &block)
end
create!(attributes = {}, &block) click to toggle source

Like create, except that if the record is invalid, raises an exception.

class Person
  has_many :pets
end

class Pet
  validates :name, presence: true
end

person.pets.create!(name: nil)
# => ActiveRecord::RecordInvalid: Validation failed: Name can't be blank
# File lib/active_record/associations/collection_proxy.rb, line 305
def create!(attributes = {}, &block)
  @association.create!(attributes, &block)
end
delete(*records) click to toggle source

Deletes the records supplied from the collection according to the strategy specified by the :dependent option. If no :dependent option is given, then it will follow the default strategy. Returns an array with the deleted records.

For +has_many :through+ associations, the default deletion strategy is :delete_all.

For has_many associations, the default deletion strategy is :nullify. This sets the foreign keys to NULL.

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

person.pets.size # => 3
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.delete(Pet.find(1))
# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]

person.pets.size # => 2
person.pets
# => [
#       #<Pet id: 2, name: "Spook", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

Pet.find(1)
# => #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>

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

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

person.pets.size # => 3
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.delete(Pet.find(1), Pet.find(3))
# => [
#       #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

person.pets.size # => 1
person.pets
# => [#<Pet id: 2, name: "Spook", person_id: 1>]

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

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

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

person.pets.size # => 3
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.delete(Pet.find(1))
# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]

person.pets.size # => 2
person.pets
# => [
#       #<Pet id: 2, name: "Spook", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

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

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

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.size # => 3
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.delete("1")
# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]

person.pets.delete(2, 3)
# => [
#       #<Pet id: 2, name: "Spook", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 588
def delete(*records)
  @association.delete(*records)
end
delete_all(dependent = nil) click to toggle source

Deletes all the records from the collection according to the strategy specified by the :dependent option. If no :dependent option is given, then it will follow the default strategy.

For +has_many :through+ associations, the default deletion strategy is :delete_all.

For has_many associations, the default deletion strategy is :nullify. This sets the foreign keys to NULL.

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

person.pets.size # => 3
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.delete_all
# => [
#       #<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.size # => 0
person.pets      # => []

Pet.find(1, 2, 3)
# => [
#       #<Pet id: 1, name: "Fancy-Fancy", person_id: nil>,
#       #<Pet id: 2, name: "Spook", person_id: nil>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: nil>
#    ]

Both has_many and +has_many :through+ dependencies default to the :delete_all strategy if the :dependent option is set to :destroy. Records are not instantiated and callbacks will not be fired.

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

person.pets.size # => 3
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.delete_all

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

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

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

person.pets.size # => 3
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.delete_all

Pet.find(1, 2, 3)
# => ActiveRecord::RecordNotFound
# File lib/active_record/associations/collection_proxy.rb, line 442
def delete_all(dependent = nil)
  @association.delete_all(dependent)
end
destroy(*records) click to toggle source

Destroys the records supplied and removes them from the collection. This method will always remove record from the database ignoring the :dependent option. Returns an array with the removed records.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.size # => 3
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.destroy(Pet.find(1))
# => [#<Pet id: 1, name: "Fancy-Fancy", person_id: 1>]

person.pets.size # => 2
person.pets
# => [
#       #<Pet id: 2, name: "Spook", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

person.pets.destroy(Pet.find(2), Pet.find(3))
# => [
#       #<Pet id: 2, name: "Spook", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

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

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

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

person.pets.size # => 3
person.pets
# => [
#       #<Pet id: 4, name: "Benny", person_id: 1>,
#       #<Pet id: 5, name: "Brain", person_id: 1>,
#       #<Pet id: 6, name: "Boss",  person_id: 1>
#    ]

person.pets.destroy("4")
# => #<Pet id: 4, name: "Benny", person_id: 1>

person.pets.size # => 2
person.pets
# => [
#       #<Pet id: 5, name: "Brain", person_id: 1>,
#       #<Pet id: 6, name: "Boss",  person_id: 1>
#    ]

person.pets.destroy(5, 6)
# => [
#       #<Pet id: 5, name: "Brain", person_id: 1>,
#       #<Pet id: 6, name: "Boss",  person_id: 1>
#    ]

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

Pet.find(4, 5, 6) # => ActiveRecord::RecordNotFound: Couldn't find all Pets with IDs (4, 5, 6)
# File lib/active_record/associations/collection_proxy.rb, line 660
def destroy(*records)
  @association.destroy(*records)
end
destroy_all() click to toggle source

Deletes the records of the collection directly from the database ignoring the :dependent option. Records are instantiated and it invokes before_remove, after_remove , before_destroy and after_destroy callbacks.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.size # => 3
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.destroy_all

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

Pet.find(1) # => Couldn't find Pet with id=1
# File lib/active_record/associations/collection_proxy.rb, line 469
def destroy_all
  @association.destroy_all
end
distinct() click to toggle source

Specifies whether the records should be unique or not.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.select(:name)
# => [
#      #<Pet name: "Fancy-Fancy">,
#      #<Pet name: "Fancy-Fancy">
#    ]

person.pets.select(:name).distinct
# => [#<Pet name: "Fancy-Fancy">]
# File lib/active_record/associations/collection_proxy.rb, line 678
def distinct
  @association.distinct
end
Also aliased as: uniq
empty?() click to toggle source

Returns true if the collection is empty. If the collection has been loaded it is equivalent to collection.size.zero?. If the collection has not been loaded, it is equivalent to collection.exists?. If the collection has not already been loaded and you are going to fetch the records anyway it is better to check collection.length.zero?.

class Person < ActiveRecord::Base
  has_many :pets
end

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

person.pets.delete_all

person.pets.count  # => 0
person.pets.empty? # => true
# File lib/active_record/associations/collection_proxy.rb, line 772
def empty?
  @association.empty?
end
fifth(*args) click to toggle source

Same as first except returns only the fifth record.

# File lib/active_record/associations/collection_proxy.rb, line 190
def fifth(*args)
  @association.fifth(*args)
end
find(*args, &block) click to toggle source

Finds an object in the collection responding to the id. Uses the same rules as ActiveRecord::Base.find. Returns ActiveRecord::RecordNotFound error if the object cannot be found.

class Person < ActiveRecord::Base
  has_many :pets
end

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.find(1) # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>
person.pets.find(4) # => ActiveRecord::RecordNotFound: Couldn't find Pet with id=4

person.pets.find(2) { |pet| pet.name.downcase! }
# => #<Pet id: 2, name: "fancy-fancy", person_id: 1>

person.pets.find(2, 3)
# => [
#       #<Pet id: 2, name: "Spook", person_id: 1>,
#       #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 140
def find(*args, &block)
  @association.find(*args, &block)
end
first(*args) click to toggle source

Returns the first record, or the first n records, from the collection. If the collection is empty, the first form returns nil, and the second form returns an empty array.

class Person < ActiveRecord::Base
  has_many :pets
end

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.first # => #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>

person.pets.first(2)
# => [
#      #<Pet id: 1, name: "Fancy-Fancy", person_id: 1>,
#      #<Pet id: 2, name: "Spook", person_id: 1>
#    ]

another_person_without.pets          # => []
another_person_without.pets.first    # => nil
another_person_without.pets.first(3) # => []
# File lib/active_record/associations/collection_proxy.rb, line 170
def first(*args)
  @association.first(*args)
end
forty_two(*args) click to toggle source

Same as first except returns only the forty second record. Also known as accessing “the reddit”.

# File lib/active_record/associations/collection_proxy.rb, line 196
def forty_two(*args)
  @association.forty_two(*args)
end
fourth(*args) click to toggle source

Same as first except returns only the fourth record.

# File lib/active_record/associations/collection_proxy.rb, line 185
def fourth(*args)
  @association.fourth(*args)
end
include?(record) click to toggle source

Returns true if the given record is present in the collection.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets # => [#<Pet id: 20, name: "Snoop">]

person.pets.include?(Pet.find(20)) # => true
person.pets.include?(Pet.find(21)) # => false
# File lib/active_record/associations/collection_proxy.rb, line 857
def include?(record)
  !!@association.include?(record)
end
last(*args) click to toggle source

Returns the last record, or the last n records, from the collection. If the collection is empty, the first form returns nil, and the second form returns an empty array.

class Person < ActiveRecord::Base
  has_many :pets
end

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.last # => #<Pet id: 3, name: "Choo-Choo", person_id: 1>

person.pets.last(2)
# => [
#      #<Pet id: 2, name: "Spook", person_id: 1>,
#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

another_person_without.pets         # => []
another_person_without.pets.last    # => nil
another_person_without.pets.last(3) # => []
# File lib/active_record/associations/collection_proxy.rb, line 226
def last(*args)
  @association.last(*args)
end
length() click to toggle source

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

class Person < ActiveRecord::Base
  has_many :pets
end

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

# Because the collection is loaded, you can
# call the collection with no additional queries:
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>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 750
def length
  @association.length
end
load_target() click to toggle source
# File lib/active_record/associations/collection_proxy.rb, line 44
def load_target
  @association.load_target
end
loaded?() click to toggle source

Returns true if the association has been loaded, otherwise false.

person.pets.loaded? # => false
person.pets
person.pets.loaded? # => true
# File lib/active_record/associations/collection_proxy.rb, line 53
def loaded?
  @association.loaded?
end
many?(&block) click to toggle source

Returns true if the collection has more than one record. Equivalent to collection.size > 1.

class Person < ActiveRecord::Base
  has_many :pets
end

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

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

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

person.pets
# => [
#      #<Pet name: "Gorby", group: "cats">,
#      #<Pet name: "Puff", group: "cats">,
#      #<Pet name: "Snoop", group: "dogs">
#    ]

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

person.pets.many? do |pet|
  pet.group == 'cats'
end
# => true
# File lib/active_record/associations/collection_proxy.rb, line 843
def many?(&block)
  @association.many?(&block)
end
new(attributes = {}, &block)
Alias for: build
prepend(*args) click to toggle source
# File lib/active_record/associations/collection_proxy.rb, line 975
def prepend(*args)
  raise NoMethodError, "prepend on association is not defined. Please use << or append"
end
proxy_association() click to toggle source
# File lib/active_record/associations/collection_proxy.rb, line 865
def proxy_association
  @association
end
push(*records)
Alias for: <<
reload() click to toggle source

Reloads the collection from the database. Returns self. Equivalent to collection(true).

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets # fetches pets from the database
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]

person.pets # uses the pets cache
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]

person.pets.reload # fetches pets from the database
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]

person.pets(true)  # fetches pets from the database
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
# File lib/active_record/associations/collection_proxy.rb, line 1005
def reload
  proxy_association.reload
  self
end
replace(other_array) click to toggle source

Replaces this collection with other_array. This will perform a diff and delete/add only records that have changed.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets
# => [#<Pet id: 1, name: "Gorby", group: "cats", person_id: 1>]

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

person.pets.replace(other_pets)

person.pets
# => [#<Pet id: 2, name: "Puff", group: "celebrities", person_id: 1>]

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

person.pets.replace(["doo", "ggie", "gaga"])
# => ActiveRecord::AssociationTypeMismatch: Pet expected, got String
# File lib/active_record/associations/collection_proxy.rb, line 359
def replace(other_array)
  @association.replace(other_array)
end
reset() click to toggle source

Unloads the association. Returns self.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets # fetches pets from the database
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]

person.pets # uses the pets cache
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]

person.pets.reset # clears the pets cache

person.pets  # fetches pets from the database
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
# File lib/active_record/associations/collection_proxy.rb, line 1026
def reset
  proxy_association.reset
  proxy_association.reset_scope
  self
end
scope() click to toggle source

Returns a Relation object for the records in this association

# File lib/active_record/associations/collection_proxy.rb, line 878
def scope
  @association.scope
end
Also aliased as: spawn
scoping() { || ... } click to toggle source

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.

# File lib/active_record/associations/collection_proxy.rb, line 873
def scoping
  @association.scope.scoping { yield }
end
second(*args) click to toggle source

Same as first except returns only the second record.

# File lib/active_record/associations/collection_proxy.rb, line 175
def second(*args)
  @association.second(*args)
end
select(*fields, &block) click to toggle source

Works in two ways.

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

class Person < ActiveRecord::Base
  has_many :pets
end

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.select(:name)
# => [
#      #<Pet id: nil, name: "Fancy-Fancy">,
#      #<Pet id: nil, name: "Spook">,
#      #<Pet id: nil, name: "Choo-Choo">
#    ]

person.pets.select(:id, :name )
# => [
#      #<Pet id: 1, name: "Fancy-Fancy">,
#      #<Pet id: 2, name: "Spook">,
#      #<Pet id: 3, name: "Choo-Choo">
#    ]

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

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

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

person.pets.select { |pet| pet.name =~ /oo/ }
# => [
#      #<Pet id: 2, name: "Spook", person_id: 1>,
#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]

person.pets.select(:name) { |pet| pet.name =~ /oo/ }
# => [
#      #<Pet id: 2, name: "Spook">,
#      #<Pet id: 3, name: "Choo-Choo">
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 110
def select(*fields, &block)
  @association.select(*fields, &block)
end
size() click to toggle source

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

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

class Person < ActiveRecord::Base
  has_many :pets
end

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

person.pets # This will execute a SELECT * FROM query
# => [
#       #<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.size # => 3
# Because the collection is already loaded, this will behave like
# collection.size and no SQL count query is executed.
# File lib/active_record/associations/collection_proxy.rb, line 726
def size
  @association.size
end
spawn()
Alias for: scope
take(n = nil) click to toggle source
# File lib/active_record/associations/collection_proxy.rb, line 230
def take(n = nil)
  @association.take(n)
end
target() click to toggle source
# File lib/active_record/associations/collection_proxy.rb, line 40
def target
  @association.target
end
third(*args) click to toggle source

Same as first except returns only the third record.

# File lib/active_record/associations/collection_proxy.rb, line 180
def third(*args)
  @association.third(*args)
end
to_a()
Alias for: to_ary
to_ary() click to toggle source

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

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets
# => [
#       #<Pet id: 4, name: "Benny", person_id: 1>,
#       #<Pet id: 5, name: "Brain", person_id: 1>,
#       #<Pet id: 6, name: "Boss",  person_id: 1>
#    ]

other_pets = person.pets.to_ary
# => [
#       #<Pet id: 4, name: "Benny", person_id: 1>,
#       #<Pet id: 5, name: "Brain", person_id: 1>,
#       #<Pet id: 6, name: "Boss",  person_id: 1>
#    ]

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

other_pets
# => [#<Pet id: nil, name: "BooGoo", person_id: 1>]

person.pets
# This is not affected by replace
# => [
#       #<Pet id: 4, name: "Benny", person_id: 1>,
#       #<Pet id: 5, name: "Brain", person_id: 1>,
#       #<Pet id: 6, name: "Boss",  person_id: 1>
#    ]
# File lib/active_record/associations/collection_proxy.rb, line 944
def to_ary
  load_target.dup
end
Also aliased as: to_a
uniq()
Alias for: distinct