【发布时间】:2014-08-24 06:05:58
【问题描述】:
这是我要达到的目标的简化示例。
- 目录 has_many 集合:通过 catalog_collections
- 产品 has_many 收藏:通过 collection_products
我有这个架构:
class Product < ActiveRecord::Base
has_many :collection_products, :foreign_key => :product_id, :dependent => :destroy, :inverse_of => :product
has_many :collections, :through => :collection_products, :foreign_key => :collection_id, :inverse_of => :products
end
class Catalog < ActiveRecord::Base
has_many :catalog_collections, :foreign_key => :catalog_id, :dependent => :destroy, :inverse_of => :catalog
has_many :collections, :through => :catalog_collections, :foreign_key => :collection_id, :inverse_of => :catalogs
end
class Collection < ActiveRecord::Base
has_many :collection_products, :foreign_key => :collection_id, :dependent => :destroy, :inverse_of => :collection
has_many :products, :through => :collection_products, :foreign_key => :product_id, :inverse_of => :collections
has_many :catalog_collections, :foreign_key => :collection_id, :dependent => :destroy, :inverse_of => :collection
has_many :catalogs, :through => :catalog_collections, :inverse_of => :collections
end
class CollectionProduct < ActiveRecord::Base
belongs_to :collection, inverse_of: :collection_products
belongs_to :product, inverse_of: :collection_products
end
class CatalogCollection < ActiveRecord::Base
belongs_to :catalog, inverse_of: :catalog_collections
belongs_to :collection, inverse_of: :catalog_collections
end
我渴望使用 .includes() 加载关联,这只会生成我需要的查询。
cats = Catalog.includes(collections: :products)
Catalog Load (0.6ms) SELECT "catalogs".* FROM "catalogs"
CatalogCollection Load (0.4ms) SELECT "catalog_collections".* FROM "catalog_collections" WHERE "catalog_collections"."catalog_id" IN (1)
Collection Load (0.5ms) SELECT "collections".* FROM "collections" WHERE "collections"."id" IN (1)
CollectionProduct Load (0.3ms) SELECT "collection_products".* FROM "collection_products" WHERE "collection_products"."collection_id" IN (1)
Product Load (0.3ms) SELECT "products".* FROM "products" WHERE "products"."id" IN (1)
=> #<ActiveRecord::Relation [#<Catalog id: 1, name: "catalog1", created_at: "2014-08-20 08:59:05", updated_at: "2014-08-20 08:59:05">]>
cats.first.collections.first.products
=> #<ActiveRecord::Associations::CollectionProxy [#<Product id: 1, name: "product1", created_at: "2014-08-20 08:58:46", updated_at: "2014-08-20 08:58:46">]>
问题是我有 n+1 个查询问题,这不知何故会产生更多查询。
cats.first.collections.first.products.where(name: 'product1')
Product Load (0.4ms) SELECT "products".* FROM "products" INNER JOIN "collection_products" ON "products"."id" = "collection_products"."product_id" WHERE "collection_products"."collection_id" = ? AND "products"."name" = 'product1' [["collection_id", 1]]
=> #<ActiveRecord::AssociationRelation [#<Product id: 1, name: "product1", created_at: "2014-08-20 08:58:46", updated_at: "2014-08-20 08:58:46">]>
我需要以某种方式让这些函数使用我们已经加载的关联进行查询,而不是从头开始查找它们当前正在执行的所有内容。
【问题讨论】:
-
您的最后一个查询正在执行另一个查询,因为您在
products上有一个where子句,但是当您第一次执行includes(collections: :products)时,products查询已经在没有它的情况下运行。将您的products视为一个数组,并改用 Rubyselect方法。
标签: ruby-on-rails ruby activerecord