Active Record Collection Proxy¶ ↑
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 计算,而不会自行触发实际帖子记录的实例化。
- #
- A
- B
- C
- D
- E
- F
- I
- L
- M
- N
- P
- R
- S
- T
实例公共方法
<<(*records) 链接
通过将其外键设置为关联的主键,向集合添加一个或多个 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> # ]
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1049 def <<(*records) proxy_association.concat(records) && self end
==(other) 链接
等同于 Array#==。如果两个数组包含相同数量的元素,并且每个元素都等于 other 数组中的相应元素,则返回 true,否则返回 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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 980 def ==(other) load_target == other end
any?() 链接
如果集合不为空,则返回 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
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 836
build(attributes = {}, &block) 链接
返回一个新对象,该对象属于集合类型,已使用 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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 318 def build(attributes = {}, &block) @association.build(attributes, &block) end
calculate(operation, column_name) 链接
来源:显示 | 在 GitHub 上
# 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() 链接
等同于 delete_all。区别在于它返回 self,而不是已删除对象的数组,因此可以链接方法。有关更多信息,请参阅 delete_all。请注意,由于 delete_all 通过直接在数据库中运行 SQL 查询来删除记录,因此对象的 updated_at 列不会改变。
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1066 def clear delete_all self end
count(column_name = nil, &block) 链接
计算所有记录。
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
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 733
create(attributes = {}, &block) 链接
返回一个新对象,该对象属于集合类型,已使用属性实例化,链接到此对象,并且已保存(如果通过了验证)。
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> # ]
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 349 def create(attributes = {}, &block) @association.create(attributes, &block) end
create!(attributes = {}, &block) 链接
与 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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 365 def create!(attributes = {}, &block) @association.create!(attributes, &block) end
delete(*records) 链接
根据 :dependent 选项指定的策略,从集合中删除提供的 records。如果未提供 :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,则通过调用它们的 destroy 方法来删除所有 records。有关更多信息,请参阅 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> # ]
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 620 def delete(*records) @association.delete(*records).tap { reset_scope } end
delete_all(dependent = nil) 链接
根据 :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 依赖关系,如果 :dependent 选项设置为 :destroy,则默认使用 :delete_all 策略。记录不会被实例化,回调也不会被触发。
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)
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 474 def delete_all(dependent = nil) @association.delete_all(dependent).tap { reset_scope } end
destroy(*records) 链接
销毁提供的 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)
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 692 def destroy(*records) @association.destroy(*records).tap { reset_scope } end
destroy_all() 链接
直接从数据库中删除集合中的记录,忽略 :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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 501 def destroy_all @association.destroy_all.tap { reset_scope } end
distinct(value = true) 链接
指定记录是否应唯一。
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"> # ]
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 697
empty?() 链接
如果集合为空,则返回 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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 831 def empty? @association.empty? end
fifth() 链接
与 first 相同,但仅返回第五条记录。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 201
find(*args) 链接
在集合中查找响应 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> # ]
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 138 def find(*args) return super if block_given? @association.find(*args) end
first(limit = nil) 链接
从集合中返回第一条记录,或前 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) # => []
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 144
forty_two() 链接
与 first 相同,但仅返回第四十二条记录。也称为访问“reddit”。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 209
fourth() 链接
与 first 相同,但仅返回第四条记录。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 193
include?(record) 链接
如果给定的 record 存在于集合中,则返回 true。
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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 927 def include?(record) !!@association.include?(record) end
last(limit = nil) 链接
从集合中返回最后一条记录,或最后 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) # => []
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 259 def last(limit = nil) load_target if find_from_target? super end
length() 链接
通过在目标上调用 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> # ]
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 787
load_target() 链接
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 44 def load_target @association.load_target end
loaded?() 链接
如果关联已加载,则返回 true,否则返回 false。
person.pets.loaded? # => false person.pets.records person.pets.loaded? # => true
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 53 def loaded? @association.loaded? end
many?() 链接
如果集合包含多个记录,则返回 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
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 877
pluck(*column_names) 链接
来源:显示 | 在 GitHub 上
# 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() 链接
返回集合的关联对象。
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 中的 关联扩展。
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 944 def proxy_association @association end
reload() 链接
从数据库重新加载集合。返回 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>]
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1085 def reload proxy_association.reload(true) reset_scope end
replace(other_array) 链接
用 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
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 391 def replace(other_array) @association.replace(other_array) end
reset() 链接
卸载关联。返回 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>]
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 1106 def reset proxy_association.reset proxy_association.reset_scope reset_scope end
scope() 链接
返回此关联中记录的 Relation 对象。
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 949 def scope @scope ||= @association.scope end
second() 链接
与 first 相同,但仅返回第二条记录。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 177
second_to_last() 链接
与 last 相同,但仅返回倒数第二条记录。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 226
select(*fields, &block) 链接
有两种用法。
第一种:指定要从结果集中选择的字段子集。
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> # ]
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 59
size() 链接
返回集合的大小。如果集合尚未加载,它将执行一个 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.
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 782 def size @association.size end
take(limit = nil) 链接
使用与 ActiveRecord::FinderMethods.take 相同的规则,从集合中获取一条记录(如果提供了参数则为 N 条记录)。
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) # => []
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 289 def take(limit = nil) load_target if find_from_target? super end
target() 链接
来源:显示 | 在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 40 def target @association.target end
third() 链接
与 first 相同,但仅返回第三条记录。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 185
third_to_last() 链接
与 last 相同,但仅返回倒数第三条记录。
来源:在 GitHub 上
# File activerecord/lib/active_record/associations/collection_proxy.rb, line 218