So I’ve tried Ezra’s “ez_where” and InVisible’s “where” plugins, but in the end I just couldn’t get past the hackish feeling I got when I used them.

I liked the concept that Ezra built—trying to make a domain-specific language for a where clause in Ruby—but the result felt like a heavy-weight addition to a small but common problem. In addition, I had trouble memorizing which Ruby operators mapped to which SQL operators in fringe cases.

Using InVisible’s “where” plugin was a bit of a relief, as it was lighter weight and the mapping was more direct; however, in order to test for a condition in the case where the column is in another table, I had to resort to a “send” method, like this:

    c = InVisible::Cond.new do
      send("permissions.value", params[:role])
    end

Which isn’t all that bad, but the inelegant solution gnawed at me for a while. Finally, I decided to make a “simplest-case” Condition class by re-using Ezra’s Cond class. The final outcome looks like this, and feels more Rubyesque to me:

    @invitees = @book.permitted_users \
      :conditions => Condition.block { |c|
        c << [ "permissions.value", params[:role] ] if params[:role]
      }

As with the InVisible::Cond class, you can do things like this:

cond = Condition.new do |c|
  c << [ "first_name", "like", "#{prefix}%" ] if prefix
  c << [ "verified", true ]
  c << [ "created_at", ">", 5.days.ago ]
end

cond.where
# => ["first_name like ? AND verified = ? AND created_at > ?", "dua%", true, "2006-10-18"]

users = User.find(:all, :conditions => cond.where)

My simple version of the plugin is available for download as a tar/gz file here.

Thanks to both Ezra and InVisible for their pioneer work!