我有一个带有标签的产品型号使用has_many:通过关联。我想在显示页面上根据所选标签显示类似产品(为每种产品选择标签)。
class Product < ActiveRecord::Base
has_many :product_tags
has_many :tags, through: :product_tags
end
我们说我有3个产品和2个标签 - &#39; dog&#39;并且&#39; cat&#39; (用于狗食和猫食)。
产品1和2的标签设置为“狗”。产品3将其标记设置为&#39; cat&#39;
因此,产品1显示页面上的所需输出是产品2显示在&#34;您可能也感兴趣的项目中#34;。产品3不应该在那里显示。
我的控制器中的正确方法是什么?
我的想法现在正在使用&amp; - 运营商,即
(@product_1.product_tags & @product_2.product_tags).empty?
如果不为空,则显示产品。但是如何在控制器中将其作为查询来完成?
这是我的尝试
def show
@product = Product.find(params[:id])
@similar_products = Product.where(!(tags & @product.tags).empty?)
end
但它显然不起作用。如何在查询中访问关联的模型?我也找到了this解决方案,但它对我不起作用:
Product.joins(:tags).where((:tags & @pr1.tags).empty?).all
NoMethodError: undefined method `&' for :tags:Symbol
答案 0 :(得分:1)
ActiveRecord关系的问题在于您尝试在where
子句中使用Ruby代码。它可以处理一个简单的哈希或一个SQL字符串,但没有什么比你正在做的那么复杂。
但是,出于上述目的,我并非认为您需要对此进行查询;你可以用Ruby数组做到这一点。
如果您的Tag
模型具有反比关系:
Class Tag
has_many :product_tags
has_many :products, through: :product_tags
end
...那么你应该能够得到你的产品标签&#39;带有这个的产品(在map
它开始使用Ruby数组而不是ActiveRecord关系):
@similar_products = @product.tags.map(&:products).flatten.uniq - [@product]
然后你只需要在视图中迭代@similar_products
来显示它们。
如果您 需要查询(例如,如果您的数据最终需要花费大量时间或内存来处理),那么您需要:
@similar_products = Product.joins(:tags).where('tags.id' => @product.tag_ids).where.not('products.id' => @product.id)
(免责声明:我还没有对此进行过测试。)
NB。 如果您的ProductTag
模型没有其他逻辑,,您可以完全取消product_tag.rb
,将表重命名为products_tags
(两个部分复数并按字母顺序排列),并使用这些:
class Product
has_and_belongs_to_many :tags
end
class Tag
has_and_belongs_to_many :products
end