2011-09-07 163 views
8

有一個電子商務應用程序正在開發中我試圖讓我的頭圍繞以下問題: 我通過awesome_nested_set插件實現了我的類別。 如果我通過選擇一個類別列出我的文章,一切正常,但對於某些鏈接,我想顯示一個類別的所有產品及其子類別的產品。得到類別和子類別的所有產品(rails,awesome_nested_set)

這裏是控制器代碼,只有一個類別正常工作:

# products_controller.rb 
    def index 
    if params[:category] 
     @category = Category.find(params[:category]) 
     #@products = @category.product_list 
     @products = @category.products 
    else 
     @category = false 
     @products = Product.scoped 
    end 
    @products = @products.where("title like ?", "%" + params[:title] + "%") if params[:title] 
    @products = @products.order("created_at).page(params[:page]).per(params[:per_page] ? params[:per_page] : 25) 
    @categories = Category.all 
    end 

我註釋掉該生產線是我寫我自己的分類模型的輔助方法,它返回的類別和其子所有產品數組中的類別。當我取消這條線,並嘗試選擇一類我的產品控制器代碼打破了這樣的錯誤

undefined method `order' for #<Array:0x1887c2c> 

undefined method `page' for #<Array:0x1887c2c> 

# app/models/category.rb 
def product_list 
    self_and_ancestors.to_a.collect! { |x| x.products } 
end 

現在:

它是作爲遵循定義

,因爲我正在使用排序和分頁,它不能再訂購。

任何想法如何獲得我的控制器中的ActiveRecord關係元素中的所有產品? 感謝

UPDATE

所以,當我使用以下命令:

class Category < ActiveRecord::Base 
    acts_as_nested_set 

    attr_accessible :name, :description, :lft, :rgt, :parent_id 

    has_many :categorizations 
    has_many :products, :through => :categorizations 

    attr_accessor :product_list 

    def branch_ids 
     self_and_descendants.map(&:id).uniq 
    end 

    def all_products 
     Product.find(:all, :conditions => { :category_id => branch_ids }) 
    end 


end 

,並要求控制器@category.all_products我得到以下錯誤:

Mysql::Error: Unknown column 'products.category_id' in 'where clause': SELECT `products`.* FROM `products` WHERE `products`.`category_id` IN (6, 8, 9) 

我會怎樣獲得這個星座的所有產品?

更新2

好了,我要開始一個賞金。

如果我嘗試:

高清ALL_PRODUCTS Categorization.find(:全部:條件=> {:CATEGORY_ID => branch_ids}) 結束

我再次得到undefined method秩序」爲#` 我需要知道如何將一個many_to_many關係的所有產品作爲一個ActiveRecord關係獲得。

更新3

我把相關代碼的要點 https://gist.github.com/1211231

回答

5

awesome_nested_set的關鍵是使用lft列中的範圍。 下面是我要做的事有直接關聯(類別的has_many文章)

module Category 
    extend ActiveSupport::Concern 
    included do 
     belongs_to :category 
     scope :sorted, includes(:category).order("categories.lft, #{table_name}.position") 
    end 

    module ClassMethods 
     def tree(category=nil) 
     return scoped unless category 
     scoped.includes(:category).where([ 
      "categories.tree_id=1 AND categories.lft BETWEEN ? AND ?", 
      category.lft, category.rgt 
     ]) 
     end 
    end # ClassMethods 
    end 

然後在控制器

@category = Category.find_by_name("fruits") 
@articles = Article.tree(@category) 

會找到下的類別蘋果,橘子所有文章某處的代碼示例,香蕉等等 你應該適應這個想法加入分類(但你確定你需要一個多對多的關係嗎?)

無論如何,我會試試這個:

class Product < AR 
     has_many :categorizations 

     def self.tree(category=nil) 
     return scoped unless category 
     select("distinct(products.id), products.*"). 
     joins(:categorizations => :category).where([ 
      "categories.lft BETWEEN ? AND ?", category.lft, category.rgt 
     ]) 
     end 
end 

讓我知道,如果有任何疑難雜症

+0

這給我一個語法錯誤.. ./Users/frankblizzard/Sites/rails_projekte/sotaca/app/models/product.rb:56:語法錯誤,意外的'}',期待tASSOC scoped.joins(:categorizations => {:category})。where( [「 – tmaximini

+0

等待 - 我認爲它現在可以工作(去掉大括號左邊的類別) - 現在將進行深入測試 – tmaximini

+0

確定它的工作到目前爲止 - 剩下的唯一問題是現在有些文章會顯示兩次 - 如果他們有兩個例如,我知道有一種方法「uniq」,它可以整理出重複的內容,但是「.order」和「paginate」將不起作用,因爲這會將ActiveRecord關係轉化爲一個數組。用這種方法處理重複? – tmaximini

3

這裏有幾種方法,你可以改善你的代碼,但如果你正在尋找一個屬於所有產品分類和類別的兒童(後裔),那麼爲什麼你會不會做這樣的:

def branch_ids 
    self_and_descendants.map(&:id).uniq 
end 

def all_products 
    Product.find(:all, :conditions => { :category_id => branch_ids }) 
end 

我已經在這裏做了一些假設,但我希望你的想法。

+0

謝謝,稍後再測試並報告回 – tmaximini

+0

嗨,對不起回來晚了,但現在我記得我嘗試了類似的東西。問題是,產品表中沒有列「category_id」。我有一個has_many:通過'分類'關係,因爲產品可以有多個類別。那就是爲什麼這個查詢不起作用。我會更新這個問題。 – tmaximini

+0

收集所有Categorizations_ids而不是category_ids,並按照上面所述執行類似操作,或者編寫一個命名的作用域,以便在涉及的模型上執行連接... – socjopata

0

擴展charlysisto的答案,當你正在處理has_and_belongs_to_many類別,你很快就會發現,蠻力角度來看是相當緩慢......你需要一些「中間件」,使其更快...

socjopata的答案提供了一個很好的方法來改善這一點。所以,你使用的定義爲

def branch_ids 
    self_and_descendants.map(&:id).uniq 
end 

你的category.rb文件(模型)。

然後,例如,在你的控制器(例如使用分頁):

@category = Category.find... # whatever 
branches = @category.branch_ids 
@prodcats = ProductCategory.select('distinct product_id') 
          .where('category_id IN (?)',branches) 
          .order(:product_id) 
          .paginate(page: params[:page], :per_page => 25) 
ids  = @prodcats.map(&:product_id) 
@products = Product.where('id IN (?)', ids) 

最後,在你看來,你將需要一點「技術」,纔能有分頁。您將分頁上@prodcats,不@products ...

<%= will_paginate @prodcats %> 
<% @products.each do |product| %> 
    .... 
<% end %> 

這種做法是這樣快,many_to_many交易,雖然不是100%的政治正確,我必須承認。

相關問題