Using Searchlogic to combine named scopes with ‘OR’

A few days ago I released a feature that Ryan Bates requested: combining named scopes with ‘OR’. As you know, when you combine named scopes they join the conditions with ‘AND’. This obviously makes sense, but what if you want to combine conditions with ‘OR’? With this new feature you can do the following:

User.first_name_or_last_name_like("ben")
User.id_lt_or_age_gt(10)

I think this is nice feature on a variety of levels, but what I particularly like is the implementation. It uses method_missing to accomplish this. You can call any scope you want, call scopes provided by searchlogic, call your own scopes, call scopes on associations, etc. As long as it maps to a named scope it will join the conditions with ‘OR’. So you have a little more flexibility when building a query with named scopes:

User.id_gt(10).first_name_or_last_name_like("ben")
# => (id > 10) AND (first_name LIKE '%ben% OR last_name LIKE '%ben%')

More than just named scopes

A lot of people think searchlogic is just a bunch of named scopes, what people don’t realize is that it provides tools around how you use named scopes in general.

The other day I was reviewing an application for a friend who was using searchlogic. I noticed this:

User.named_scope :with_recent_orders, :conditions => ["orders.created_at >= ?", 1.week.ago], :joins => :orders
Order.named_scope :recent, :conditions => ["orders.created_at >= ?", 1.week.ago]

See the duplication there? With more complex named scopes this becomes more obvious, but the scope was so simple I think he missed it. I even catch myself doing this sometimes, then I realize I don’t need to. The named_scope in the User class is pointless. With searchlogic, you can accomplish the same thing by doing:

User.orders_recent

searchlogic dynamically creates the scope for you, pulls over the scope details, and create the necessary join.

The goal of named scopes

In my opinion the simpler the named scope, the better. If you find yourself writing a complicated named scope, take a step back and look at it. I’d be willing to bet you could split that named scope into multiple smaller scopes. For example, instead of calling a named scope ‘Product.popular_expensive’, create 2 named scopes called ‘popular’ and ‘expensive’. Break your scope into small parts and then piece them together when you need them.

Another good idea is to create scope procedures. This allows you to create small named scopes and still get the advantage of calling a single scope. Creating a procedure is as easy as creating a class level method:

class User
  def self.awesome
    name_begins_with("Ben").name_ends_with("Johnson")
  end
end

Even better, used searchlogic’s scope procedure:

User.scope_procedure :awesome, lambda { name_begins_with("Ben").name_ends_with("Johnson") }

I’ll leave it at that. If you are bored one day checkout the searchlogic docs. I think you’ll find some small things like this that could help save you time and DRY up your code.

  • Share/Save/Bookmark


8 Responses to “Using Searchlogic to combine named scopes with ‘OR’”

  1. dbalmeida says:

    Nice improvement.

    Thanks for the update.

  2. Hy Ben,

    Nice feature. Searchlogic (and authlogic) is an amazing gem. I haven’t checked the source, but this feature is available using the “form_for @search” way?

    thanks

  3. Congrats Ben.

    Authlogic & Searchlogic have become the 2 gems that I install with every new Rails project.

    Being able to create complex searching forms like in many administration/back office web site parts in a few minutes is a killer feature.

  4. Rich says:

    This is a nice addition.

    I’m currently converting a large app that uses Searchlogic 1.6.6 to the latest 2.x. One thing that I’ve been trying to figure out is that in 1.6.6 there are some nice param helpers for links and forms (i.e., searchlogic_params, etc.) I use searchlogic_params extensively to maintain the current state of the params. This doesn’t seem to be available in 2.x. Am I just missing it?

    Thanks for all your awesome gems/plugins!!!

  5. Tim Harper says:

    The only thing that exceeds this project’s awesomeness is you. Seriously, SearchLogic is great. Thank you for it.

  6. [...] Using Searchlogic to combine named scopes with ‘OR’ – More method_missing goodies. [...]

  7. Eric Lubow says:

    Searchlogic is awesome and I am definitely making use of this new feature. However, I don’t think it works with associations. For instance, if I am working with an Address model and want to search the associated business name and description, I can’t do something like:
    s.text_field :business_name_contains_or_business_description_contains

    I ended up doing it with a named_scope, but this almost seems to defeat the purpose of Searchlogic.

    Is there something I am missing?

  8. mrkris says:

    By the way, I think *I* asked you for that feature before Ryan :)