A collection of computer systems and programming tips that you may find useful.
 
Brought to you by Craic Computing LLC, a bioinformatics consulting company.

Showing posts with label searchlogic. Show all posts
Showing posts with label searchlogic. Show all posts

Wednesday, October 27, 2010

Searchlogic versus MetaSearch and Rails3

Searchlogic is a great Rails gem for basic searching of your tables. I've used it for quite a while now. Problem is that at the time of writing (October 2010) it does not work with Rails3.

You can install it just fine but starting up your server will produce and error like this:
/Users/jones/.rvm/gems/ruby-1.9.2-p0/gems/activesupport-3.0.1/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method': undefined method `merge_joins' for class `Class' (NameError)


What to do? Well there is an alternative search gem called MetaSearch that has a very similar interface to Searchlogic and which does work with Rails3. In fact it may be a little better.

In my code I have search code in three places - the index action of my controllers, a search form at the top of my index view pages and column headers on my index view pages that will reorder the matching rows when I click on them.

So here are the three code blocks in Searchlogic and then MetaSearch (with a very simple model where I'm simple searching the name column). Note that I'm using will_paginate in both cases.

Controller Index Action

Searchlogic
  def index
@search = Product.search(params[:search])
@search.order ||= :ascend_by_name
@products = @search.all.paginate :page => params[:page], :per_page => 20
end

MetaSearch
  def index
@search = Product.search(params[:search])
@search.meta_sort ||= 'name.asc'
@products = @search.all.paginate :page => params[:page], :per_page => 20
end

View Index Page Search Form (omitting some of the html formatting)

Searchlogic
<% form_for @search do |f| %>
<p>SEARCH</p>
<p><%= f.label :name_like, 'Name' %>
<%= f.text_field :title_like, :size => 15 %>
<%= f.submit "SEARCH" %>
<%= @search.count %>Matches</p>
<% end %>

MetaSearch - NO CHANGE!

View Index Page Column Headers (just showing a single column header)

Searchlogic
<%= order @search, :by => 'name', :as => 'name'.humanize %>

MetaSearch
<%= sort_link @search, 'name', 'name'.upcase %>

All in all, a pretty straightforward replacement.

But there is at least on additional bonus, over and about working with Rails3. 'attr_searchable' and 'assoc_searchable' allow you to specify in your models exactly which fields can and cannot be searched. Searching in either Searchlogic or MetaSearch uses GET requests which display the search parameters in the URL in the browser. That opens the door to people trying out other likely field names and searching otherwise private data. This mechanism provides a way to limit that problem.

I have no doubt that searchlogic will get updated soon, as so many people use it. But until then MetaSearch is the way to go.


 

Wednesday, March 10, 2010

Rails searchlogic and confusing column names

Searchlogic is a great Rails gem from Ben Johnson for adding model search capabilities to your Rails app with a minimum of effort.

You can build complex queries very easily such as Company.name_like_or_address_like.

But if you have column names that contain the Model name you can run into problems.

For examples, let's say my Company model has columns 'company_name' and 'company_address', then my query becomes:
Company.company_name_like_or_company_address_like

It gets worse is my Person model has_one :company and I want to search companies through that model - now my query becomes
Person.company_company_name_like_or_company_company_address_like()

Not only is that ugly as sin, it may cause searchlogic to barf when you use it in a search form.

My experience is that it can handle ugly queries like this when run in script/console but for some reason they may fail in the context of a real Rails app.

So what can you do about it?

The best solution is to change the names of your columns to remove the model names, but that is not always possible, especially in legacy databases.

Failing that, you can create a named scope in your model that performs the same query but uses a shorter, more sensible name. Searchlogic will use your named scopes quite happily.

In my example I would create a named scope in the Company model like this:

named_scope :company_name_address_like, lambda { |name|
  { :conditions => ['company_name like ? or company_address like ?', "%#{name}%", "%#{name}%"] }
}

I can then call it as Company.company_name_address_like().

Don't be tempted to include 'or','and', etc. in your custom named scope names. Searchlogic appears to try and split up the scope into components based on these 'operator' words.


 

Archive of Tips