获取所有类别和子类别的产品(rails,awesome_nested_set)

正在开发一个正在开发的电子商务应用程序我试图解决以下问题:我通过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 

我注释掉的一行是我在类别模型中自己编写的辅助方法,它返回类别中所有产品及其子类别的数组。

它的定义如下:

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

现在,当我取消注释这一行并尝试选择一个类别时,我的产品控制器代码会出现错误,例如

 undefined method `order' for # 

要么

 undefined method `page' for # 

因为我正在使用订购和分页,它不能再订购。

有什么想法如何在我的控制器中的ActiveRecord Relation元素中获取所有产品? 谢谢

UPDATE

所以,当我使用以下内容时:

 class Category  :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

好的,所以我要开始赏金。

如果我尝试:

def all_products Categorization.find(:all,:conditions => {:category_id => branch_ids})结束

我再次得到undefined method顺序’for #`我需要知道如何将many_to_many关系的所有产品作为ActiveRecord关系。

更新3

我把相关的代码放在一个要点https://gist.github.com/1211231

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 

如果有任何问题,请告诉我

有几种方法可以改进您的代码,但如果您正在寻找属于某个类别的所有产品以及该类别的子代(后代),那么为什么您不会这样做:

 def branch_ids self_and_descendants.map(&:id).uniq end def all_products Product.find(:all, :conditions => { :category_id => branch_ids } ) end 

我在这里做了一些假设,但我希望你能得到这个想法。

扩展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%在政治上正确。