Searchlogic released!

Searchlogic’s inspiration comes right from ActiveRecord. ActiveRecord lets you create objects that represent a record in the database, so why can’t you create objects that represent searching the database? Now you can! It’s searching, ordering, and pagination all in one.

Enough said, let me show you some of my favorite features. If you are still interested you can just jump over to the searchlogic github page for a more detailed explanation.

For the following examples lets assume these relationships: User => Orders => LineItems

Simple Searching Example

User.all(
  :conditions => {
    :first_name_contains => "Ben",          # first_name like '%Ben%'
    :email_ends_with => "binarylogic.com"   # email like '%binarylogic.com'
  },
  :per_page => 20,                      # limit 20
  :page => 3,                           # offset 40, which starts us on page 3
  :order_as => "ASC",
  :order_by => {:user_group => :name}   # order user_groups.name ASC
)

same as above, but object based

search = User.new_search
search.conditions.first_name_contains = "Ben"
search.conditions.email_ends_with = "binarylogic.com"
search.per_page = 20
search.page = 3
search.order_as = "ASC"
search.order_by = {:user_group => :name}
search.all

In both examples, instead of using the “all” method you could use any search method: first, find(:all), find(:first), count, sum, average, etc, just like ActiveRecord.

The beauty of searchlogic, integration with rails

Using Searchlogic in rails is the best part, because rails has all kinds of nifty methods to make dealing with ActiveRecord objects quick and easy, especially with forms. So let’s take advantage of them! That’s the idea behind this plugin. Searchlogic is searching, ordering, and pagination all rolled into one simple plugin. Take all of that pagination and searching cruft out of your models and let Searchlogic handle it. Check it out:

# app/controllers/users_controller.rb
def index
    @search = User.new_search(params[:search])
    @users, @users_count = @search.all, @search.count
end

Now your view.

# app/views/users/index.html.haml
- form_for @search do |f|
 - f.fields_for @search.conditions do |users|
  = users.text_field :first_name_contains
  = users.calendar_date_select :created_after # nice rails plugin for replacing date_select
  - users.fields_for users.object.orders do |orders|
    = orders.select :total_gt, (1..100)
  = f.submit "Search"

- if @users_count > 0
  %table
    %tr
      %th= order_by_link :account => :name
      %th= order_by_link :first_name
      %th= order_by_link :last_name
      %th= order_by_link :email
    - @users.each do |user|
      %tr
        %td= user.first_name
        %td= user.last_name
        %td= user.email

  Per page:
  = per_page_select
  Page:
  = page_select
- else
  No users returned

Things to notice

  1. Passing a search object right into form_for and fields_for
  2. The built in conditions for each column and how you can traverse the relationships and set conditions on them
  3. The order_by_link helper
  4. The page_select and per_page_select helpers
  5. All of your search logic is in 1 spot: your view. Nice and DRY.

See my tutorial on this example

Nifty methods for searching trees

Just like the conditions you automatically get with each column. You automatically get conditions for searching tree data structures, if you’re model is a tree data structure.

# User is a tree data structure.
conditions = User.new_conditions
conditions.child_of = User.roots.first                  # Finds all children
conditions.sibling_of = User.first                      # Finds siblings
conditions.descendant_of = User.roots.first             # Finds all children, grandchildren, etc
conditions.inclusive_descendant_of = User.roots.first   # Includes root + children, grandchildren, etc.

Any of these conditions can accept a User object or a User id.

Get Started

Check out the GitHub repository to get started:

http://github.com/binarylogic/searchlogic/

Or a tutorial I posted on using Searchlogic in rails:

http://www.binarylogic.com/2008/9/7/tutorial-pagination-ordering-and-searching-with-searchlogic

  • Share/Save/Bookmark


20 Responses to “Searchlogic released!”

  1. DONNELL says:

    Very Nice Site! Thanx!
    <a href= http://www.tdn-ns2.cn >Best Cards For People With Limited Credit History</a>

  2. Thanks for this !
    It sounds beautifull : I’m raring to try it in a real case application !

    There is a typo on the users_controler sample code : there is a missing closing square bracket on line 3, ending the params selection.

  3. Ben Johnson says:

    Good find! I fixed the typo. Let me know how using it goes. I love hearing feedback and am always looking to improve this.

  4. mollo says:

    Thanks Ben for sharing this nice plugin!

  5. Robert says:

    Thanks – this is indeed a very promising plugin.

  6. Tjerk says:

    Too bad this is all too slow, you want to compile your queries…., but that is a inherent problem of activerecord.

  7. Alex Gregianin says:

    I havent tested anything yet,but the idea sounds promising!I’m only worried about speed,as the guy above said this is not going as fast as it is supposed to be!I’m gonna do some benchmarks and comment here!

    Congratulations for the great work!

  8. Ben Johnson says:

    Thanks for the comments. Tjerk, I agree, but I am not trying to replace ActiveRecord, I am building on top of it. I leverage it for anything I can and try not to "recreate the wheel". I’m trying to keep this as simple and clean as possible. Alex, I did some benchmarks and they were positive. Since then I have made some minor changes, I will run some benchmarks and post my results, probably in the readme. Thanks for the feedback.

  9. Ben Johnson says:

    I posted my benchmarking file along with the results on pastie.org. You can check it out here: http://pastie.org/271935. There are still some other things I can do to improve performance, but this definitely should not slow down your application. I plan to work on it more in the next few days. Thanks!

  10. Oleg says:

    This plugin looks very promising. I’m tired of rolling half-assed searching/ordering code for every project. Thanks!

  11. piter says:

    Hello,

    Looks great. What about will_paginate? Can I use it as always?

  12. Cameron says:

    Very useful, was about to have to roll my own code doing exactly this, nice timesaver!

  13. ff says:

    i try your example and when i click on "search"
    i got this error:
    undefined method `nil_class=’ for #<UserConditions>

    what the metter?

  14. Ben Johnson says:

    FF, I am not sure. I would need a lot more information on this. Please go to lighthouse and create a ticket and I will be happy to help you out there. Thanks.

  15. Gregory says:

    Hello,

    Thanks for the great plugin!
    I’ve got one question however, concerning searching: does search methods support UTF-8 characters or ASCII only?

    Thanks, regards.

  16. Ben Johnson says:

    It supports whatever you have you system / database set up to support. It just sits on top of ActiveRecord and doesn’t really mess around with the character set. The only case where it could is in the keywords condition where it does some filtering. Even with that I account for foreign characters. Test it out, I am confident it will work properly with either character set, if it doesn’t let me know and we’ll get it working.

  17. Gregory says:

    Hello Ben,

    Thanks for a fast reply. Actually I did some testing and my previous question is related to them. Searching in my web-app does not work properly if some outside-ASCII character is included in the searched phrase. At the beginning I thought it is something wrong with my db (or rails) settings but I’ve tested your "searchlogic example" available here: <http://searchlogic_example.binarylogic.com/> and results were similar.
    If, say, I’d like to search ‘Zebra’ as the First Name Keyword, the app is returning 2 records which is OK. When I put ‘Żebra’ (with non-ascii character at the beginning) which is the Polish verb ‘to beg’ – it is not OK, because again 2 records are returned (the same records as in previous case). If I put the single letter ‘Ż’ as the First Name Keyword – all records are returned which suggests the app ignores non-ascii characters while searching.

    Anyway, irrespectively of what I wrote above, I think your plugin is really great.

    Thanks a lot,
    Gregory.

  18. Gregory says:

    Small note to my post above: searching works OK if I use searching condition ‘like’ instead of ‘keyword’.

    Gregory.

  19. Sumeet says:

    I am not sure as what i might be missing. But this is what I get, when i try to run the below on console…

    >> User.all
    NoMethodError: undefined method `all’ for #<Class:0×4597898>
    from C:/Working/InstantRails/ruby/lib/ruby/gems/1.8/gems/activerecord-2.
    0.2/lib/active_record/base.rb:1532:in `method_missing’
    from (irb):1

  20. Jérôme says:

    Hi,

    got the same issue as Sumeet
    something wrong in my code, surely, but what ? :)
    if you have any clue, it would be much apprecieted

    beside I really love your code and tutos
    thank you for your great job :)