Rails 3 Easy Search forms using SimpleForm and ActiveModel
For the sites I'm currently working on I have search pages all over the place for different resources, especially on the backend. In the past I would forego using form builders and just do some HTML to make a form GET the data. I hate HTML.
So I did some poking around to see what I could do to DRY up my time on creating these search forms. My first thought was to create a Search class and use active model, but it sucked because I everytime I had to create a new form I had to come into the search class and add a bunch of attr_accessors for all of the search fields. That sucks.
So I decided to mix it up with OpenStruct and ActiveModel
require 'ostruct' class Search < OpenStruct include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming def initialize(*args) super end def persisted? ; false ; end; end
Now I use this one model for searching of all of my resources.
I create the form super easily with SimpleForm:
= simple_form_for(@search, url: my_cool_path(), html:{method: :get}) do |f| = f.input :text = f.select :category, Product::CATEGORIES = f.input :minimum_price = f.input :maximum_price = f.submit :search
In your controller you are going to get a params[:search] hash with :text, :category, :minimum_price, :maximum_price.
Want to persist that search across page reloads?
class ApplicationController < ActionController::Base before_filter :persist_search protected def persist_search @search = Search.new params[:search] end end
Now you'll have a Search object in all of your requests with your user's search params. Use it as you will to return them the resources they are looking for.
*Side note*
I use the above logic for all of my resources, until one of my resources has a requirement like a validation. Then I break it into something like FlightSearch:
require 'ostruct' # ostruct for that lazy goodness class FlightSearch < OpenStruct # Get activemodel in there for all its cool functionality like model name, pluralization, validation, yada yada yada include ActiveModel::Validations include ActiveModel::Conversion extend ActiveModel::Naming validates_presence_of :origin_airport, :destination_airport # you can do cool things here, just make sure you call super so ostruct # takes all those hash params and makes them methods def initialize(*args) super end # ActiveModel needs to know that this wasn't persisted. def persisted? ; false ; end; end
January 8th, 2012 - 10:30
In search.rb, why is this necessary?
def initialize(*args)
super
end
Not trying to critique/criticize, just curious.
January 9th, 2012 - 11:29
I just left it in there and clipped out some code I had in that method. You don’t need it.