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.)
Related
How can I call a method with a hyperlink on my index.html.erb?
I currently have a search field that allows the user to type in a keyword. This will search attributes in a model and display any that are found.
For example, I have records_controller.rb with this in it:
def index
#records = Record.search(params[:search])
end
app/models/record.rb has:
# Added for the search
def self.search(search)
where("title LIKE ? OR keyword LIKE ? OR description LIKE ?", "%#{search}%", "%#{search}%", "%#{search}%")
end
'title, 'keyword', and 'decscription' are attributes in the model.
app/views/records/index.html.erb contains a search form:
<%= form_tag(records_path, :method => "get", id: "search-form") do %>
<%= text_field_tag :search, params[:search], placeholder: " Search" %>
<%= submit_tag "Find" %>
<% end %>
On this same index.html.erb page, how can I add a hyperlink that displays all data from a model that contains a title I specify?
Such as displaying all rows that have the title "truck".
If the user clicks the hyperlink, it will display data
where('title LIKE "truck"', "%#{search}%")
I'm assuming I'll also need to put a new method in the record model such as:
# I'll have to play with this because I know it is wrong
# Added for the search
def self.searchtruck(search)
where('title LIKE "truck"', "%#{search}%")
end
This does what you're asking, creates a link with the param[:search] = 'truck'
<%= link_to 'Search for truck', records_path(search: 'truck') %>
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
At the moment I am trying to create a search within a project to bring up users depending on their region. From what I understand, I basically need to place the search params in the controller, the self.search method in the model, and then the form in the view.
In another project, I have a search but it shows all the options above and use the search to filter out those which do not match. For this situation, I do not want to list any users in the beginning. I want to use the search bar and bring up any users that match within that view page. Additionally I use Devise for users if that does make a difference. Here are my three regions of code:
Model (user.rb):
def self.search(search)
where("state ILIKE ?", "%#{search}%")
end
Controller (welcome_controller.rb):
def index
#users = User.all.order("created_at DESC")
#newusers = User.all.order("created_at DESC").limit(5)
#differentlocations = User.all.group_by(&:state).count
render :layout => 'with_newest_members'
if params[:search]
#users = User.search(params[:search]).order("created_at DESC")
else
#users = User.all.order('created_at DESC')
end
end
View (find.html.erb):
<%= form_tag(find_path, :method => "get") do %>
<%= text_field_tag :search, params[:search], placeholder: "Search Posts" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
Please let me know if you have any knowledge for me to help =) Any additional explanation would be greatly appreciated to help me understand, thank you!
Edit: I know I need to enter the results portion but I am confused about how/where to put it.
Joe
ANSWER:
The issue was in my controller because I had a render command prior to the search code. The controller should be:
def index
#users = User.all.order("created_at DESC")
#newusers = User.all.order("created_at DESC").limit(5)
#differentlocations = User.all.group_by(&:state).count
if params[:search]
#users = User.search(params[:search]).order("created_at DESC")
else
#users = User.all.order('created_at DESC')
end
render :layout => 'with_newest_members'
end
Fantastic =)
Two small things that might help:
1) In your Search model, I believe you have a typo in your search method. It should read as follows:
def self.search(search)
where("state LIKE ?", "%#{search}%")
end
You might also want to consider a more description name for your argument, such as state.
2) In your form, you don't need to explicitly write params[:search] anywhere. The params hash will be generated for you in the controller, with the name of the text_field as the key and the value inputted by the user as the value (see Ruby docs here). In this case, use :search as the name of the text_field_tag name.
<%= form_tag(find_path, :method => "get") do %>
<%= text_field_tag :search, placeholder: "Search Posts" %>
<%= submit_tag "Search", :name => nil %>
<% end %>
More on FormHelpers here.
I want to be able to search and update the index.
this is my controller method:
def index
if params[:search]
#ofertas = Oferta.search(params[:search]).paginate(page: params[:ofertas_page], :per_page => 5)
else
#ofertas = Oferta.all.paginate(page: params[:ofertas_page], :per_page => 5)
end
end
My search method in the model
def self.search(search)
where("titulo like ?","%w{search}%")
end
and this is the search form
<%= form_tag ofertas_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search], placeholder: "Procurar Entidades" %>
<%= submit_tag "Procurar", :name => nil %>
</p>
<% end %>
I've seen this setup in a number of search tutorials but no matter what I type nothing appears. Does someone know what I'm doing wrong?
It looks like you were trying to interpolate the search variable into the string, but didn't quite get the right symbol. How about this:
"%#{search}%"
Note the # instead of the w.
where("titulo like ?","%w{search}%")
should be:
where("titulo like ?", "%#{search}%")
#{xxx} is for string interpolation - it allows you to inject ruby (including variables) into a string.
"%xxxx%" is telling SQL that the search string can appear anywhere in the titulo column. '%' is a wildcard in SQL.
%w{xxx yyy zzz} is shorthand for ["xxx", "yyy", "zzz"] - an array in Ruby, which wouldn't mean much to the SQL as a string by itself.
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.