Search code examples
ruby-on-railsruby-on-rails-3model-view-controllerruby-on-rails-3.1ransack

ransack search form in header partial: No Ransack::Search object was provided to search_form_for


First of all, I'm new to RoR, so the answer may be obvious, in which case I apologize. I've looked around and haven't found anything that helps.

I'm trying to have a search form at the header of every web page on my app that will search through the names of all my "buckets". Here is the relevant code:

In app/views/layouts/_header.html.erb (within a nav bar):

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

In app/controllers/buckets_controller.rb:

def index
  unless params[:q].blank?
    @q = Bucket.search(params[:q])
    @buckets = @q.result.paginate(:page => params[:page])
  else
    @buckets = Bucket.find(:all, :limit => 5).paginate(:page => params[:page])
  end
end

I understand the last part isn't that great: what I'm trying to do is if I'm just accessing the bucket index page (not by searching), i display the 5 most recently created buckets. When I search for something in the header form, I access the index page but only show the buckets that hit the search. (would a better way to handle it to have a search page separate from my index page?)

I found this issue which is pretty much identical, but I still don't see how I handle @q if every page is going to have the form on it--surely I don't have to alter every controller's every action?

Sorry in advance for any frustration my noobishness my cause you!


Solution

  • As others have said, you need to utilize the ApplicationController's before_filter. Though ernie himself seems not to recommend this, the implementation is simple.

    First, use the advanced Ransack options to set your path for your search thusly

    #config/routes.rb
      resources :buckets do
        collection do
          match 'search' => 'buckets#search', via: [:get, :post], as: :search
        end
      end
    

    Second, update your BucketsController to include the following custom action:

    #controllers/buckets_controller.rb
      def search
        index
        render :index
      end
    

    Nothing yet out of the ordinary. If you currently try to search you will get the error from your original question. Your definition of the variable q is correctly implemented, but you will have to move it to the ApplicationController like so:

    #controllers/application_controller.rb
    before_filter :set_global_search_variable
    
      def set_global_search_variable
        @q = Bucket.search(params[:q])
      end
    

    Finally, update your search form to pass in the correct search options

    #layouts/_header.html.erb
    
        <% search_form_for @q, url: search_buckets_path, html: { method: :post }  do |f| %>
          <%= f.label :name_cont %>
          <%= f.text_field :name_cont %>
          <%= f.submit %>
        <% end %>