Ransack, the library formerly known as MetaSearch 2.0


A couple of nights ago, I pushed Ransack to GitHub. What's Ransack? Well, previously I was calling it MetaSearch 2.0, and it's a complete rewrite, not unlike the MetaWhere 2.0 development in the rewrite branch (a name change is also forthcoming for MW 2.0, if you're curious). Why change names? A few reasons:

The current name sucks

Let's get this one out of the way early. I chose the name for MetaSearch as a minor tie-in to this blog's URL, and because "metasearch" was a real word. The downside? The real meaning of "metasearch" is something entirely different, but still search-related. This means the name is unintentionally misleading.

"Ransack" is an awesome word

It just is. Come on. Plus, this morning I saw this in my GitHub stream, which just screams with anarchic excellence.

Freedom to reinvent

There are going to be a whole lot of changes between how Ransack works, and how MetaSearch worked. A name change frees me up from preconceptions in a way that even a major version number increment just can't do. Since I've already established that the old name sucked, it was an easy choice.

Changes? What kind of changes?

I'm still sorting those out.

The most obvious, though, will be an attempt at decoupling the library from ActiveRecord as much as possible. I'm not intimately familiar with DataMapper internals, but my aim is to give someone who is familiar with DM the tools they need to make this happen, via a suitable context. To support this change, I won't be making any assumptions about what should be delegated to the underlying AR::Relation anymore -- because it may not even be a relation. You'll get at the search result object by calling @search.result, and you can do with it whatever you like. The goal of any adapter's context should be to return an object that makes sense for this adapter.

Additionally, I'll be rethinking the way that associations and attributes are authorized for search, and how to approach custom search methods.

The biggest change, though, is the move toward enabling more complex search forms through Rails' support for nested attributes in parameters. While Ransack will continue to support ghost methods for setting search parameters in a simple fashion, such as...

    <%= search_form_for @q do |f| %>
      <%= f.label :title_contains %>
      <%= f.text_field :title_contains %>
    <% end %>

...it will be adding support for building up a query using collections that largely mimic the way that ActiveRecord's nested attributes work with fields_for, matched with some customized form helpers. For example:

    <%= search_form_for @q, :url => search_people_path, :html => {:method => :post} do |f| %>
      <%= content_for :document_ready do %>
        <%= grouping_templates f %>
      <% end %>

      <%= f.sort_fields do |s| %>
        <%= render 'sort_fields', :f => s %>
      <% end %>
      <p><%= link_to_add_fields "Add Sort", f, :sort %></p>

      <%= f.condition_fields do |c| %>
        <%= render 'condition_fields', :f => c %>
      <% end %>
      <p><%= link_to_add_fields "Add Condition", f, :condition %></p>

      <%= f.and_fields do |n| %>
        <%= render 'and_fields', :f => n %>
      <% end %>
      <p><%= link_to_add_fields "Add And", f, :and %></p>

      <%= f.or_fields do |o| %>
        <%= render 'or_fields', :f => o %>
      <% end %>
      <p><%= link_to_add_fields "Add Or", f, :or %></p>

      <%= f.submit %>
    <% end %>

The bad news: nested attributes make for some seriously verbose parameters, which means we need to submit via POST instead of the more RESTfully-correct GET. :( The good news? Advanced search forms with functionality like this (excuse the ugly -- this is a proof of concept, not a fashion show):

This will allow you to provide advanced search form capabilities that are far beyond what is easily possible with MetaSearch, today.

That's all I've got, for now. Thanks for reading/watching!

comments powered by Disqus