是非に及ばず

プログラミングに関する話題などを書いていきます(主にRailsやAndroidアプリ開発について)

Railsのnamed_scopeをまとめて実行するサンプル(Ruby1.9.2 + Rails3版)

説明

前回のエントリーと同じ内容なので、ポイントだけ書く。
Ruby1.9.2+Rails3では前回のサンプルでは動かない部分があるので、それを動くようにする。
具体的には、この部分が動かない。

scope.call p, *args

Ruby1.8.7Rails.2.3では動作するが、Ruby1.9.2 + Rails3ではここでエラーとなる。
理由は、よく分からないがRails3のArelの関係ような気がする。
ここでは、単純なメソッド呼び出しの形に変更して対応してみる。

named_scopeをまとめて実行するメソッド(Ruby1.9.2 + Rail3.0.0で動作確認)

class Member < ActiveRecord::Base
  belongs_to :customer
  named_scope by_email, lambda{|email| {:conditions => ['email = ?', email]} }
  named_scope active,  {:conditions => ['deleted = ?', false]} # 有効
  named_scope deleted, {:conditions => ['deleted = ?', true]}  # 無効(論理削除)

  def self.search(params = {})
    exec_scopes = []  # [実行するスコープ名(シンボル), 引数] を格納する配列

    if params[:deleted] == true
      exec_scopes << [:deleted]
    else
      exec_scopes << [:active]
    end

    if params[:email]
      exec_scopes << [:by_email, params[:email]]
    end
  
    # 実行するスコープがない場合
    if exec_scopes.size == 0
      return Member.scoped
    end

    # named_scopeをまとめて実行
    exec_scopes.reverse.inject(self){|obj, exec_scope|
      scope = exec_scope.shift
      args = exec_scope

      if args.size > 0
        obj = obj.send(scope, *args)
      else
        obj = obj.send(scope)
      end
    }
  end
end