Spec-Zone.ru › Ruby on Rails 7.0

класс ActiveRecord::Associations::CollectionProxy

Родитель:
Relation

Прокси-объекты коллекций в Active Record являются посредниками между association, и его набором результатов target.

Например, при

class Blog < ActiveRecord::Base
  has_many :posts
end

blog = Blog.first

Прокси-объект коллекции, возвращаемый blog.posts, создан на основе :has_many association, и делегирует работу с коллекцией сообщений как target.

Этот класс делегирует неизвестные методы классу связи association через кэш делегирования.

Набор результатов target загружается только по мере необходимости. Например,

blog.posts.count

вычисляется напрямую через SQL и не вызывает само по себе создание фактических записей сообщений.

Публичные методы экземпляра

<<(*records) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1031
def <<(*records)
  proxy_association.concat(records) && self
end

Добавляет одну или несколько records в коллекцию, устанавливая их внешние ключи на первичный ключ ассоциации. Так как << сглаживает свой список аргументов и вставляет каждую запись, push и concat ведут себя идентично. Возвращает self, поэтому несколько добавлений могут быть объединены вместе.

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>
#    ]
Также имеет псевдоним: push, append, concat
==(other) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 962
def ==(other)
  load_target == other
end

Эквивалентно Array#==. Возвращает true, если два массива содержат одинаковое количество элементов и если каждый элемент равен соответствующему элементу в массиве other, иначе возвращает 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
any?() Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 834
      

Возвращает true, если коллекция не пуста.

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

Вызов без блока, когда коллекция еще не загружена, эквивалентен collection.exists?. Если вы собираетесь загрузить коллекцию в любом случае, лучше вызвать collection.load.any?, чтобы избежать дополнительного запроса.

Вы также можете передать block, чтобы определить критерии. Поведение такое же, он возвращает true, если коллекция на основе критериев не пуста.

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
append(*records)
Псевдоним для: <<
build(attributes = {}, &block) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 316
def build(attributes = {}, &block)
  @association.build(attributes, &block)
end

Возвращает новый объект типа коллекции, который был создан с помощью attributes и связан с этим объектом, но еще не сохранен. Вы можете передать массив хэшей атрибутов, это вернет массив с новыми объектами.

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
Также имеет псевдоним: new
calculate(operation, column_name) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 722
def calculate(operation, column_name)
  null_scope? ? scope.calculate(operation, column_name) : super
end
Вызывает метод суперкласса
clear() Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1048
def clear
  delete_all
  self
end

Эквивалентно delete_all. Разница в том, что возвращает self, а не массив с удаленными объектами, поэтому методы могут быть связаны. Смотрите delete_all для получения дополнительной информации. Обратите внимание, что поскольку delete_all удаляет записи путем прямого выполнения SQL-запроса в базу данных, столбец updated_at объекта не изменяется.

concat(*records)
Псевдоним для: <<
count(column_name = nil, &block) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 731
      

Подсчитать все записи.

class Person < ActiveRecord::Base
  has_many :pets
end

# This will perform the count using SQL.
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>
#    ]

Передача блока выберет всех питомцев человека в SQL, а затем выполнит подсчет с использованием Ruby.

person.pets.count { |pet| pet.name.include?('-') } # => 2
create(attributes = {}, &block) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 347
def create(attributes = {}, &block)
  @association.create(attributes, &block)
end

Возвращает новый объект типа коллекции, который был создан с атрибутами, связан с этим объектом и уже сохранен (если он проходит валидацию).

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>
#    ]
create!(attributes = {}, &block) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 363
def create!(attributes = {}, &block)
  @association.create!(attributes, &block)
end

Как create, за исключением того, что если запись недействительна, возникает исключение.

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
delete(*records) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 618
def delete(*records)
  @association.delete(*records).tap { reset_scope }
end

Удаляет предоставленные records из коллекции в соответствии со стратегией, указанной параметром :dependent. Если параметр :dependent не указан, то будет использоваться стратегия по умолчанию. Возвращает массив с удаленными записями.

Для ассоциаций has_many :through, стратегия удаления по умолчанию — :delete_all.

Для ассоциаций has_many, стратегия удаления по умолчанию — :nullify. Это устанавливает внешние ключи в 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>

Если он установлен в :destroy, все records удаляются путем вызова их метода destroy. Смотрите destroy для получения дополнительной информации.

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)

Если он установлен в :delete_all, все records удаляются без вызова их метода destroy.

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

Вы можете передать значения Integer или String, он находит записи, отвечающие id, и выполняет для них удаление.

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>
#    ]
delete_all(dependent = nil) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 472
def delete_all(dependent = nil)
  @association.delete_all(dependent).tap { reset_scope }
end

Удаляет все записи из коллекции в соответствии со стратегией, указанной параметром :dependent. Если параметр :dependent не указан, то будет использоваться стратегия по умолчанию.

Для ассоциаций has_many :through, стратегия удаления по умолчанию — :delete_all.

Для ассоциаций has_many, стратегия удаления по умолчанию — :nullify. Это устанавливает внешние ключи в 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>
#    ]

Зависимости has_many и has_many :through по умолчанию используют стратегию :delete_all, если параметр :dependent установлен в :destroy. Записи не создаются, и обратные вызовы не вызываются.

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)

Если он установлен в :delete_all, все объекты удаляются без вызова их метода destroy.

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)
destroy(*records) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 690
def destroy(*records)
  @association.destroy(*records).tap { reset_scope }
end

Уничтожает предоставленные records и удаляет их из коллекции. Этот метод всегда будет удалять запись из базы данных, игнорируя параметр :dependent. Возвращает массив с удаленными записями.

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)

Вы можете передать значения Integer или String, он находит записи, отвечающие id, и затем удаляет их из базы данных.

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)
destroy_all() Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 499
def destroy_all
  @association.destroy_all.tap { reset_scope }
end

Удаляет записи коллекции непосредственно из базы данных, игнорируя параметр :dependent. Записи создаются, и вызываются обратные вызовы before_remove, after_remove, before_destroy и after_destroy.

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
distinct(value = true) Show source
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 695
      

Указывает, должны ли записи быть уникальными или нет.

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

person.pets.select(:name).distinct.distinct(false)
# => [
#      #<Pet name: "Fancy-Fancy">,
#      #<Pet name: "Fancy-Fancy">
#    ]
empty?() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 829
def empty?
  @association.empty?
end

Возвращает true, если коллекция пуста. Если коллекция загружена, это эквивалентно collection.size.zero?. Если коллекция не загружена, это эквивалентно !collection.exists?. Если коллекция еще не загружена, и вы собираетесь получать записи, лучше проверить collection.load.empty?.

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
fifth() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 199
      

Аналогично first, за исключением того, что возвращает только пятую запись.

find(*args) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 136
def find(*args)
  return super if block_given?
  @association.find(*args)
end

Ищет объект в коллекции, соответствующий id. Использует те же правила, что и ActiveRecord::Base.find. Возвращает ошибку ActiveRecord::RecordNotFound, если объект не найден.

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>
#    ]
Вызывает метод суперкласса
first(limit = nil) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 142
      

Возвращает первую запись или первые n записи из коллекции. Если коллекция пуста, первая форма возвращает nil, а вторая форма — пустой массив.

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) # => []
forty_two() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 207
      

Аналогично first, за исключением того, что возвращает только сорок вторую запись. Также известна как доступ к “reddit”.

fourth() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 191
      

Аналогично first, за исключением того, что возвращает только четвёртую запись.

include?(record) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 925
def include?(record)
  !!@association.include?(record)
end

Возвращает true, если заданная record присутствует в коллекции.

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
last(limit = nil) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 257
def last(limit = nil)
  load_target if find_from_target?
  super
end

Возвращает последнюю запись или последние n записи из коллекции. Если коллекция пуста, первая форма возвращает nil, а вторая форма — пустой массив.

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) # => []
Вызывает метод суперкласса
length() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 785
      

Возвращает размер коллекции, вызывая size на целевом объекте. Если коллекция уже загружена, length и size эквивалентны. Если нет, и вам всё равно понадобятся записи, этот метод выполнит на одну запрос меньше. В противном случае size более эффективен.

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>
#    ]
load_target() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 42
def load_target
  @association.load_target
end
loaded()
Псевдоним для: loaded?
loaded?() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 51
def loaded?
  @association.loaded?
end

Возвращает true если ассоциация загружена, иначе false.

person.pets.loaded? # => false
person.pets.records
person.pets.loaded? # => true
Также используется как псевдоним: loaded
many?() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 875
      

Возвращает true, если в коллекции более одной записи. Эквивалентно 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

Также можно передать block для определения критериев. Поведение аналогичное, возвращается true, если в коллекции, основанной на критериях, более одной записи.

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
new(attributes = {}, &block)
Псевдоним для: build
pluck(*column_names) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 726
def pluck(*column_names)
  null_scope? ? scope.pluck(*column_names) : super
end
Вызывает метод суперкласса
push(*records)
Псевдоним для: <<
reload() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1067
def reload
  proxy_association.reload(true)
  reset_scope
end

Перезагружает коллекцию из базы данных. Возвращает 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>]
replace(other_array) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 389
def replace(other_array)
  @association.replace(other_array)
end

Заменяет эту коллекцию на other_array. Это выполнит сравнение и удалит/добавит только изменившиеся записи.

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

Если в предоставленном массиве неправильный тип ассоциации, возникает ошибка ActiveRecord::AssociationTypeMismatch:

person.pets.replace(["doo", "ggie", "gaga"])
# => ActiveRecord::AssociationTypeMismatch: Pet expected, got String
reset() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1088
def reset
  proxy_association.reset
  proxy_association.reset_scope
  reset_scope
end

Разгружает ассоциацию. Возвращает 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>]
scope() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 934
def scope
  @scope ||= @association.scope
end

Возвращает объект Relation для записей в этой ассоциации

second() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 175
      

Аналогично first, за исключением того, что возвращает только вторую запись.

second_to_last() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 224
      

Аналогично first, за исключением того, что возвращает только предпоследнюю запись.

select(*fields, &block) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 57
      

Работает двумя способами.

Во-первых: Укажите подмножество полей для выбора из набора результатов.

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

Будьте осторожны, так как это также означает инициализацию объекта модели только полями, которые вы выбрали. Если вы попытаетесь получить доступ к полю, которое id отсутствует в инициализированной записи, вы получите:

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

Во-вторых: Вы можете передать блок, чтобы использовать его так же, как Array#select. Это создаёт массив объектов из базы данных для области видимости, преобразуя их в массив и итерируя по ним с помощью Array#select.

person.pets.select { |pet| /oo/.match?(pet.name) }
# => [
#      #<Pet id: 2, name: "Spook", person_id: 1>,
#      #<Pet id: 3, name: "Choo-Choo", person_id: 1>
#    ]
size() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 780
def size
  @association.size
end

Возвращает размер коллекции. Если коллекция ещё не загружена, она выполняет запрос SELECT COUNT(*). В противном случае она вызывает collection.size.

Если коллекция уже загружена size, и length эквивалентны. Если нет, и вам всё равно нужны записи, length потребует на один запрос меньше. В противном случае size более эффективен.

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.
take(limit = nil) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 287
def take(limit = nil)
  load_target if find_from_target?
  super
end

Возвращает запись (или N записей, если параметр указан) из коллекции, используя те же правила, что и 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) # => []
Вызывает метод родительского класса
target() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 38
def target
  @association.target
end
third() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 183
      

Аналогично first, но возвращает только третью запись.

third_to_last() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 216
      

Аналогично first, но возвращает только третью с конца запись.

© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API