class ActiveEntity::Associations::Embeds::CollectionProxy
Association
proxies in Active Entity 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 ActiveEntity::Reflection::AssociationReflection.
For example, given
class Blog < ActiveEntity::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.
Attributes
Public Class Methods
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 45 def initialize(klass, association) @klass = klass @association = association extensions = association.extensions extend(*extensions) if extensions.any? end
Public Instance Methods
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 < ActiveEntity::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_entity/associations/embeds/collection_proxy.rb, line 298 def <<(*records) proxy_association.concat(records) && self end
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 < ActiveEntity::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_entity/associations/embeds/collection_proxy.rb, line 225 def ==(other) records == other end
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.
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 192 def clear delete_all self end
Add one or more records to the collection by setting their foreign keys to the association's primary key. Since <<
flattens its argument list and inserts each record, push
and concat
behave identically. Returns self
so method calls may be chained.
class Person < ActiveEntity::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_entity/associations/embeds/collection_proxy.rb, line 146 def concat(*records) @association.concat(*records) end
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 181 def delete(*records) @association.delete(*records) end
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 176 def delete_all @association.delete_all end
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 76 def inspect entries = records.take([size, 11].compact.min).map!(&:inspect) entries[10] = "..." if entries.size == 11 "#<#{self.class.name} [#{entries.join(', ')}]>" end
Returns true
if the association has been loaded, otherwise false
.
person.pets.loaded? # => false person.pets person.pets.loaded? # => true
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 89 def loaded? @association.loaded? end
Initializes new record from relation while maintaining the current scope.
Expects arguments in the same format as ActiveEntity::Base.new.
users = User.where(name: 'DHH') user = users.new # => #<User id: nil, name: "DHH", created_at: nil, updated_at: nil>
You can also pass a block to new with the new record as argument:
user = users.new { |user| user.name = 'Oscar' } user.name # => Oscar
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 66 def new(attributes = nil, &block) klass.new(attributes, &block) end
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 304 def prepend(*_args) raise NoMethodError, "prepend on association is not defined. Please use <<, push or append" end
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 72 def pretty_print(q) q.pp(records) end
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 197 def proxy_association @association end
Replaces this collection with other_array
. This will perform a diff and delete/add only records that have changed.
class Person < ActiveEntity::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 ActiveEntity::AssociationTypeMismatch
error:
person.pets.replace(["doo", "ggie", "gaga"]) # => ActiveEntity::AssociationTypeMismatch: Pet expected, got String
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 172 def replace(other_array) @association.replace(other_array) end
:method: 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 < ActiveEntity::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> # ]
Converts relation objects to Array.
# File lib/active_entity/associations/embeds/collection_proxy.rb, line 269 def to_ary records.dup end