Search multiple models at once with Ransack - ruby-on-rails

I have a search form in the header of my app and I would like to use this search form to search through multiple models within the application.
For example a request like /search?q=rails should trigger a search through multiple models like Work, Project, User and their defined attributes. I wanted to use Ransack because I already use it on the Work model in a different area of the app.
I think I don't quite understand Ransack yet and the documentation always points out that you have to define #q = MyModel.search(params[:q]) to use it in the form search_form_for #q. Is there a way where you don't have to define a specific model in advance? And just pass in the parameter name like search_form_for :q?

Okay, after asking the question the answer popped into my head.
Instead of the search_form_for helper I'm now just using the form_tag helper in the following way:
<%= form_tag search_path, method: :get do %>
<%= text_field_tag :q, params[:q] %>
<%= end %>
and in the search action I just do:
q = params[:q]
#works = Work.search(name_cont: q).result
#projects = Project.search(name_cont: q).result
#users = User.search(name_cont: q).result
This works for me. I hope this also helps someone else.

Related

ruby on rails search form

I'm new to RoR and I've managed to make a basic search form but keep getting errors when trying to expand the search tags (name).. I have a model with various data (location, website, email, telephone) and was wondering how I can add these to my current search code.
/models/ciir.rb
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
static_pages_controller.rb
def home
#ciirs = Ciir.search(params[:search])
end
/home.html.erb
<%= form_tag ciirs_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag " Search Database Records ", :name => nil %>
</p>
<% end %>
When clicking the submit button (no search terms) the url is:
ciirs?utf8=✓&search=
but when modifying the name condition to something like 'website' the url changes to
ciirs?utf8=✓&search=&commit=+Search+Database+Records+ –
Since you mentioned you are new to RoR, I must share the way I learned RoR was reading, using and analyzing one issue at a time. I would suggest you to take a look at following points one at a time and try & learn how RoR treats them and how these fit your question:
How form_tag works?
How text_field_tag works?
Once you have understood form_tag, difference between text_field_tag and f.text_field?
How params objects are created, and it uses names of form controls?
How and when to use GET and/or POST form methods? Inadvertently, what are different types of method and when to use them?
How URL are used in the form_tag and what components are they made of?
Sprinkle a bit of knowledge of Ruby language by learning between Arrays and Hashes? In fact, learn Ruby as much as you can.
Answering your question,
/home.html.erb
<%= form_tag "/static_pages/home", :method => 'post' do %>
<p>
<%= text_field_tag "search[name]", params.has_key?("search") && params[:search].has_key?("name") ? params[:search][:name] : "" %>
<%= submit_tag " Search Database Records " %>
</p>
<% end %>
/models/ciir.rb
def self.search(search)
if search
find(:all, :conditions => ["name LIKE '%?%'", search[:name]])
else
find(:all)
end
end
So I modified your form, and told RoR about search params containing data for name.
params is a Hash (which is a key-value pair) having key named search, which further is a Hash having key named name.
The same principle is followed in the model code. We passed the Hash of key search to the function and in there, used the value of key named name.
I also updated the url in form_tag, to point it to home action of your controller. Assuming that you have added it to your routes.rb file, it usually follows the pattern controller_name/action_name or the function name action_name_controller_name_path or action_name_controller_name_url. Run rake routes command at your root directory to list out all paths in your application.
Also note, I used POST method instead of original GET. You may wish to use GET here, so please change it back.
I hope this works.
I found no error in your code. the url changed to ciirs?utf8=✓&search=&commit=+Search+Database+Records+ is normal. submit_tag generates a button named "commit" defaultly, it will be parsed in the params. I see you add :name => nil , it will fix the problem, the other part of your code needn't to be modified. I copied your code and tested it, it ran smoothly.

using Bootstrap Navbar Search with form_tag to redirect to resource index with search params

I'm trying to put a quick keyword search in my navbar, using Bootstrap's Navbar Search component. Currently this is using a form_tag as follows
<form class="navbar-search pull-left">
<%= form_tag(recipes_path, :method => :get) do %>
<%= text_field_tag :keywords, nil,
{:class => "search-query", :placeholder => "recipes quick search"} %>
<%= hidden_field_tag :use_keywords, "true" %>
<%= hidden_field_tag :wide_search, "true" %>
<% end %>
</form>
This is for a recipe lookup. I'm using the form to (try to) get keywords, which will be passed as params to the search, which resides in the recipes index action.
def index
if params[:wide_search].present?
#search = Search.new
#search.use_keywords = params[:use_keywords]
#search.keywords = params[:keywords]
... (more params for other search types)
if params[:wide_search] == "true"
#recipes = #search.wide_search
elsif params[:wide_search] == "false"
#recipes = #search.narrow_search
end
#recipes = #recipes.paginate(:page => params[:page])
else # no params, just index all
#recipes = Recipe.paginate(:page => params[:page])
end
end
Note that "Search" is a ruby class. I was thinking of making it into a full-blown resource so I could create and view old searches (maybe they could be looked at to offer suggested searches based on past history, etc), but decided against it. I still dunno if that was a good idea or not. If it was an actual resource, it could have RESTful actions and maybe save some problems. This is not my actual problem, but does anyone have suggestions for this?
Sorry, back to the actual problem -- From the root page or wherever, I would like to be able to type in keywords, press the enter key (within the search bar) and have it redirect to the Recipe Index with the params needed so it can run the search and display the results.
Right now, if I go to the index page and do this, it works fine. BUT, if I'm in any other page (like the root page, or wherever) and try to type keywords and press enter, it just reloads the current page, although I do see the params in the URL. So it's not redirecting to Recipe Index. I must be missing something, but I'm not sure what. I'm kind of suspicious of the form_tag since there's no actual submit button. But then it works when I'm in the index page, so I dunno. Any suggestions appreciated!

I need a very simple search gem for just searching the partyname on a sqlight3 database?

My party registry Rails 3 app needs a search function for visitors to search a partyname and then be able to click on the party and go to the show page of that party. Must be very simple ajax list that pops up without reloading etc.
The app is almost done and runs off a sqlight3 database.
Any suggestions - tried all the RailsCasts ones and nothing fits right 100%.
Thanks in advance.
I think you want two different things.
1) To create a simple search you can do something like this.
2) To autocomplete while typing (partyname for example) you can use the autocomplete gem.
You must decide which approach you want to follow.....
I hope if helps in some way...
EDIT - to show how to implement the simple search.
let's say you have a model called Party
your form (index page for example):
...
<%= form_tag parties_path, method: :get do %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", name: nil %>
<% end %>
...
#display results
<% #parties.each do |party| %>
...
<% end %>
model Party:
...
def self.search(search)
# if search is not empty
if search
find(:all, :conditions => ["partyname LIKE ?", "%#{search}%"])
# if search is empty return all
else
find(:all)
end
end
...
controle parties_controller:
#parties = Party.search(params[:search])
Try smart_search gem
gem install smart_search
Does everything that needs to be done to make your model searchable!

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!
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 %>
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.
Looks like this is not possible. This is a comment from Ernie the gem author.
You'd have to handle the Ransack-required stuff in a before_filter or
(ick) in the view partial itself. If you're putting a search field on
every single part of the site, I'd recommend you strongly consider
whether ransack is the right tool for the job, as well. You might want
some sort of inverted index search setup like sphinx, solr, etc.
https://github.com/ernie/ransack/issues/3

Using one search form to search multiple models

I am working a simple rails app and i would like to know how possible it is to use one search form to search inside multiple models. like i have a story model and a book model. this search form should be able to search the both models with a single parameter.
<%= for_tag :url => search_path %>
<%= text_field_tag :q %>
<% end %>
How can i make this search from work for multipple models
Whatever search you need to do, is done inside an action in a controller. You could basically create a controller, say search_controller and have an action say, item
def item
if params[:q]
#found_stories = Story.find_all_by_...(params[:q])
#found_books= Book.find_all_by_...(params[:q])
end
end
Then you could use the objects #found_stories and #found_books in your view to show the search results.
This is just an example of how you could do to fulfill your requirement.
Thanks.

Resources