2012-04-23

active scaffoldのfield_searchを使うときhas_manyで関連している先のテーブルの複数のカラムを検索対象にする

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
ActiveScaffoldでfield_searchを使うときのお話です。

以下のようなモデルがあるとします。

class Order < ActiveRecord::Base
  has_many :items
end

class Item < ActiveRecord::Base
  belongs_to :order
end

Orderに対してActiveScaffoldを設定して、検索する際にOrderの情報だけでなくItemのコードや名称も検索したい場合です。
field_searchでなく、通常のsearchならば

config.columns[:items].search_sql = "concat(items.code,' ',items.name)"
みたいな設定をしてitemsをsearch対象に入れてあげればOKです。

field_searchの場合で、itemsの一つのカラムだけであれば
同じように
config.columns[:items].search_sql = "items.code"
でできるのですが、items.codeとitems.nameの両方の検索用テキストボックスを表示したい場合は、以下のように
ダミーカラムを用意することと検索条件を上書きすることで、できるようになります。

ここではダミーカラム、item_codeとitem_nameを定義しています。このカラムはorders、itemsにも存在しないカラムです。
一部記述を省略しています。
class OrderController < ApplicationController
  active_scaffold :orders do |config|
    config.label = "オーダー管理"

    config.actions.exclude :search
    config.actions.add :field_search

    config.columns = [...
                      :item_code,
                      :item_name]
    ...
    config.columns[:item_code].label = "商品コード"
    config.columns[:item_code].search_sql = ""
    config.columns[:item_name].label = "商品名"
    config.columns[:item_name].search_sql = ""

    #ダミーカラムを表示しないようにします
    config.list.columns.exclude [:item_code,:item_name]
    config.show.columns.exclude [:item_code,:item_name]
    config.create.columns.exclude [:item_code,:item_name]
    config.update.columns.exclude [:item_code,:item_name]

    #ダミーカラムを検索で利用します。
    config.field_search.columns = [:item_code,:item_name]
    config.field_search.text_search = false

    config.nested.add_link(:items,:label => "商品")
  end

  #ダミーカラムitem_codeを利用した検索条件
  def self.condition_for_item_code_column(column, value, like_pattern)
    ["orders.id in (select distinct order_id from items where where code = ?))", value.strip]
  end

  #ダミーカラムitem_nameを利用した検索条件
  def self.condition_for_item_code_column(column, value, like_pattern)
    ["orders.id in (select distinct order_id from items where where name = ?))", value.strip]
  end

end
コメントを投稿