Spec-Zone.ru › Ruby on Rails 7.2

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

Родитель:
Relation

Заместитель коллекции Active Record

Заместители коллекций в 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) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1049
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) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 980
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
# => true
any?() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 836
      

Возвращает 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) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 318
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) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 724
def calculate(operation, column_name)
  null_scope? ? scope.calculate(operation, column_name) : super
end
Вызывает метод суперкласса
clear() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1066
def clear
  delete_all
  self
end

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

concat(*records)
Псевдоним для: <<
count(column_name = nil, &block) Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 733
      

Подсчёт всех записей.

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

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

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 831
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 201
      

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

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

Ищет объект в коллекции, соответствующий id. Использует те же правила, что и ActiveRecord::FinderMethods.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 144
      

Возвращает первую запись или первые 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 209
      

То же, что и first, но возвращает только сорок вторую запись. Также известен как доступ к «reddit».

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

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

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

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

Возвращает 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 728
def pluck(*column_names)
  null_scope? ? scope.pluck(*column_names) : super
end
Вызывает метод суперкласса
proxy_association() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 944
def proxy_association
  @association
end

Возвращает объект ассоциации для коллекции.

class Person < ActiveRecord::Base
  has_many :pets
end

person.pets.proxy_association
# => #<ActiveRecord::Associations::HasManyAssociation owner="#<Person:0x00>">

Возвращает тот же объект, что и person.association(:pets), позволяя вам выполнять вызовы, такие как person.pets.proxy_association.owner.

См. Дополнительные сведения об ассоциациях на Associations::ClassMethods.

push(*records)
Псевдоним для: <<
reload() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1085
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 391
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 1106
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>]
END_OF_DOCUMENT_MARKER
scope() Показать исходный код
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 949
def scope
  @scope ||= @association.scope
end

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

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

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

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

То же, что и last, но возвращает только предпоследнюю запись.

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

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

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

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' for Pet

Во-вторых: вы можете передать блок, чтобы использовать его так же, как 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 782
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 289
def take(limit = nil)
  load_target if find_from_target?
  super
end

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

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

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

То же, что и last, но возвращает только третью с конца запись.

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

Spec-Zone.ru

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