2011-01-26

ActiveScaffoldでbelogns_toのモデルの内容でソートする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
最近、ActiveScaffoldをいろいろいじっています。

ActiveScaffoldでは、あるモデルに関係している情報もいい感じで表示してくれる機能があります。
例えば、以下のモデルがあるとします。
class User < ActiveRecord::Base
  belongs_to :group
end

class Group < ActiveRecord::Base
  has_many :users

  def to_label
    "#{code}:#{name}"
  end
end

それぞれのテーブルは、以下の情報を持つとします。
users
idgroup_idname
11aaa
21bbb
33ccc

groups
idcodename
1g1xxx
2g2yyy

Userの一覧を表示するならば以下のような感じのコントローラーを作成します。
class UsersController < ApplicationController
  active_scaffold :user do |config|
    config.columns = [:id, :group, :name]

    config.columns[:group].form_ui = :select
  end
end

これで表示するとUser一覧にグループ情報としてGroupモデルのto_labelで指定した内容で一覧が以下のような感じで表示されます。
idgroupname
1g1:xxxaaa
2g1:xxxbbb
2g2:yyyccc
登録や変更をする際もgroup欄にはセレクトto_labelで指定した内容のセレクトボックスが表示され、ちゃんと対応するgroup_idがセットされて登録されることになります。

ここで表示順を以下のようにgroups.codeで降順にして、さらにuser.nameの昇順にしたいとするとします。
idgroupname
2g2:yyyccc
1g1:xxxaaa
2g1:xxxbbb

そのためにUserControllerに以下を追加します。
config.list.sorting = [{:group => :desc},{:name => :asc}]

でも、これでは以下のエラーが出てダメなのです。
Can't mix :method- and :sql-based sorting

それぞれ単独ならば問題なく動きます。

どうやらデフォルトでは、直接表示させているモデルに関するデータでソートする場合は、sqlでソートさせているのですが 関連するモデルの情報でソートする際は、データを持ってきてからActiveScaffold側でソートしているようです。
そしてソート手段が混ざるとダメなようです。

これをなんとかするには、以下のようにgroupsも検索対象に含めるように明示します。
config.columns[:group].includes = [:group]
config.columns[:group].sort_by :sql => "groups.code"

これでソートができるようになりました。

最終的なコントローラーは以下のような感じです。
class UsersController < ApplicationController
  active_scaffold :user do |config|
    config.columns = [:id, :group, :name]

    config.columns[:group].form_ui = :select
    config.columns[:group].includes = [:group]
    config.columns[:group].sort_by :sql => "groups.code"

    config.list.sorting  = [{:group => :desc},{:name => :asc}]
  end
end


コメントを投稿