2016-03-06 55 views
0

我有一個使用has_many:through關聯的標籤的產品模型。我想根據選定的標籤在展示頁面上顯示類似的產品(爲每個產品選擇標籤)。Rails使用標籤顯示類似的產品

class Product < ActiveRecord::Base  
    has_many :product_tags 
    has_many :tags, through: :product_tags 
end 

比方說,我有3個產品,2個標籤 - 「狗」和「貓」(狗食品和貓的食物)。

產品1和2的標籤設置爲'狗'。產品3的標籤設置爲'貓'。

因此,產品1展示頁面上的所需輸出是產品2顯示在「您可能還會感興趣的項目」部分。產品3不應顯示在那裏。

在我的控制器中正確的方法是什麼?

我的想法是,現在使用& - 運營商,即

(@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

的問題與你的ActiveRecord的關係是你想的where子句中使用Ruby代碼。它可以處理一個簡單的哈希或一個SQL字符串,但沒有像你所做的那麼複雜。

但是,出於上述目的,我不想認爲您需要爲此查詢;你可以用Ruby數組來完成。

如果Tag模型具有反比關係:

Class Tag 
    has_many :product_tags 
    has_many :products, through: :product_tags 
end 

...那麼你應該能夠用這種(讓你的產品的標籤的產品在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 
+0

我想你」已經編輯並添加了這個部分:'where.not('products.id'=> @ product.id)'這實際上是超級有用的,我沒有想到它:)我最終與查詢一起去了,似乎對我來說更「正確」。 – mohnstrudel