読者です 読者をやめる 読者になる 読者になる

ウェブサービスを作っています。

railswhere が Rails 2.3.3 で動かない件

komagata さんの記事で知って以来、便利に使わせていただいている railswhere というプラグインがあるのですが (timcharper さんの笑顔が素敵)、Rails 2.3.3 にしたら動かなくなってしまいました。

where.and("name LIKE ?", "%#{ name }%")

みたいな部分で

undefined method `abstract_class?' for Object:Class

というエラーになります。


バックトレースとソースを追いかけていったところ、上のような Array 形式で条件指定をしたときに railswhere が

@criteria = ActiveRecord::Base.send(:sanitize_sql, criteria)

ActiveRecord::Base#sanitize_sql (ActiveRecord::Base#sanitize_sql_for_conditions のエイリアス) を呼び出すのですが、こいつが 2.3.2 と 2.3.3 で変わっています。

def sanitize_sql_for_conditions(condition)  # 2.3.2
  (..snip..)
end

def sanitize_sql_for_conditions(condition, table_name = quoted_table_name)  # 2.3.3
  (..snip..)
end

なんか第 2 引数ができてます。


で、quoted_table_name が呼ばれるせいで最終的に例外が発生してしまいます。
ただ、この第 2 引数は第 1 引数が Array のとき使われないので

@criteria = ActiveRecord::Base.send(:sanitize_sql, criteria, nil)

とかやっておけば解決します。


というわけで、config/initializers に railswhere_patch.rb みたいなのを置きました。

class Where
  class Clause
    def initialize(criteria, conjuction = "AND") # :nodoc:
      @conjuction=conjuction.upcase
      criteria = criteria.first if criteria.class==Array && criteria.length==1
        
      if criteria.class==Array   # if it's an array, sanitize it
        @criteria = ActiveRecord::Base.send(:sanitize_sql, criteria, nil)
      else
        @criteria = criteria.to_s   # otherwise, run to_s.  If it's a recursive Where clause, it will return the sql we need
      end
    end
  end
end