如何使用ActiveRecord对深层嵌套集合进行排序?

时间:2011-09-06 17:38:04

标签: ruby-on-rails activerecord scope acts-as-list

我正在构建一个音乐管理Rails应用程序,我的应用程序的用户将能够制作有序的专辑播放列表,每张专辑都会有一个有序的歌曲列表。

从本质上讲,这将是:

class User < ActiveRecord::Base
  has_many :playlists, :order => "position"
  has_many :albums, :through => :playlists
end

class Playlist < ActiveRecord::Base
  belongs_to :user
  belongs_to :album
end

class Album < ActiveRecord::Base
  has_many :songs, :order => "position"
  has_many :playlists
end

class Song < ActiveRecord::Base
  belongs_to :album
end

(我正在使用acts_as_list在歌曲和播放列表表格中使用position列来分别管理歌曲和播放列表的排序顺序。)

现在我想找到给定用户的所有歌曲列表(按顺序)。如果我将此范围添加到 Song 模型:

scope :for_user, lambda{|user|
  joins(:album => {:playlists => :user}).
  where(:'users.id' => user.id)
}

我可以做到这一点,但返回的记录不是按顺序保存的。相反,我希望看到每首歌曲首先按其专辑的播放列表位置为用户排序,然后是歌曲在该专辑中的位置。换句话说,如果用户想要按顺序播放专辑A,B和C,我正在寻找A中所有歌曲的数组(按照他们在专辑中的顺序),以及来自B的所有歌曲。 (按顺序),加上C中的所有歌曲(按顺序)。

我已经尝试了范围内的 order group 子句的几种排列,但没有一种能够在订购相册的上下文中对歌曲进行排序所需的效果

2 个答案:

答案 0 :(得分:2)

你试过了吗?

scope :for_user, lambda{|user|
  joins(:album => {:playlists => :user}).
  where('users.id' => user.id).
  order('"albums"."position" ASC, "songs"."position" ASC')
}

ORDER BY sql子句接受多个参数(参见http://www.quackit.com/sql/tutorial/sql_order_by.cfm)。不要使用GROUP BY,它仅在生成聚合时有用(例如。http://www.w3schools.com/sql/sql_groupby.asp

答案 1 :(得分:0)

要添加到m_x的答案,如果您希望代码更加面向对象,可以构建如下的order子句:

order(Album.arel_table[:position], Song.arel_table[:position])