Web ページの拡張検索機能に取り組んでいます。
ransackを見ましたが、必要な機能がいくつか欠けていて、url-query 文字列が非常に長くなり、バグがいくつかあります (報告されています)。
したがって、私は自分のハックを実装し始めました。
最初に私のアイデアを紹介したいと思います。その後、私の問題を解決する方法を親切に尋ねたいと思います。最後に、これを改善する他の方法があるかどうか.
アイデア:
モデルは次のように定義します (さらに、モデルはエンジン内にあります)。
module EngineName
class Post < ActiveRecord::Base
search_for :name, :as => :string do |b, q|
b.where{name =~ "%#{q}%"}
end
end
end
:name は、使用する query-param を定義することです。たとえば、これは ?q[name]=something になります。これは、ランサックのように完全に一般的ではないことはわかっていますが、まあ...
:as is 正しいフォームタグを構築します。:string は text_field の場合、:integer は number_field の場合などです。さらに拡張して、関連付けなどのコレクションの自動生成を実装したいと考えています。
これで、ブロックは簡単に使用できるスコープになりました。複雑なクエリ (count() など) を構築するときに、ランサックでいくつかの欠点に遭遇します。squeelで独自の最適化されたクエリを指定できるようになりました。
ActiveRecord::Base を拡張してロジックをセットアップしました (エンジン内ではなく、グローバルなものです。どこでも使用したい)。スコープ :search を定義したので、ランサックのように Model.search(param[q]) を使用できます。また、search_for 呼び出しで定義された「検索可能な」キーのリストを保持しようとしました。
class ActiveRecord::Base
@@searchable_attributes = Hash.new({})
def self.search_for(name, *opts, &search_scope)
return unless search_scope
@@searchable_attributes[name] = {
:type => opts[:as],
:condition => search_scope
}
unless @@searchable_attributes.has_key? :nil
@@searchable_attributes[:nil] = Proc.new { scoped }
end
end
scope :search, lambda {|q|
next unless q.kind_of?(Hash)
base = @@searchable_attributes[:nil].call
q.each do |key, search|
next unless base.class.searchable_attributes.has_key?(key)
base = @@searchable_attributes[key][:condition].call(base, search)
end
base
}
end
今問題:
それは主にクラスの継承に関係しています。しかし、 3、4を読んで試した後でも、うまくいきません。
スコープ :search の 2 行目を見てください。
そこで、「スコープ」のみを含む上で定義した単純な Proc を呼び出しています。これは、「Post」や「Comment」などのモデル自体ではなく、self が「ActiveRecord::Base」を返すという問題を回避するためです。
これは、継承時に Base クラスでスコープが呼び出されるためですが、これを修正するものは何も見つかりませんでした。
モデル自体 (Post など) で search_for が呼び出されるため、そこに返されるスコープ モデルは「正しいもの」です。
これを回避する方法を知っている人はいますか?
次の質問は、「検索可能な」スコープのリストを保存する方法です。@@変数を使用しました。しかし、それらはすべてのサブクラス内で共有されるため、これは不可能です。ただし、インスタンスを初期化せずに search_for を呼び出すため、静的である必要があります (そうではありませんか?)。
最後になりましたが、すべてのスコープで使用するベースモデルを常に指定して、それらを連鎖できるようにするのは、ある種恐ろしいことです。
これを改善する他の可能性はありますか?