Class: ActiveRecord::Associations::CollectionProxy
- Defined in:
- lib/active_record/associations/collection_proxy.rb
Overview
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.
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
Constants included from QueryMethods
QueryMethods::FROZEN_EMPTY_ARRAY, QueryMethods::FROZEN_EMPTY_HASH, QueryMethods::VALID_UNSCOPING_VALUES
Constants included from Batches
Batches::ORDER_OR_LIMIT_IGNORED_MESSAGE
Instance Attribute Summary
Attributes inherited from Relation
#klass, #loaded, #predicate_builder, #table
Instance Method Summary collapse
-
#<<(*records) ⇒ Object
(also: #push, #append)
Adds one or more
recordsto the collection by setting their foreign keys to the association’s primary key. -
#==(other) ⇒ Object
Equivalent to
Array#==. -
#any?(&block) ⇒ Boolean
Returns
trueif the collection is not empty. -
#build(attributes = {}, &block) ⇒ Object
(also: #new)
Returns a new object of the collection type that has been instantiated with
attributesand linked to this object, but have not yet been saved. - #calculate(operation, column_name) ⇒ Object
-
#clear ⇒ Object
Equivalent to
delete_all. -
#concat(*records) ⇒ Object
Add one or more records to the collection by setting their foreign keys to the association’s primary key.
-
#count(column_name = nil) ⇒ Object
Count all records using SQL.
-
#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).
-
#create!(attributes = {}, &block) ⇒ Object
Like #create, except that if the record is invalid, raises an exception.
-
#delete(*records) ⇒ Object
Deletes the
recordssupplied from the collection according to the strategy specified by the:dependentoption. -
#delete_all(dependent = nil) ⇒ Object
Deletes all the records from the collection according to the strategy specified by the
:dependentoption. -
#destroy(*records) ⇒ Object
Destroys the
recordssupplied and removes them from the collection. -
#destroy_all ⇒ Object
Deletes the records of the collection directly from the database ignoring the
:dependentoption. -
#distinct ⇒ Object
(also: #uniq)
Specifies whether the records should be unique or not.
-
#empty? ⇒ Boolean
Returns
trueif the collection is empty. -
#fifth(*args) ⇒ Object
Same as #first except returns only the fifth record.
-
#find(*args, &block) ⇒ Object
Finds an object in the collection responding to the
id. -
#first(*args) ⇒ Object
Returns the first record, or the first
nrecords, from the collection. -
#forty_two(*args) ⇒ Object
Same as #first except returns only the forty second record.
-
#fourth(*args) ⇒ Object
Same as #first except returns only the fourth record.
-
#include?(record) ⇒ Boolean
Returns
trueif the givenrecordis present in the collection. -
#initialize(klass, association) ⇒ CollectionProxy
constructor
:nodoc:.
-
#last(*args) ⇒ Object
Returns the last record, or the last
nrecords, from the collection. -
#length ⇒ Object
Returns the size of the collection calling
sizeon the target. - #load_target ⇒ Object
-
#loaded? ⇒ Boolean
Returns
trueif the association has been loaded, otherwisefalse. -
#many?(&block) ⇒ Boolean
Returns true if the collection has more than one record.
- #pluck(*column_names) ⇒ Object
- #prepend(*args) ⇒ Object
- #proxy_association ⇒ Object
-
#records ⇒ Object
:nodoc:.
-
#reload ⇒ Object
Reloads the collection from the database.
-
#replace(other_array) ⇒ Object
Replaces this collection with
other_array. -
#reset ⇒ Object
Unloads the association.
-
#reset_scope ⇒ Object
:nodoc:.
-
#scope ⇒ Object
Returns a
Relationobject for the records in this association. -
#second(*args) ⇒ Object
Same as #first except returns only the second record.
-
#second_to_last(*args) ⇒ Object
Same as #first except returns only the second-to-last record.
-
#select(*fields, &block) ⇒ Object
Works in two ways.
-
#size ⇒ Object
Returns the size of the collection.
-
#take(n = nil) ⇒ Object
Gives a record (or N records if a parameter is supplied) from the collection using the same rules as
ActiveRecord::Base.take. - #target ⇒ Object
-
#third(*args) ⇒ Object
Same as #first except returns only the third record.
-
#third_to_last(*args) ⇒ Object
Same as #first except returns only the third-to-last record.
-
#to_ary ⇒ Object
(also: #to_a)
Returns a new array of objects from the collection.
Methods inherited from Relation
#_update_record, #arel_attribute, #as_json, #blank?, #cache_key, #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, #initialize_copy, #insert, #inspect, #joined_includes_values, #load, #none?, #one?, #pretty_print, #scope_for_create, #scoping, #substitute_values, #to_sql, #uniq_value, #update, #update_all, #values, #where_values_hash
Methods included from FinderMethods
#exists?, #fifth!, #find_by, #find_by!, #first!, #forty_two!, #fourth!, #last!, #raise_record_not_found_exception!, #second!, #second_to_last!, #take!, #third!, #third_to_last!
Methods included from Calculations
#average, #ids, #maximum, #minimum, #sum
Methods included from SpawnMethods
#except, #merge, #merge!, #only, #spawn
Methods included from QueryMethods
#_select!, #arel, #bound_attributes, #create_with, #create_with!, #create_with_value, #distinct!, #eager_load, #eager_load!, #extending, #extending!, #from, #from!, #group, #group!, #having, #having!, #includes, #includes!, #joins, #joins!, #left_outer_joins, #left_outer_joins!, #limit, #limit!, #lock, #lock!, #none, #none!, #offset, #offset!, #or, #or!, #order, #order!, #preload, #preload!, #readonly, #readonly!, #references, #references!, #reorder, #reorder!, #reverse_order, #reverse_order!, #rewhere, #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
Methods included from Delegation
Constructor Details
#initialize(klass, association) ⇒ CollectionProxy
:nodoc:
31 32 33 34 35 36 37 |
# File 'lib/active_record/associations/collection_proxy.rb', line 31 def initialize(klass, association) #:nodoc: @association = association super klass, klass.arel_table, klass.predicate_builder extensions = association.extensions extend(*extensions) if extensions.any? end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class ActiveRecord::Delegation
Instance Method Details
#<<(*records) ⇒ Object Also known as: push, append
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>
# ]
1000 1001 1002 |
# File 'lib/active_record/associations/collection_proxy.rb', line 1000 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
934 935 936 |
# File 'lib/active_record/associations/collection_proxy.rb', line 934 def ==(other) load_target == other end |
#any?(&block) ⇒ Boolean
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 # => 1
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
845 846 847 |
# File 'lib/active_record/associations/collection_proxy.rb', line 845 def any?(&block) @association.any?(&block) 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
292 293 294 |
# File 'lib/active_record/associations/collection_proxy.rb', line 292 def build(attributes = {}, &block) @association.build(attributes, &block) end |
#calculate(operation, column_name) ⇒ Object
734 735 736 |
# File 'lib/active_record/associations/collection_proxy.rb', line 734 def calculate(operation, column_name) null_scope? ? scope.calculate(operation, column_name) : super end |
#clear ⇒ Object
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.
1016 1017 1018 1019 |
# File 'lib/active_record/associations/collection_proxy.rb', line 1016 def clear delete_all self end |
#concat(*records) ⇒ Object
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
367 368 369 |
# File 'lib/active_record/associations/collection_proxy.rb', line 367 def concat(*records) @association.concat(*records) end |
#count(column_name = nil) ⇒ Object
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>
# ]
730 731 732 |
# File 'lib/active_record/associations/collection_proxy.rb', line 730 def count(column_name = nil) @association.count(column_name) 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>
# ]
323 324 325 |
# File 'lib/active_record/associations/collection_proxy.rb', line 323 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
339 340 341 |
# File 'lib/active_record/associations/collection_proxy.rb', line 339 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>
# ]
622 623 624 |
# File 'lib/active_record/associations/collection_proxy.rb', line 622 def delete(*records) @association.delete(*records) 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)
476 477 478 |
# File 'lib/active_record/associations/collection_proxy.rb', line 476 def delete_all(dependent = nil) @association.delete_all(dependent) 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)
694 695 696 |
# File 'lib/active_record/associations/collection_proxy.rb', line 694 def destroy(*records) @association.destroy(*records) end |
#destroy_all ⇒ Object
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
503 504 505 |
# File 'lib/active_record/associations/collection_proxy.rb', line 503 def destroy_all @association.destroy_all end |
#distinct ⇒ Object Also known as: uniq
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">]
712 713 714 |
# File 'lib/active_record/associations/collection_proxy.rb', line 712 def distinct @association.distinct 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
812 813 814 |
# File 'lib/active_record/associations/collection_proxy.rb', line 812 def empty? @association.empty? end |
#fifth(*args) ⇒ Object
Same as #first except returns only the fifth record.
189 190 191 |
# File 'lib/active_record/associations/collection_proxy.rb', line 189 def fifth(*args) @association.fifth(*args) end |
#find(*args, &block) ⇒ 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>
# ]
139 140 141 |
# File 'lib/active_record/associations/collection_proxy.rb', line 139 def find(*args, &block) @association.find(*args, &block) end |
#first(*args) ⇒ Object
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) # => []
169 170 171 |
# File 'lib/active_record/associations/collection_proxy.rb', line 169 def first(*args) @association.first(*args) end |
#forty_two(*args) ⇒ Object
Same as #first except returns only the forty second record. Also known as accessing “the reddit”.
195 196 197 |
# File 'lib/active_record/associations/collection_proxy.rb', line 195 def forty_two(*args) @association.forty_two(*args) end |
#fourth(*args) ⇒ Object
Same as #first except returns only the fourth record.
184 185 186 |
# File 'lib/active_record/associations/collection_proxy.rb', line 184 def fourth(*args) @association.fourth(*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
897 898 899 |
# File 'lib/active_record/associations/collection_proxy.rb', line 897 def include?(record) !!@association.include?(record) end |
#last(*args) ⇒ 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) # => []
235 236 237 |
# File 'lib/active_record/associations/collection_proxy.rb', line 235 def last(*args) @association.last(*args) end |
#length ⇒ Object
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>
# ]
790 791 792 |
# File 'lib/active_record/associations/collection_proxy.rb', line 790 def length @association.length end |
#load_target ⇒ Object
43 44 45 |
# File 'lib/active_record/associations/collection_proxy.rb', line 43 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
52 53 54 |
# File 'lib/active_record/associations/collection_proxy.rb', line 52 def loaded? @association.loaded? end |
#many?(&block) ⇒ Boolean
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
883 884 885 |
# File 'lib/active_record/associations/collection_proxy.rb', line 883 def many?(&block) @association.many?(&block) end |
#pluck(*column_names) ⇒ Object
738 739 740 |
# File 'lib/active_record/associations/collection_proxy.rb', line 738 def pluck(*column_names) null_scope? ? scope.pluck(*column_names) : super end |
#prepend(*args) ⇒ Object
1006 1007 1008 |
# File 'lib/active_record/associations/collection_proxy.rb', line 1006 def prepend(*args) raise NoMethodError, "prepend on association is not defined. Please use <<, push or append" end |
#proxy_association ⇒ Object
901 902 903 |
# File 'lib/active_record/associations/collection_proxy.rb', line 901 def proxy_association @association end |
#records ⇒ Object
:nodoc:
976 977 978 |
# File 'lib/active_record/associations/collection_proxy.rb', line 976 def records # :nodoc: load_target end |
#reload ⇒ Object
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>]
1039 1040 1041 1042 |
# File 'lib/active_record/associations/collection_proxy.rb', line 1039 def reload proxy_association.reload 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
393 394 395 |
# File 'lib/active_record/associations/collection_proxy.rb', line 393 def replace(other_array) @association.replace(other_array) end |
#reset ⇒ Object
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>]
1060 1061 1062 1063 1064 |
# File 'lib/active_record/associations/collection_proxy.rb', line 1060 def reset proxy_association.reset proxy_association.reset_scope reset_scope end |
#reset_scope ⇒ Object
:nodoc:
1066 1067 1068 1069 |
# File 'lib/active_record/associations/collection_proxy.rb', line 1066 def reset_scope # :nodoc: @scope = nil self end |
#scope ⇒ Object
Returns a Relation object for the records in this association
906 907 908 |
# File 'lib/active_record/associations/collection_proxy.rb', line 906 def scope @scope ||= @association.scope end |
#second(*args) ⇒ Object
Same as #first except returns only the second record.
174 175 176 |
# File 'lib/active_record/associations/collection_proxy.rb', line 174 def second(*args) @association.second(*args) end |
#second_to_last(*args) ⇒ Object
Same as #first except returns only the second-to-last record.
205 206 207 |
# File 'lib/active_record/associations/collection_proxy.rb', line 205 def second_to_last(*args) @association.second_to_last(*args) end |
#select(*fields, &block) ⇒ Object
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">
# ]
109 110 111 |
# File 'lib/active_record/associations/collection_proxy.rb', line 109 def select(*fields, &block) @association.select(*fields, &block) end |
#size ⇒ Object
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.
766 767 768 |
# File 'lib/active_record/associations/collection_proxy.rb', line 766 def size @association.size end |
#take(n = 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) # => []
264 265 266 |
# File 'lib/active_record/associations/collection_proxy.rb', line 264 def take(n = nil) @association.take(n) end |
#target ⇒ Object
39 40 41 |
# File 'lib/active_record/associations/collection_proxy.rb', line 39 def target @association.target end |
#third(*args) ⇒ Object
Same as #first except returns only the third record.
179 180 181 |
# File 'lib/active_record/associations/collection_proxy.rb', line 179 def third(*args) @association.third(*args) end |
#third_to_last(*args) ⇒ Object
Same as #first except returns only the third-to-last record.
200 201 202 |
# File 'lib/active_record/associations/collection_proxy.rb', line 200 def third_to_last(*args) @association.third_to_last(*args) end |
#to_ary ⇒ Object Also known as: to_a
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>
# ]
971 972 973 |
# File 'lib/active_record/associations/collection_proxy.rb', line 971 def to_ary load_target.dup end |