I am trying to have two search fields, that however end up combining the two results.
In one filed you can search for the location of a listing and in the other for a keyword, which will look for title and description of the listing.
When a location and keyword is entered, listings that match both the location and keyword should show. So if I enter San Francisco and Retail, only listings located in SF and with the description or title Retail should pop up.
Feng Chen suggested to do this in one query by the following:
self.where("location like ? and (title like ? or description like ?)", query, query)
However this does not show a result that matches both the location and the keyword(title, description).
Do I need to change something in my view or anywhere else?
Here is what I have listing.rb
def self.locsearch(search)
query = "%#{search}%"
if search
self.where("location like ? and (title like ? or description like ?)", query, query)
else
self.all
end
end
end
Static_pages_controller.rb
def home
#listings = #listings.locsearch(params[:search]) if params[:search].present?
home.html.erb
<%= form_tag findjobs_path, :controller => 'listings', :action => 'locsearch', :method => 'get' do %>
<p>
<%= text_field_tag :search, "location" %>
<%= text_field_tag :search, "keyword" %>
<%= submit_tag "search" %>
</p>
</div>
<% end %>
You need a descsearch method in your listing model and you need to do
# Right now you have #listings = #listings.locsearch(...)
# You need #listings = Listing.locsearch(...)
#listings = Listing.locsearch(params[:search][:location], params[:search][:keyword])
And in your listing model
def self.locsearch(location, keyword)
location = "%#{location}%"
keyword = "%#{keyword}%"
if !location.bllank? && !keyword.blank?
self.where("location like ? and (title like ? or description like ?)", location, keyword)
else
self.all
end
end
end
If you are using a postgres database, you could try to use the full text search feature to do the above. There is gem pg_search enter link description herewhich will allow you to do so easily. The overhead incurred would be trivial and would provide you greater flexibility in this search problem and any such other ones you might have to solve later.
Related
I'm following Railscast: http://railscasts.com/episodes/37-simple-search-form?autoplay=true
The result shows well in my implementation. But because I have first_name and last_name columns instead of just "name" as in the example above, I need a way to search for both no matter what the search term is. How can I do this? Right now only first name search works.
user.rb
def self.search(search)
if search
where('first_name LIKE :search OR last_name LIKE :search', search: "%#{search}%")
else
all
end
end
people_controller, index function:
#users = User.search(params[:search])
index.html.erb (for people controller):
<%= form_tag people_path, :method => 'get' do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag("Search users", first_name: nil, last_name: nil) %>
</p>
<% end %>
<ul>
<% #users.each do |user| %>
<li>
<%= link_to profiles_path(user_id: user.id) do %>
<%= user.first_name %>
<%= user.last_name %>
<% end %>
</li>
<% end %>
</ul>
UPDATE:
So this is weird. I have 4 users. For the first 3, only first name search works. Last name or full name (or partial name) doesn't. For the last user, only last name search works.
...what could be going on? Just made three more users and tested. The first new user got searched only by first name. The second new user got searched by only last name. His first name is part of the last name of 3rd user, and that 3rd original user name was returned when searched by that new user's first name (...why? didn't work like this before; partial name search doesn't work for other users). And third user's last name only was searched.
UPDATE:
OK, didn't do anything. But now the first original's user gets searched by either last name or first name (only first name before). WHY? Second original user as well. And partial search for two users works now. WHY? And the last new user whose last name (only) was searchable is now not searchable by any. WHY?
And tried it again just now and returned to previous, searchable by first name only, no partial search, etc. Why is this keep changing? How can I make the search term simply search for either first name or last name or both?
UPDATE:
I got the answer (to the above, not in general). The search is CASE-SENSITIVE. Now my question is: how can I make it non-case-sensitive and have the search term that includes both first name and last name (eg "Tom Paulson") work? (right now only searching for either works)
UPDATE:
So I solved case sensitivity by changing LIKE to ILIKE. I'm using Postgres.
If you could help with searching for both first name and last name, I'd appreciate it!
UPDATE:
So I'm now using this to search for both or either first name and last name. But now partial search does not work. Is there a way to make that work here as well?
where("first_name ilike :search or last_name ilike :search or first_name || ' ' || last_name ilike :search", search: "%#{search}")
UPDATE:
Solved it by adding % to %#{search}
%#{search}%
The case seems resolved. Thank you! I will maybe post an answer later.
UPDATE:
ooh, you wanted to search in both columns.
one way is to use 'concat'.
assuming you put a space in between first and last name:
where("CONCAT(first_name, ' ', last_name ) ILIKE ?","%#{search}%")
FIRST ANSWER:
def self.search(search)
if search
buff=search.downcase
where('lower(first_name) LIKE ? OR lower(last_name) LIKE ?', "%#{buff}%", "%#{buff}%")
should be working.
or ILIKE if you prefer.
where('first_name ILIKE ? OR last_name ILIKE ?', "%#{search}%", "%#{search}%")
can you check the value of 'params[:search]' if it is not nil?
I am new to Rails, but slowly making progress. I can't quite wrap my head around how to achieve my next task.
I have a controller (IdeasController) with an index that looks like this:
def index
if params[:round].blank? && params[:challenge].blank?
#ideas = Idea.all.order(params[:sort])
# #ideas = Idea.all.order(created_at: :desc, cached_votes_up: :desc)
end
if params[:round].present?
#round_id = Round.find_by(name: params[:round]).id
#ideas = Idea.where(round_id: #round_id).order("created_at DESC")
end
if params[:challenge].present?
#challenge_id = Challenge.find_by(name: params[:challenge]).id
#ideas = Idea.where(challenge_id: #challenge_id).order("created_at DESC")
end
end
I am updating the view and filtering by category with the above :round and :challenge with the code below in my index.html.erb:
<%= link_to "All", ideas_path %>
<% Round.all.each do |round| %>
<%= link_to round.name, ideas_path(round: round.name) %>
<% end %>
<% Challenge.all.each do |challenge| %>
<%= link_to challenge.name, ideas_path(challenge: challenge.name) %>
<% end %>
Now, my problem is that I want to create a button that orders by created_at DESC or ASC. I want the button to essentially be a toggle. I also want another button to order by cached_weighted_average DESC or ASC. This is from acts_as_votable so I can sort by vote counts.
The problem I am running into is that I can create a link or button that orders by created_at or cached_weighted_average, but it replaces all of the URL that was previously filtered by :round or :challenge. For example, if a user clicks "Round 1" and sees all ideas marked for "Round 1" and then they click the link to order by cached_weighted_average, the URL replaces:
/ideas?round=Round+1
With this:
/ideas?sort=cached_weighted_average+ASC
What I want is:
/ideas?round=Round+1&?sort=cached_weighted_average+ASC
I know this is a very new question, but everything I have tried has failed so far. It feels like I am missing something very easy. What I noticed I can do easily is inside the controller I can do something like:
if params[:round].present?
#round_id = Round.find_by(name: params[:round]).id
#ideas = Idea.where(round_id: #round_id).order("cached_weighted_average DESC")
end
Which is perfect. This button just needs to switch between cached_weighted_average DESC and created_at DESC.
Any help is appreciated, thanks.
passing multiple parameters is one way to handle:
<%= link_to object.name, object_path(first: something, second: something_else) %>
then alter your conditionals to contemplate presence of multiple params.
to differentiate between round and challenge when attempting to allow the user to choose how they'd like to sort you could use the same name and then pass it different values.
something like:
params["round_or_challenge"]
this would change your conditional to something like:
if params["round_or_challenge"] == "round" && params["asc_or_desc"] == "asc"
# query
elsif params["round_or_challenge"] == "challenge"
# query
end
or whatever. it's basically the same...just pass the values you need. you can also pass the existing parameters from the view the same way you access them in the controller.
Thanks for the response, #toddmetheny. I didn't implement your solution, but your solution helped me understand passing multiple parameters a bit more.
I ended up creating a helper, sortable. I also used the url_for to append at the end of whatever the current URL might be. I liked this approach because it meant I could sort on any parameter. I'm not sure that it's the best solution, but it works.
def sortable (name, sort)
link_to name, url_for(params.merge(sort: sort))
end
I have a very simple, typical search form in rails. Input a string, and it checks a column for that model if any strings match it. A few weeks ago it was working just fine. I came back today, and suddenly doesn't work.
Here is my code. My search form:
<%= form_tag("/search/products", method: "get") do %>
<%= label_tag(:q, "Search for:") %>
<%= text_field_tag(:q) %>
<%= submit_tag("Search") %>
<% end %>
My Controller:
def search
term = params[:q]
puts "the term is #{term}"
#resultats = Product.search_products(term)
end
In my model, the search_products method:
def self.search_products(search_term)
if search_term == ""
return []
else
where("name LIKE ?", "%#{search_term}")
end
end
in the controller code, the puts "the term is #{term} prints the correct term every time. So I know that is being picked up correctly. just, when i search for something, it doesn't return the correct results. Here is a screenshot from my terminal:
"Les résultats sont" in the terminal means "the results are..." and then empty, because it returns nothing. What could be wrong here?
Your code currently searches for LIKE '%term' (string must end in term)
You probably need to have it search for LIKE '%term%' (string must contain term)
Just add a %:
where("name LIKE ?", "%#{search_term}%")
Why don't you do lower(?) and search_term.downcase to make sure its not case sensitive
I am working on a search with two text fields. It searches for two things (right now location and description) and only shows the entries (listings) that match both of them.
I would like the second text field to also search for title, so it should look for description and title. How would that work?
This is what I have right now
listing.rb
def self.locsearch(search_location, search_description)
return scoped unless search_location.present? || search_description.present?
where(['location LIKE? AND description LIKE?', "%#{search_location}%", "%#{search_description}%"])
end
home.html.erb
<%= form_tag findjobs_path, :controller => 'listings', :action => 'locsearch', method: :get do %>
<%= text_field_tag :location, params[:location] %>
<%= text_field_tag :descripiton, params[:descripiton] %>
<%= submit_tag "Search", name: nil %>
<% end %
listings_controller.rb
def index
#listings = #listings.locsearch(params[:location], params[:description])
end
Also, my locsearch method right now uses the or || condition. How would I implement the "and" condition? (If I change the || to && I get the error" undefined method or variable scroped)
Are you sure you want to use unless
unless is used only if you want to execute a specified code if the condition(s) is false.
And scoped is used along with a model.
Model.scoped
You can refer the Apidock or Github
You can write return scoped only if u have defined scoped as a local variable or a method.
You can also see scope for databases
I've managed to build a simple search model and have four attributes that can be searched; name, age, location and gender. The problem I am having is I can't seem to find the right code to search multiple attributes.
For example a search for "adam" should produce all users named adam, whereas a search for london should display all users from london. I can only search one attribute individually (name) so if I type in "london" it displays a blank result page.
/people/index.html.erb (search form)
<%= form_tag people_path, :method => 'get' do %>
<%= text_field_tag :search, params[:search]%>
<%= submit_tag "Search" %>
<% end %>
models/person.rb
class Person < ActiveRecord::Base
attr_accessible :age, :gender, :location, :name
def self.search(search, id)
if search
where(['name LIKE ?', "%#{search}%"])
else
scoped
end
end
end
people_controller.rb
def index
#people = Person.search(params[:search], params[:id])
end
The following code worked fine.
where('name LIKE ? OR location LIKE ?', "%#{search}%","%#{search}%")
#meagar, I fail to understand how that simple line of code "is outside the scope of Stack Overflow".
You can checkout Sunspot_rails gem for your problem, it integrate Solr search engine platform into Rails and is a battle proved solution for Rails app. In my company's website Fishtrip.cn we use solr to search for both House, Transportation retailer and tours. It might be a little bit heavy for your project, but if are looking for a powerful solution then Sunspot definitely would be one of it.