searchlogic with globalize2?

270 views Asked by At

Given there is a model:

class MenuItem < ActiveRecord::Base
  translates :title
end

and searchlogic is plugged in, I'd expect the following to work:

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

Sadly, it doesn't:

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

Is there a way to make work?


P.S. The closest I managed to get workging, was:

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

Which doesn't look nice.

1

There are 1 answers

0
Binary Logic On

I developed searchlogic. By default, it leverages existing named scopes and the database columns. It can't really go beyond that because ultimately it has to create the resulting SQL using valid column names. That said, there really is no way for searchlogic to cleanly understand what your :title attribute means. Even if it did, it would be specific to the logic defined in your translation library. Which is a red flag that this shouldn't be in the library itself, but instead a plugin or code that gets initialized within your app.

Why not override the method_missing method and do the mapping yourself? Searchlogic provides and easy way to alias scoped by doing alias_scope:

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

Here's a quick stab (this is untested):

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)

Hope that helps. Again, I haven't tested the code, but you should get the general idea. But I agree, the implementation of the translations should be behind the scenes, you really should never be typing "globalize_translations" anywhere in your app, that should be take care of transparently on the model level.