So I have a search box working in my application, however it only returns a result if the search matches exactly what is submitted, as opposed to something like it. Heres my code for the search method;
def self.search(search)
if search
where(:title => ["title LIKE ?", "#{search}"])
else
all
end
end
The "title LIKE ?" doesn't seem to be returning results which are like the query, only ones which are exactly the same.
What am I missing here?
Try this
where(["title LIKE ?", "%#{search}%"])
Here is another way if you want to avoid string queries (using arel):
where(arel_table[:title].matches("%#{search}%"))
Related
I have simple search form in Rails, but when I using the search box, I need to enter the name exactly.
For instance, when I try to search for "more" it doesn't return anything, but when I do with "More", then it returns the records, So it seems like it behaves in a case-sensitive way.
Is it possible to make this case-sensitive way?
Here is my code
def self.search(search)
if search
star = Star.find_by(who: search)
if star
self.where(star_id: star)
else
Post.all
end
else
Post.all
end
end
You could do something like:
star = Star.where("UPPER(who) = ?", search.upcase).take
or
star = Star.where("LOWER(who) = ?", search.downcase).take
Either way, this coerces both your search term as well as the who value in the database before comparing them, which should get you the results that you need
So I want to my user to be able to search by title and description so I have added this line of code.
Here is the error i receive
wrong number of bind variables (1 for 2) in: title LIKE ? or
description LIKE ?
def index
#posts = Post.where(["title LIKE ? or description LIKE ?", "%#{params[:search]}%"]).page(params[:page]).per(10)
end
You can name your arguments when you use the hash syntax - for example name it just :q:
#posts = Post
.where('title LIKE :q or description LIKE :q', q: "%#{params[:search]}%")
.page(params[:page]).per(10)
you're using two ? in this statement. so, the interpreter is expecting 2 arguments for each ?.
change your code to this:
#posts = Post.where("title LIKE ? OR description LIKE ?", "%#{params[:search]}%", "%#{params[:search]}%").page(params[:page]).per(10)
Let me know if it helps.
It's good practice to check Case insensitive matching
#posts = Post.where("LOWER(title) LIKE ? OR LOWER(description) LIKE ?", "%#{params[:search].downcase}%", "%#{params[:search].downcase}%").page(params[:page]).per(10)
You can also use this gem called ransack. Although is focused on forms, you can still make great simple search queries. See this documentation: https://github.com/activerecord-hackery/ransack/wiki/Basic-Searching
I'm trying to build a basic search where only the entire exact search term shows results. Currently it is showing results based on individual words.
Here's the code from the model:
def search
find(:all, :conditions => ['term' == "%#{search}%"])
end
Sorry in advance. I'm very new to rails!
Thank you.
Remove the % from "%#{search}%" so it's "#{search}".
% is a wildcard that matches every result containing the word. So "%tea%" for example would match tear, nestea, and steam, when that's not what you want.
This should yield an exact match:
def search
find(:all, :conditions => ['term' == "#{search}"])
end
Your code doesn't work for several reasons.
You do not pass any value to that method. Therefore search will always be nil.
The ['term' == "%#{search}%"] condition doesn't make much sense because - as I said before - search is undefined and therefore the condition will is the same as ['term' == "%%"]. The string term is not equal to %% therefore the whole condition is basically: [false].
Rails 5.0 uses a different syntax for queries. The syntax you used is very old and doesn't work anymore.
I would do something like this:
# in your model
scope :search, -> (q) {
q.present? ? where("column_name LIKE :query", query: "%#{q}%") :none
}
# in your controller
def set_index
#b = Best.search(params[:search]).order(:cached_weighted_score => :desc)
end
I have this tentative search function, however, it is limited to search one chunk of keyword only.
def self.search(search)
search_condition = "%" + search + "%"
active.where("lower(title) LIKE ?", search_condition.downcase)
end
E.g. I have this title: "Peter Paul Mary"
If I search "peter Mary", it doesn't show.
I found this code useful in this post:
def self.search(search)
if search
search_length = search.split.length
find(:all, :conditions => [(['name LIKE ?'] * search_length).join(' AND ')] + search.split.map { |name| "%#{name}%" })
else
find(:all)
end
end
Unfortunately, it's in older rails.
So, how do I translate this into rails 4?
Update:
I've changed to something like this:
def self.search(str)
search = str.split.map{|w| "(lower(title) LIKE ? )"}.join(" OR ")
values = str.split.map{|w| "%#{w.downcase}%"}.map(&:inspect).join(', ')
.where("#{search}", values)
end
But it raises this error:
ActiveRecord::PreparedStatementInvalid (wrong number of bind variables (1 for 2) in: (lower(title) LIKE ? ) OR (lower(title) LIKE ? )):
Please advise.
If you happen to be using Postgres with your app, then you can easily take advantage of PG's Full Text Search capabilities using the pg_search gem.
You can also plug into frameworks like Solr or ElasticSearch to give you this functionality, but they will increase you development effort.
PG and MySQL both also have pattern matching functions that would allow you to search based on a regex string from the search values.
Given a query like:
current_user.conversations.where("params[:projectid] = ?", projectid).limit(10).find(:all)
params[:projectid] is being sent from jQuery ajax. Sometimes that is an integer and the above works fine. But if the use selects "All Projects, that's a value of '' which rails turns into 0. which yields an invalid query
How with rails do you say search params[:projectid] = ? if defined?
Thanks
I think you may have mistyped the query a bit. "params[:projectid] = ?" shouldn't be a valid query condition under any circumstances.
In any case, you could do some sort of conditional statement:
if params[:project_id].blank?
#conversations = current_user.conversations.limit(10)
else
#conversations = current_user.conversations.where("project_id = ?", params[:project_id]).limit(10)
end
Although, I'd probably prefer something like this:
#conversations = current_user.conversations.limit(10)
#converstaions.where("project_id = ?", params[:project_id]) unless params[:project_id].blank?
Sidenotes:
You don't have to use .find(:all). Rails will automatically execute the query when the resultset is required (such as when you do #conversations.each).
Wherever possible, try to adhere to Rails' snakecasing naming scheme (eg. project_id as opposed to projectid). You'll save yourself and collaborators a lot of headaches in the long run.
Thanks but if the where query has lets say 3 params, project_id, project_status, ... for example, then the unless idea won't work. I'm shocked that Rails doesn't have a better way to handle conditional query params
EDIT: If you have multiple params that could be a part of the query, consider the fact that where takes a hash as its argument. With that, you can easily build a parameter hash dynamically, and pass it to where. Something like this, maybe:
conditions = [:project_id, :project_status, :something_else].inject({}) do |hsh, field|
hsh[field] = params[field] unless params[field].blank?
hsh
end
#conversations = current_user.conversations.where(conditions).limit(10)
In the above case, you'd loop over all fields in the array, and add each one of them to the resulting hash unless it's blank. Then, you pass the hash to the where function, and everything's fine and dandy.
I didn't understand why you put:
where("params[:projectid] = ?", projectid)
if you receive params[:project] from the ajax request, the query string shouldn't be:
where("projectid = ?", params[:projectid])
intead?
And if you are receiving an empty string ('') as the parameter you can always test for:
unless params[:projectid].blank?
I don't think i undestood your question, but i hope this helps.