Ransack (neé Metasearch) is brilliant at providing ad hoc table searches for users, but handling all the possible ActiveRecord associations can require workarounds. However, it is bonehead simple to use with a single table. So, we’re going to give it one.
Views are Read-only Tables
A lot of the problems posted on StackOverflow happen when we use associated table fields. An employee has_one section, and we want to filter/sort by the section name. That kind of thing.
I find it’s simpler to avoid the whole issue. I have a demo running at http://search-results-demo.herokuapp.com/ The Employees Search (the landing page) uses results from four different tables, one used twice with an alias, and from another view. It ought to be a nightmare, but it’s actually simple, because it’s using a single virtual table (a Postgresql view.)
There are some other features implemented in the demo, but they’re for future tutorials. You can ignore them, for now.
I wouldn’t use a view for editing, but we only need to show/sort/filter. The view joins any associated tables and makes their columns look and act like native columns in a table.
A view will play nicely with Ransack, because it looks to Rails just like a single table.
How nice it is to get a table with all the columns renamed, all the text concatenation done, all the columns from associated tables sortable and filterable — yum! Null handling is another nice feature: nulls can be shown as “NULL” or “Inactive” or whatever you like, or left as nil values.
Creating/Editing a view in PostGreSQL:
I like to name my views “fil_whatever” (filter), and columns from joined tables as “whatever_disp” if several tables have columns with the same name. For example, if the “sections” and “divisions” tables both have a ‘title’ column, I’d rename them to section_disp and division_disp. I usually include the ‘whatever_id’ columns as well, so that my associations work, although I seldom use them.
That sql will produce a virtual table in PostGreSQL. The view can be used as though it were a table in its own right:
Gives results like:
So, we have pulled four tables and another view and an alias into one do-it-all table. However, as far as Rails is concerned, it is just another table, except:
- It doesn’t show up in your schema.rb
- You need to add a couple of lines to the model to let Rails find the table.
Here’s the controller:
and here’s the view:
There you have it. For my money, that’s a lot easier than fiddling :joins, :includes, scopes, etc. in Rails. YMMV, of course.