класс ActiveRecord::Associations::CollectionProxy
Прокси-объекты коллекций в 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 и не вызывает само по себе создание фактических записей сообщений.
Публичные методы экземпляра
# 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> # ]
# 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
# 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
# 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
# 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
# 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 объекта не изменяется.
# 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
# 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>
# ]
# 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
# 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>
# ]
# 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)
# 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)
# 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
# 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"> # ]
# 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
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 199
Аналогично first, за исключением того, что возвращает только пятую запись.
# 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>
# ]
# 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) # => []
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 207
Аналогично first, за исключением того, что возвращает только сорок вторую запись. Также известна как доступ к “reddit”.
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 191
Аналогично first, за исключением того, что возвращает только четвёртую запись.
# 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
# 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) # => []
# 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> # ]
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 42 def load_target @association.load_target end
# 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
# 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
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 726 def pluck(*column_names) null_scope? ? scope.pluck(*column_names) : super end
# 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>]
# 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
# 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>]
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 934 def scope @scope ||= @association.scope end
Возвращает объект Relation для записей в этой ассоциации
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 175
Аналогично first, за исключением того, что возвращает только вторую запись.
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 224
Аналогично first, за исключением того, что возвращает только предпоследнюю запись.
# 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>
# ]
# 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.
# 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) # => []
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 38 def target @association.target end
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 183
Аналогично first, но возвращает только третью запись.
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 216
Аналогично first, но возвращает только третью с конца запись.
© 2004–2021 David Heinemeier Hansson
Licensed under the MIT License.