(使用Rails 3.1.3)
我有一个管理产品的应用。我从几个经销商处导入产品,他们都将其类别命名为不同。因此,我有resellercategories映射到我自己的子类别。
分类
子类别(belongs_to类别)
Resellercategories(belongs_to Subcategory)
产品(belongs_to Resellercategory)
您可以在此处查看模型以及如何定义关系: http://snipt.net/Linuus/category-and-subcategory?key=38ba590408ac4233927a06046eeca30d
在我的网站上,我想轻松地显示类别及其子类别。
如果用户仅为“女性”产品过滤产品,我还要过滤类别和子类别,以便仅显示具有“女性”产品的类别和子类别。性别存储在产品中。
那么,我该怎么做呢?
我尝试创建这样的查询: http://snipt.net/Linuus/categories-1/?key=2d5d54fd573f0afe60eaa3c47a23fd4d (我认为)过滤正确的类别。但是,当我做类似的事情时:
@menu_categories.each do |c|
c.subcategories.each do |sc|
# do something...
end
end
它仍会查询所有子类别是否有女性产品。因此,我在Ruby on Rails Google Group上建议使用.includes()急切加载:subcategories。所以,像这样:
Category.includes(:subcategories)
.joins("INNER JOIN resellercategories AS r ON subcategories.id = r.subcategory_id")
.joins("INNER JOIN products AS p ON r.id = p.resellercategory_id")
.group("categories.id")
.order("categories.name ASC")
.where("p.gender = 'unisex' OR p.gender = 'female'")
.where("subcategories.id > 0") # Dummy to trigger eager loading
然而,当混合.includes()和.joins()时,包含似乎无法加载任何东西。因此抛出以下错误:
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: subcategories.id:
SELECT "categories".* FROM "categories"
INNER JOIN resellercategories AS r ON subcategories.id = r.subcategory_id
INNER JOIN products AS p ON r.id = p.resellercategory_id
WHERE (p.gender = 'unisex' OR p.gender = 'female')
GROUP BY categories.id
ORDER BY categories.name ASC
预计会出现这种情况吗?这是一个错误吗? 我试图以正确的方式做到这一点还是有更好的方法来做到这一点?
非常感谢任何帮助。
(关于RoR Google Group的讨论:https://groups.google.com/forum/?pli=1#!topic/rubyonrails-talk/UkCF7jbehHk)
解决方案: 好的,所以解决方案是使用eager_load()而不是includes()。我也不得不删除组() 这似乎对我有用:
Category.eager_load(:subcategories)
.joins("INNER JOIN resellercategories AS r ON subcategories.id = r.subcategory_id")
.joins("INNER JOIN products AS p ON r.id = p.resellercategory_id")
.order("categories.name ASC")
.where("p.gender = 'unisex' OR p.gender = 'female'")
答案 0 :(得分:1)
Rails并不总是使用连接来实现包含。您也可以通过eager_load
而不是includes
强制执行此操作。
答案 1 :(得分:1)
这条AR链看起来更干净。
Category.joins({:subcategories =>
{:resellercategories =>
:products}})
.includes(:subcategories)
.where('products.gender = unisex OR
products.gender = ?', gender)
但我不认为这会解决你获得所有subcategories
的原始问题。要解决这个问题,你实际上必须查询关联。
@menu_categories.each do |c|
c.subcategories.joins({:resellercategories =>
:products}})
.where('products.gender = unisex OR
products.gender = ?', gender)
.each do |sc|
# do something...
end
end