仕事で触ってるRailsを、本番環境ではなくローカルで開発するために
そのまま scp して持ってきて ruby や rails のバージョンもあわせているのに
なぜか動かない。こういうエラーが出ます
Unknown key(s): include_conditions
include_conditions ってのはなんぞやってググってみると
http://d.hatena.ne.jp/osakanas/20070102/p1
これですね。便利だなと思いながらもなぜ動かない。
少なくとも本番環境では動いているのに。謎だ。
とエラーをよく見ると、:include_conditions が登録されていないとのこと。
上のページのやつと比較すると、さりげなく
class Base VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :from, :include_conditions ] end
が書かれていなかったので、「これが原因か!」と思い足してみたが、やはり変わらず。
起動時には読み込まれているらしいが、実行中にはすでに
VALID_FIND_OPTIONS が元のライブラリでの宣言の状態に戻ってしまっている。
ちなみに元の状態ってのがこれ
VALID_FIND_OPTIONS = [ :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly, :group, :having, :from, :lock ]
(どこか)/lib/active_record/base.rb では、
VALID_FIND_OPTIONS は protected になっているため、
include_with_conditions.rbで定義しても意味がない。
ということは、base.rb で宣言されたVALID_FIND_OPTIONS に対して、
実行中に :include_conditions を追加すればいいんだなと思った。
問題はどのタイミングで追加するのか。
include_with_conditions.rb で定義(オーバーライドというのかな)されてるメソッドでは
すでに options が validation ほげほげでエラーが出ているのでだめ。
タイミング的には find の所だろう。ということで、find をオーバーライドすることにしました。
module ActiveRecord class Base class << self def find(*args) VALID_FIND_OPTIONS << :include_conditions VALID_FIND_OPTIONS.uniq! # 以下は既存の find と同じ options = args.extract_options! validate_find_options(options) set_readonly_option!(options) case args.first when :first then find_initial(options) when :last then find_last(options) when :all then find_every(options) else find_from_ids(args, options) end end end end module Associations module ClassMethods def select_all_rows(options, join_dependency) # 以下、参考ページと同じ
find するたびに :include_conditions が増えていくので
uniq! を実行して :include_conditions を一つにしているというアホなコードです。
Arrayのメソッドで「〜の要素を持っている場合は真」的なメソッドがあったようななかったような。
ちなみに VALID_FIND_OPTIONS は validate_find_options の中で使っているので
その中で VALID_FIND_OPTIONS とは別の定数を使って
validate すれば、毎回追加とかしなくていいんじゃね?って話なんだけど
残念ながら validate_find_options は protected method なのよね。。。
だれかもう少しマシなコードお願いします