通过子模型属性对ActiveRecord模型进行排序?

时间:2009-07-19 00:01:26

标签: sql mysql ruby-on-rails activerecord

假设我有Category has_many的模型Items。现在,我想提供一个类别的表格,这些类别按照项目 的各种属性排序。例如,将具有最高价格项目的类别放在顶部。或者根据最佳评分项目对类别进行排序。或者根据最新项目对类别进行排序(即,最新项目的类别将是第一个)。

class Category < ActiveRecord::Base
  has_many :items

  # attributes: name
end

class Item < ActiveRecord::Base
  belongs_to :category

  # attributes: price, rating, date, 
end

哪种方法最好?

  1. 在类别模型上维护其他列以保存排序属性(即,该类别中项目的最高商品价格或最佳评级)。我以前做过这个,但它有点难看,每次项目更改时都需要更新类别模型
  2. 订单条款中的一些神奇的SQL咒语?
  3. 别的什么?
  4. 我能想出的最好的是这个SQL,用于生成按所包含项目的最高价格排序的类别列表。

    select categories.name, max(items.price) from categories join items group by categories.name
    

    不确定这如何转换为Rails代码。如果我希望按最近项目的价格排序类别,则此SQL也不起作用。出于明显的性能原因,我真的想把它保存在数据库中。

2 个答案:

答案 0 :(得分:3)

假设项目模型中列出的属性是数据库列,您可以做很多事情。

最简单的可能是named_scopes

<强> /app/models/category.rb

class Category < ActiveRecord::Base
  has_many :items

  # attributes: name
  named_scope :sorted_by_price, :joins => :items, :group => 'users.id', :order => "items.price DESC"    
  named_scope :sorted_by_rating, :joins => :items, :group => 'users.id', :order => "items.rating DESC"

  named_scope :active, :condition => {:active => true}


end

然后您可以使用Category.sorted_by_price返回按价格排序的类别列表,从最高到最低。 named_scopes的优点允许您链接多个类似的查询。使用上面的代码,如果您的Category有一个名为active的布尔值。你可以用     Category.active.sorted_by_price获取按其最昂贵项目排序的活动类别列表。

答案 1 :(得分:0)

这究竟是什么:加入是为了什么?

Category.find(:all, :joins => :items, :order => 'price')

Category.find(:all, :joins => :items, :order => 'rating')