2011-09-07 129 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%的政治正确,我必须承认。

相关问题