Rails使用标签

时间:2016-03-06 22:21:42

标签: ruby-on-rails activerecord associations

我有一个带有标签的产品型号使用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

1 个答案:

答案 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