这里的控制器代码仅适用于一个类别:
# 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 #<Array:0x1887c2c>
或
undefined method `page' for #<Array:0x1887c2c>
因为我正在使用订购和分页,所以它不能再订购。
如何在控制器中的ActiveRecord Relation元素中获取所有产品? 感谢
更新
所以,当我使用以下内容时:
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
好的,所以我要开始赏金。
如果我尝试:
def all_products Categorization.find(:all,:conditions =&gt; {:category_id =&gt; branch_ids}) 端
我再次为{`获得undefined method
命令'
我需要知道如何将many_to_many关系的所有产品作为ActiveRecord关系。
更新3
我把相关的代码放在一个要点中 https://gist.github.com/1211231
答案 0 :(得分: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
让我知道是否有任何问题
答案 1 :(得分:3)
有几种方法可以改进您的代码,但是如果您正在寻找属于某个类别的所有产品以及该类别的子代(后代),那么为什么您不会这样做:
def branch_ids
self_and_descendants.map(&:id).uniq
end
def all_products
Product.find(:all, :conditions => { :category_id => branch_ids } )
end
我在这里做了一些假设,但我希望你明白这一点。
答案 2 :(得分:0)
扩展charlysisto的答案,当你处理has_and_belongs_to_many
类别时,你很快就会发现蛮力的观点很慢......你需要某种“中间件”才能让它变得更快。 ..
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%在政治上正确,但我必须承认。