Class: ActiveRecord::Associations::CollectionProxy

Inherits:
Relation
  • Object
show all
Defined in:
lib/active_record/associations/collection_proxy.rb

Overview

Collection proxies in Active Record are middlemen between an association, and its target result set.

For example, given

class Blog < ActiveRecord::Base
  has_many :posts
end

blog = Blog.first

The collection proxy returned by blog.posts is built from a :has_many association, and delegates to a collection of posts as the target.

This class delegates unknown methods to the association‘s relation class via a delegate cache.

The target result set 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.

Constant Summary

Constants inherited from Relation

Relation::CLAUSE_METHODS, Relation::INVALID_METHODS_FOR_DELETE_ALL, Relation::MULTI_VALUE_METHODS, Relation::SINGLE_VALUE_METHODS, Relation::VALUE_METHODS

Constants included from FinderMethods

FinderMethods::ONE_AS_ONE

Constants included from QueryMethods

QueryMethods::FROZEN_EMPTY_ARRAY, QueryMethods::FROZEN_EMPTY_HASH, QueryMethods::VALID_UNSCOPING_VALUES

Constants included from Batches

Batches::ORDER_IGNORE_MESSAGE

Instance Attribute Summary

Attributes inherited from Relation

#_deprecated_scope_source, #klass, #loaded, #predicate_builder, #skip_preloading_value, #table

Instance Method Summary collapse

Methods inherited from Relation

#_exec_scope, #alias_tracker, #any?, #arel_attribute, #bind_attribute, #blank?, #cache_key, #cache_key_with_version, #cache_version, #create_or_find_by, #create_or_find_by!, #delete_by, #destroy_by, #eager_loading?, #empty_scope?, #encode_with, #explain, #find_or_create_by, #find_or_create_by!, #find_or_initialize_by, #first_or_create, #first_or_create!, #first_or_initialize, #has_limit_or_offset?, #initialize_copy, #inspect, #joined_includes_values, #load, #many?, #none?, #one?, #preload_associations, #pretty_print, #scope_for_create, #scoping, #to_ary, #to_sql, #touch_all, #update, #update_all, #update_counters, #values, #where_values_hash

Methods included from FinderMethods

#exists?, #fifth, #fifth!, #find_by, #find_by!, #first, #first!, #forty_two, #forty_two!, #fourth, #fourth!, #last!, #raise_record_not_found_exception!, #second, #second!, #second_to_last, #second_to_last!, #take!, #third, #third!, #third_to_last, #third_to_last!

Methods included from Calculations

#average, #count, #ids, #maximum, #minimum, #pick, #sum

Methods included from SpawnMethods

#except, #merge, #merge!, #only, #spawn

Methods included from QueryMethods

#_select!, #annotate, #annotate!, #arel, #construct_join_dependency, #create_with, #create_with!, #distinct, #distinct!, #eager_load, #eager_load!, #extending, #extending!, #extract_associated, #from, #from!, #group, #group!, #having, #having!, #includes, #includes!, #joins, #joins!, #left_outer_joins, #left_outer_joins!, #limit, #limit!, #lock, #lock!, #none, #none!, #offset, #offset!, #optimizer_hints, #optimizer_hints!, #or, #or!, #order, #order!, #preload, #preload!, #readonly, #readonly!, #references, #references!, #reorder, #reorder!, #reselect, #reselect!, #reverse_order, #reverse_order!, #rewhere, #select, #skip_preloading!, #skip_query_cache!, #unscope, #unscope!, #where, #where!

Methods included from Batches

#find_each, #find_in_batches, #in_batches

Methods included from Explain

#collecting_queries_for_explain, #exec_explain

Constructor Details

#initialize(klass, association) ⇒ CollectionProxy

:nodoc:



30
31
32
33
34
35
36
# File 'lib/active_record/associations/collection_proxy.rb', line 30

def initialize(klass, association, **) #:nodoc:
  @association = association
  super klass

  extensions = association.extensions
  extend(*extensions) if extensions.any?
end

Instance Method Details

#<<(*records) ⇒ Object Also known as: push, append, concat

Adds 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 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>
#    ]


1025
1026
1027
# File 'lib/active_record/associations/collection_proxy.rb', line 1025

def <<(*records)
  proxy_association.concat(records) && self
end

#==(other) ⇒ Object

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


956
957
958
# File 'lib/active_record/associations/collection_proxy.rb', line 956

def ==(other)
  load_target == other
end

#build(attributes = {}, &block) ⇒ Object Also known as: new

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


315
316
317
# File 'lib/active_record/associations/collection_proxy.rb', line 315

def build(attributes = {}, &block)
  @association.build(attributes, &block)
end

#calculate(operation, column_name) ⇒ Object



721
722
723
# File 'lib/active_record/associations/collection_proxy.rb', line 721

def calculate(operation, column_name)
  null_scope? ? scope.calculate(operation, column_name) : super
end

#clearObject

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. Note that because delete_all removes records by directly running an SQL query into the database, the updated_at column of the object is not changed.



1042
1043
1044
1045
# File 'lib/active_record/associations/collection_proxy.rb', line 1042

def clear
  delete_all
  self
end

#create(attributes = {}, &block) ⇒ Object

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>
#    ]


346
347
348
# File 'lib/active_record/associations/collection_proxy.rb', line 346

def create(attributes = {}, &block)
  @association.create(attributes, &block)
end

#create!(attributes = {}, &block) ⇒ Object

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


362
363
364
# File 'lib/active_record/associations/collection_proxy.rb', line 362

def create!(attributes = {}, &block)
  @association.create!(attributes, &block)
end

#delete(*records) ⇒ Object

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 'id': (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 Integer 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>
#    ]


617
618
619
# File 'lib/active_record/associations/collection_proxy.rb', line 617

def delete(*records)
  @association.delete(*records).tap { reset_scope }
end

#delete_all(dependent = nil) ⇒ Object

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: Couldn't find all Pets with 'id': (1, 2, 3)

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: Couldn't find all Pets with 'id': (1, 2, 3)


471
472
473
# File 'lib/active_record/associations/collection_proxy.rb', line 471

def delete_all(dependent = nil)
  @association.delete_all(dependent).tap { reset_scope }
end

#destroy(*records) ⇒ Object

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 'id': (1, 2, 3)

You can pass Integer 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 'id': (4, 5, 6)


689
690
691
# File 'lib/active_record/associations/collection_proxy.rb', line 689

def destroy(*records)
  @association.destroy(*records).tap { reset_scope }
end

#destroy_allObject

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


498
499
500
# File 'lib/active_record/associations/collection_proxy.rb', line 498

def destroy_all
  @association.destroy_all.tap { reset_scope }
end

#empty?Boolean

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

Returns:

  • (Boolean)


828
829
830
# File 'lib/active_record/associations/collection_proxy.rb', line 828

def empty?
  @association.empty?
end

#find(*args) ⇒ Object

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>
#    ]


135
136
137
138
# File 'lib/active_record/associations/collection_proxy.rb', line 135

def find(*args)
  return super if block_given?
  @association.find(*args)
end

#include?(record) ⇒ Boolean

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

Returns:

  • (Boolean)


919
920
921
# File 'lib/active_record/associations/collection_proxy.rb', line 919

def include?(record)
  !!@association.include?(record)
end

#last(limit = nil) ⇒ Object

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) # => []


256
257
258
259
# File 'lib/active_record/associations/collection_proxy.rb', line 256

def last(limit = nil)
  load_target if find_from_target?
  super
end

#load_targetObject



42
43
44
# File 'lib/active_record/associations/collection_proxy.rb', line 42

def load_target
  @association.load_target
end

#loaded?Boolean

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

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

Returns:

  • (Boolean)


51
52
53
# File 'lib/active_record/associations/collection_proxy.rb', line 51

def loaded?
  @association.loaded?
end

#pluck(*column_names) ⇒ Object



725
726
727
# File 'lib/active_record/associations/collection_proxy.rb', line 725

def pluck(*column_names)
  null_scope? ? scope.pluck(*column_names) : super
end

#prepend(*args) ⇒ Object

:nodoc:

Raises:

  • (NoMethodError)


1032
1033
1034
# File 'lib/active_record/associations/collection_proxy.rb', line 1032

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

#proxy_associationObject



923
924
925
# File 'lib/active_record/associations/collection_proxy.rb', line 923

def proxy_association
  @association
end

#recordsObject

:method: to_ary

:call-seq:

to_ary()

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>
#    ]


1000
1001
1002
# File 'lib/active_record/associations/collection_proxy.rb', line 1000

def records # :nodoc:
  load_target
end

#reloadObject

Reloads the collection from the database. 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.reload # fetches pets from the database
# => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]


1061
1062
1063
1064
# File 'lib/active_record/associations/collection_proxy.rb', line 1061

def reload
  proxy_association.reload(true)
  reset_scope
end

#replace(other_array) ⇒ Object

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


388
389
390
# File 'lib/active_record/associations/collection_proxy.rb', line 388

def replace(other_array)
  @association.replace(other_array)
end

#resetObject

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>]


1082
1083
1084
1085
1086
# File 'lib/active_record/associations/collection_proxy.rb', line 1082

def reset
  proxy_association.reset
  proxy_association.reset_scope
  reset_scope
end

#reset_scopeObject

:nodoc:



1088
1089
1090
1091
1092
# File 'lib/active_record/associations/collection_proxy.rb', line 1088

def reset_scope # :nodoc:
  @offsets = {}
  @scope = nil
  self
end

#scopeObject

Returns a Relation object for the records in this association



928
929
930
# File 'lib/active_record/associations/collection_proxy.rb', line 928

def scope
  @scope ||= @association.scope
end

#sizeObject

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.


779
780
781
# File 'lib/active_record/associations/collection_proxy.rb', line 779

def size
  @association.size
end

#take(limit = nil) ⇒ Object

Gives a record (or N records if a parameter is supplied) from the collection using the same rules as ActiveRecord::Base.take.

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

person.pets.take(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.take    # => nil
another_person_without.pets.take(2) # => []


286
287
288
289
# File 'lib/active_record/associations/collection_proxy.rb', line 286

def take(limit = nil)
  load_target if find_from_target?
  super
end

#targetObject



38
39
40
# File 'lib/active_record/associations/collection_proxy.rb', line 38

def target
  @association.target
end