Result of where query in rails - ruby-on-rails

I am performing a db search as below:
abc = params[:search]
Model.where("column_name ilike ?", "%#{abc}%")
When I am searching nothing it is running like below:
Model.where("column_name ilike ?", "%%")
which is giving me all rows of table.
When my search param is empty I want it to run like:
Model.where("column_name ilike ?", "")
How can I achieve that?

Well, just check whether the params is an empty string:
Model.where("column_name ilike ?", abc.blank? ? '' : "%#{abc}%")
# or, more strict check
Model.where("column_name ilike ?", abc == '' ? '' : "%#{abc}%")

Related

Rails - Where Like query is not returning results that are all capital letters [duplicate]

I'm using a LIKE clause in Ruby On Rails. When I try to search for records by typing "more" it doesn't return anything, but when I do with "More", then it returns the records which contains More keyword, so it seems like it behaves in a case-sensitive way.
Is it possible to make this case-insensitive?
Here is the query I am using currently:
Job.where('title LIKE ? OR duration LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%")
I assume you're using Postgres.
You can use ILIKE
Job.where('title ILIKE ? OR duration ILIKE ?', "%#{params[:search]}%", "%#{params[:search]}%")
Or a some tricky hack lower():
Job.where('lower(title) LIKE lower(?) OR lower(duration) LIKE lower(?)', "%#{params[:search]}%", "%#{params[:search]}%")
try something like this
def query_job(query)
job_query = "%#{query.downcase}%"
Job.where("lower(title) LIKE ? or lower(duration) LIKE ?", job_query, job_query)
end
query_job(params[:search])

Filtering items by multiple fields

Filtering items by title, created_at dates, but one of them would be empty and it raises an error, how could I handle that?
where("country_translations.title ILIKE ? AND country_translations.created_at > ? AND country_translations.created_at < ?", "%#{search[:title]}%", search[:created_at_gt], search[:created_at_lt])
You can do something like this:
YourModel.where(filter_by_translations_title).where(filter_by_translations_created)
def filter_by_translations_title
['country_translations.title ILIKE ?', search[:title]] if search[:title].present?
end
#...add rest of methods here
Chaining #where will join all queries via AND. This way will allow you add as many sub quesries as you want, and control their behavior.
You can chain your where clauses quite easily.
#results = Model.all
#results = #results.where('country_translations.title ILIKE ?', "%#{search[:title]}%") if search[:title].present?
If you're using Postgres you can also use a regex instead of ILIKE to get rid of this %#{}% stuff.
#results = #results.where('country_translations.title ~* ?', search[:title]) if search[:title].present?
and so on for your other fields.
It really depends on how you want to handle that.
First of all, I will decompose the query into multiple wheres, that default to an AND operation. This is for readability:
Model.where("country_translations.title ILIKE ?", "%#{search[:title]}%")
.where("country_translations.created_at > ?", search[:created_at_gt])
.where("country_translations.created_at < ?", search[:created_at_lt])
You could either pass default values using the || operator, like this:
Model.where("country_translations.title ILIKE ?", "%#{search[:title] || ''}%")
.where("country_translations.created_at > ?", search[:created_at_gt] || Time.now)
.where("country_translations.created_at < ?", search[:created_at_lt] || Time.now)
or you can split this into three filters that have to be applied only when needed:
query = Model.all
query = query.where("country_translations.title ILIKE ?", "%#{search[:title]}%") if search[:title]
query = query.where("country_translations.created_at > ?", search[:created_at_gt]) if search[:created_at_gt]
query = query.where("country_translations.created_at < ?", search[:created_at_lt]) if search[:created_at_lt]
# query now is filtered only with present filters.
you can always use scopes in such case, they come handy almost everywhere
scope :filter_by_title, -> (title) { where('title ILIKE ?', "%#{title}%") if title.present? }
scope :filter_by_created_at_lt, -> (date) { where('created_at < ?', date) if date.present? }
scope :filter_by_created_at_gt, -> (date) { where('created_at > ?', date) if date.present? }
Then you can restructure the query as
Model.filter_by_title(search[:title])
.filter_by_created_at_lt(search[:created_at_lt])
.filter_by_created_at_gt(search[:created_at_gt])

How to make LIKE clause case-insensitive?

I'm using a LIKE clause in Ruby On Rails. When I try to search for records by typing "more" it doesn't return anything, but when I do with "More", then it returns the records which contains More keyword, so it seems like it behaves in a case-sensitive way.
Is it possible to make this case-insensitive?
Here is the query I am using currently:
Job.where('title LIKE ? OR duration LIKE ?', "%#{params[:search]}%", "%#{params[:search]}%")
I assume you're using Postgres.
You can use ILIKE
Job.where('title ILIKE ? OR duration ILIKE ?', "%#{params[:search]}%", "%#{params[:search]}%")
Or a some tricky hack lower():
Job.where('lower(title) LIKE lower(?) OR lower(duration) LIKE lower(?)', "%#{params[:search]}%", "%#{params[:search]}%")
try something like this
def query_job(query)
job_query = "%#{query.downcase}%"
Job.where("lower(title) LIKE ? or lower(duration) LIKE ?", job_query, job_query)
end
query_job(params[:search])

Postgres Rails 4 search query id or multiple columns

I am working in an app with a basic search form with Heroku, but I can't get my sql query to work properly with PostgreSQL, even though this query worked with MySQL. By the way, I tried to paste the logs from Heroku, but it only says that when you search something it renders 500.html.
Here's my model OrdemDeServico with the search action:
def self.search(search)
if search
joins(:cliente).where("clientes.nome LIKE ? OR veiculo LIKE ? OR placa LIKE ? OR ordem_de_servicos.id = ?", "%#{search}%", "%#{search}%", "%#{search}%", "#{search}")
else
where(nil)
end
end
I just installed PostgreSQL locally, and it returned this error when searching:
`PG::InvalidTextRepresentation: ERROR: invalid input syntax for integer: "Augusto"
LINE 1: ... placa LIKE '%Augusto%' OR ordem_de_servicos.id = 'Augusto')
query:
SELECT "ordem_de_servicos".* FROM "ordem_de_servicos" INNER JOIN "clientes" ON "clientes"."id" = "ordem_de_servicos"."cliente_id" WHERE (clientes.nome LIKE '%Augusto%' OR veiculo LIKE '%Augusto%' OR placa LIKE '%Augusto%' OR ordem_de_servicos.id = 'Augusto') ORDER BY prazo LIMIT 5 OFFSET 0
I finally worked it out a solution. Those who have the same problem here's my code for the model:
def self.search(search)
if search
where("id = ?", search)
joins(:cliente).where("clientes.nome ilike :q or veiculo ilike :q or placa ilike :q", q: "%#{search}%")
else
where(nil)
end
end

Rails 3.2 - OR query not working properly - Rewriting query

I was really happy using this query for the search form. However, just found out that is not working properly.
The failing bit is the .where which like against params[:query]. This like happens 4 times against 4 different fields. However, results shows that this is not happening.
#events_casual = Event.non_timetable.where("events.finish_date >= ?", #time).where((["CAST(headers.title_es as varchar(255)) LIKE ?", "%#{params[:query]}%"] || ["CAST(headers.title_en as varchar(255)) LIKE ?", "%#{params[:query]}%"] || ["CAST(headers.title_eu as varchar(255)) LIKE ?", "%#{params[:query]}%"] || ["CAST(headers.title_fr as varchar(255)) LIKE ?", "%#{params[:query]}%"])).includes(:header).order("events.start_date ASC")
I have been trying to transform this query into:
#events_casual = Event.non_timetable.joins(:header).where(" params[:query] in (?)", [headers.title_es, headers.title_en, headers.title_eu]).order("events.start_date ASC")
But, this does not work. Error: undefined methodtitle_es' for {}:Hash`
I have tried similar syntax. But to not avail.
Any help rewriting that query much appreciated. Thanks
try the following
#events_casual = Event
.non_timetable
.includes(:header)
.order("events.start_date ASC")
.where("events.finish_date >= ?", #time)
.where("CAST(headers.title_es as varchar(255)) LIKE :query OR CAST(headers.title_en as varchar(255)) LIKE :query OR CAST(headers.title_eu as varchar(255)) LIKE :query OR CAST(headers.title_fr as varchar(255)) LIKE :query", { query: "%#{params[:query]}%"])

Resources