如何在rails上的ruby中以多对多关系对对象进行排序?

时间:2010-05-14 02:39:54

标签: ruby-on-rails sorting many-to-many ruby-on-rails-3

我一直在努力解决这个问题几个小时,现在还没有找到一个干净的解决方案。看来我对铁轨不太好......

无论如何,我有以下内容:

Diagram

在代码中:

class Article < ActiveRecord::Base
  has_many :line_aspects
  has_many :aspects, :through => :line_aspects
  #plus a 'name' field
end

class LineAspect < ActiveRecord::Base
  belongs_to :article
  belongs_to :aspect
  #plus a 'value' field
end

class Aspect < ActiveRecord::Base
  has_many :line_aspects
  has_many :articles, :through => :line_aspects
  #plus a 'name' field
end

现在,我想做的是分两步进行排序。第一种文章由他们的Articles.name,然后在内部按Aspect.name排序(注意,不是中间人)。

例如,按字母顺序排列(对不起,如果表示法不正确):

[{
   article => 'Apple',
   line_aspects => [
      {:value => 'red'}, #corresponding to the Attribute with :name => 'color'
      {:value => 'small'} #corresponding to the Attribute with :name => 'shape'
   ]
},{
   article => 'Watermelon',
   line_aspects => [
      {:value => 'green'}, #corresponding to the Attribute with :name => 'color'
      {:value => 'big'} #corresponding to the Attribute with :name => 'shape'
   ]
}]

再次注意,这些是按方面名称(形状前的颜色)排序,而不是每行的特定值(绿色前的红色)。我的目的是在视图中的表格中显示这些内容。

结果如下:

Table

这是我正在使用的代码:

<table>
  <tr>
    <th>Category</th>
    <% @articles.each do |article| -%>
      <th><%= link_to article.name, article -%></th>
    <% end -%>
  </tr>

  <% @aspects.each do |aspect| -%>
    <tr>
      <td><%= aspect.name -%></td>

      <% aspect.line_aspects.each do |line_aspect| -%>
        <td><%= line_aspect.value %></td>
      <% end -%>
    </tr>
  <% end -%>
</table>

我还没有找到一种在rails中执行此操作的好方法(不使用N查询)。任何人都可以告诉我一个很好的方法(如果我的方法错了,甚至改变观点)?

(我找到了similar question in hyphen

更新:这是我在SQL中的方式:

SELECT line_aspects.value FROM line_aspects, aspects, articles 
WHERE articles.id = line_aspects.article_id 
   AND aspects.id = line_aspects.aspect_id
ORDER BY aspects.name, articles.name

但我想以轨道方式做到这一点。

更新:添加了视图代码。这可能会让我的困境更好一些。

3 个答案:

答案 0 :(得分:3)

在尝试了另一个答案之后,我找到了一种从模型中做到这一点的方法。我不确定这是否是Right Way™,但它似乎是一个可行的解决方案(让数据库引擎对其进行排序)。

在Aspect模型中,我改变了这一行:

has_many :line_aspects

进入这个:

has_many :line_aspects, :include => :article, :order => 'articles.name'

尽管如此,我还是希望听到更多人的意见。

答案 1 :(得分:1)

这只是部分解决方案,因为它无法完全解决您的问题。

您可以使用named_scope按相应字段对模型进行排序。有点像: named_scope :ordered, :order => "name ASC"

这是一个简单的解决方案(至少语法方面,不确定复杂性)。我可以预见的唯一问题是,您无法在单个查询中对多个named_scope进行排序。

对于第二种排序,您可以对获得的集合使用Enumerable#sort_byarray.sort

希望这有点帮助:)

答案 2 :(得分:0)

此查询提取所有文章并急切加载其方面,并按文章名称和ascpect名称对其进行排序:

@articles = Article.all(:include => [ :aspects ], :order => "articles.name asc, aspects.name asc")