Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 620
Eric Avatar asked May 09 '12 20:05

Eric


2 Answers

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 %>
like image 138
cosborne Avatar answered Oct 06 '22 00:10

cosborne


No, you do not need to edit all your controllers.

You can use ApplicationController for all your "common" controller needs. Read up on it in the guides http://guides.rubyonrails.org/action_controller_overview.html and the API docs http://api.rubyonrails.org/classes/ActionController/Base.html

The key here is, when you generated your new rails app, you'll notice it created the file .../app/controllers/action_controller.rb and that class derives from ActionController::Base. Then, if you again use the rails generator to create a controller for your app, you'll notice your new controller class derives from ApplicationController (not ::Base). That means that the application_controller.rb is the parent controller class for your app. That means everything in it is available to all your app controllers. It's easy to abuse, so be judicious.

like image 22
pduey Avatar answered Oct 06 '22 00:10

pduey