I am working on a search function in Rails. I followed the following tutorial
http://railscasts.com/episodes/37-simple-search-form
I have therefore updated my tutorial.rb with the following
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
Updating my tutorials_controller.rb with the following
def index
#tutorials = Tutorial.search(params[:search])
end
Finally my view with
<div id="search">
<%= form_tag tutorials_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil, :class => "btn btn-success" %>
</p>
<% end %>
</div>
So it is all displaying. When I hit the search box I get the following error.
ActiveRecord::StatementInvalid in TutorialsController#index
SQLite3::SQLException: no such column: name: SELECT "tutorials".* FROM "tutorials" WHERE (name LIKE '%%')
Any help greatly appreciated. Still new to this and a little our of my depth. I can see that it is having problem getting information from the database but not sure how to cure it.
Cheers!
As per the error SQLite3::SQLException: no such column: name,
there is no column name in the tutorials table.
If you intended to search the tutorials table based on name field then add it to the tutorials table with a migration:
rails g migration AddNameToTutorial name
run rake db:migrate
Insert some records in Tutorial table with names.
Then, go ahead and search based on name field in tutorials table with your current code.
Second option is, if you intended to search tutorials table based on some other existing field then just update the search method as below:
def self.search(search)
if search
find(:all, :conditions => ['fieldname LIKE ?', "%#{search}%"])
else
find(:all)
end
end
where replace fieldname with the attribute name that you want to search on.
Related
I am creating a rails app where I have implemented the following search function.
application.html.erb
<div class="searchbar">
<%= form_tag(articles_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: " Search", :class => "search_form" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
</div>
article.rb
def self.search(search)
where("title LIKE ? OR creator LIKE ? OR description LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%")
end
articles_controller.rb
def index
#articles = Article.all
if params[:search]
#articles = Article.search(params[:search]).order("created_at DESC")
else
#articles = Article.all.order("created_at DESC")
end
end
This allows me to search for all primary resources but does not include nested resources in the search results. Is there a way to include these resources within the same function?
You'd need to do some joins, and define a syntax for passing the relevant join info into your search method.
This can get complicated pretty quick, and I'd highly suggest you don't reinvent the wheel and use an existing solution such as ransack. This will let you do things like
Article.ransack(title_cont: "code", author_name_cont: "bob").result
where, in this example, Author is its own model, associated with Article, and containing the field name.
It also plays very nice with views and forms, so you can very easily implement search forms without having the manually key everything up to the right association and field.
(Personally I'm not in love with their concatenation syntax but it gets the job done.)
I set up a search mechanism for my Procedure table following this railscast http://railscasts.com/episodes/37-simple-search-form?autoplay=true. I pretty much followed it exactly but I get this error when I submit the search:
ActiveRecord::RecordNotFound at /procedures
Couldn't find all Procedures with 'id': (all, {:conditions=>["name LIKE ?", "%Emergency%"]}) (found 0 results, but was looking for 2)
I want to search for Procedures by name, and this error makes it look like it is searching by id?
Here is the view:
<%= form_tag procedures_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search], :id => "welcome-search" %>
<%= submit_tag "Search Procedures", :name => nil, :class => "btn btn-success btn-lg" %>
My controller:
def index
#procedures = Procedure.search(params[:search])
render `procedures/index`
end
My model:
def self.search(search)
if search
find(:all, :conditions => ['name LIKE ?', "%#{search}%"])
else
find(:all)
end
end
I'm pretty confused since the railscast makes it look so easy to get working..Thanks.
find(:all) is very old and is no longer available since rails 3.2. Instead use where:
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
all
end
end
I have a simple search working in my rails app, but it only searches a single column of my table. I'm trying to add a simple dropdown menu with options like "last_name" and "city" so the user can select the column to search.
In my view I have:
<%= form_tag teachers_path, :method => 'get', :id => "teachers_search" do %>
<%= hidden_field_tag :direction, params[:direction]%>
<%= hidden_field_tag :sort, params[:sort]%>
<p>
<%= text_field_tag :search, params[:search], placeholder: 'First Name' %>
<%= submit_tag "Search", :first_name => nil %>
</p>
<% end %>
and in my model:
def self.search(search)
if search
where('first_name LIKE ?', "%#{search}%")
else
scoped
end
end
Any help greatly appreciated.
You can add a select_tag for your drop down menu
<%= select_tag "search_from", "<option>first_name</option><option>last_name</option><option>city_name</option>".html_safe%>
In your controller you can pass the value in params[:search_from] to your search method. and modify it to include the column name
def self.search(search, column_name)
if search
where('? LIKE ?', column_name, "%#{search}%")
else
scoped
end
end
I've written it in a crude way but i hope it gets the message along.
extending #sohaibs's answer dropdown is a good idea if you are only allowing user to filter result with some some fixed attributes
views
<%= select_tag "search_by", options_for_select(['first_name','last_name','city'].map{|o| [o.humanize,o] }) %>
<%= f.text_field 'search' %>
controller
def search
User.search params[:teacher][:search_by],params[:teacher][:search]
end
and model
def self.search(search_by,search_value)
where('? LIKE ?', search_by, search_value)
end
Awesome Rails :)
Have you tried:
def self.search(column, search)
# some logic
where('? LIKE ?', column, "%#{search}%")
# some logic
end
I currently have a basic search that will allow me to type in a word and it will return back all records that are like that search. It is as followed:
application.html.erb
<%= form_tag games_path, :method => 'get' do %>
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag t('.searchb'), :game_name => nil %>
<% end %>
controller and Model
#games = Game.search(params[:search])
def self.search(search)
search = search.to_s.strip.split
search.inject(scoped) do |combined_scope, search|
combined_scope.where(['game_name LIKE ? OR genre LIKE ? OR console LIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
end
end
What I now wish to do though is the ability to enter multiple words in to the search bar and have it return all related records to those words rather than any record that has them all.
e.g. If I type fighting, action
I want it to return all fighting games and all action games.
How would I go about implementing this?
Model:
EDIT
You should use a fulltext search engine like Sphinx for this! There is a gem called thinking-sphinx wich offers an interface between ruby and the Sphinx server! The only downside is that you need to update the database periodly. It doesnt support live updates.
You have to take the key words, loop them and create queries to achieve this. You can use inject to make it easy. This might help.
I set up a simple search as instructed in part of railscast #240.
in controller
#reports = Report.search(params[:search]).order('created_at DESC').paginate(:page => params[:page], :per_page => 5)
in model
def self.search(search)
if search
where('apparatus LIKE ?', "%#{search}")
else
scoped
end
end
in view
<%= form_tag reports_path, :method => :get do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil %>
</p>
<% end %>
it all works... but...
I have a few records for example, one with "another time test" and another with "last test of time"
if i search "test" the first comes up but the second doesn't, and if i search "time" the second comes up but not the first. It is only seeing the last word of the record.
what gives?
You need to put a percent sign on both sides of the search term. Like so:
where('apparatus LIKE ?', "%#{search}%")
By putting the percent sign before the search term, you're leaving everything before it as a wildcard. However, you're also saying, by not putting after the search term, that nothing after this should be considered a wildcard. That's why it only matching the last word.