2

モデルがあるとします:

class MenuItem < ActiveRecord::Base
  translates :title
end

そしてsearchlogicがプラグインされている場合、次のように動作することを期待しています:

>> MenuItem.search(:title_like => 'tea')

残念ながら、そうではありません:

Searchlogic::Search::UnknownConditionError: The title_like is not a valid condition. You may only use conditions that map to a named scope

仕事をする方法はありますか?


PS私がなんとかうまくいったのは、次のとおりです。

>> MenuItem.search(:globalize_translations_title_like => 'tea')

これは見栄えがよくありません。

4

1 に答える 1

1

searchlogicを開発しました。デフォルトでは、既存の名前付きスコープとデータベース列を利用します。最終的には有効な列名を使用して結果のSQLを作成する必要があるため、これを超えることはできません。とはいえ、searchlogicが:title属性の意味を明確に理解する方法は実際にはありません。たとえそうだったとしても、それは翻訳ライブラリで定義されたロジックに固有のものになります。これは、これがライブラリ自体にあるべきではなく、代わりにアプリ内で初期化されるプラグインまたはコードであるべきであるという危険信号です。

method_missingメソッドをオーバーライドして、自分でマッピングを行ってみませんか?Searchlogicは、alias_scopeを実行することにより、スコープをエイリアスする簡単な方法を提供します。

alias_scope :title_like, lambda { |value| globalize_translations_title_like(value) }

これが簡単な刺し傷です(これはテストされていません):

module TranslationsMapping
  def self.included(klass)
    klass.class_eval do
      extend ClassMethods
    end
  end

  module ClassMethods
    protected
      def method_missing(name, *args, &block)
        translation_attributes = ["title"].join("|")
        conditions = (Searchlogic::NamedScopes::Conditions::PRIMARY_CONDITIONS + 
          Searchlogic::NamedScopes::Conditions::ALIAS_CONDITIONS).join("|"))

        if name.to_s =~ /^(#{translation_attributes})_(#{conditions})$/
          attribute_name = $1
          condition_name = $2
          alias_scope "#{attribute_name}_#{condition_name}", lambda { |value| send("globalize_translations_#{attribute_name}_#{condition_name}", value) }
          send(name, *args, &block)
        else
          super
        end
      end
   end
end

ActiveRecord::Base.send(:include, TranslationsMapping)

お役に立てば幸いです。繰り返しになりますが、私はコードをテストしていませんが、一般的な考え方を理解する必要があります。ただし、翻訳の実装は舞台裏で行う必要があります。アプリのどこにも「globalize_translations」と入力しないでください。モデルレベルで透過的に処理する必要があります。

于 2011-03-01T09:57:31.013 に答える