Postgres Rails 4 search query id or multiple columns - ruby-on-rails

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

Related

Double Join in rails query

I have these three tables as below
office.rb
has_many :documents
has_one :information
information.rb
belongs_to :office
document.rb
belongs_to :office
I am trying to write a query where as below
documents_controller.rb
def search
#documents = Document.all
#documents.joins(:office).where("offices.name ILIKE ?", "%#{params[:search]}%") OR #documents.joins(:office).joins(:information).where("informations.first_name ILIKE ? OR informations.last_name ILIKE ?", "%#{params[:search]}%", "%#{params[:search]}%")
end
I am trying to achieve the above statement but I am doing something wrong. Please help me fix this query
So, the idea is to retrieve any document where the office's name is the search term or where the information first/last name is the search term, right?
The first step is to create the joins:
Document.joins(office: :information)
The second step is to create the condition:
where("offices.name ILIKE :term OR informations.first_name ILIKE :term OR informations.last_name ILIKE :term", term: "%#{params[:search]}%")
and joining both sentences:
Document.joins(office: :information).where("offices.name ILIKE :term OR informations.first_name ILIKE :term OR informations.last_name ILIKE :term", term: "%#{params[:search]}%")
there are other fancy ways to do the same thing like using or scope but probably will be more complex to understand:
search_term = "%#{params[:search]}%"
base_query = Document.joins(office: :information)
office_scope = base_query.where("offices.name ILIKE :term", search_term)
first_name_scope = base_query.where("informations.first_name ILIKE :term", search_term)
last_name_scope = base_query.where("informations.last_name ILIKE :term", search_term)
office_scope.or(first_name_scope).or(last_name_scope)

Result of where query in 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}%")

Single search box produces "ERROR: column reference "name" is ambiguous"

I am trying to use a single search field to filter any column following Railscasts 240. The key piece for defining the search function is in the Contact model.
def self.search(search)
if search
joins(:school).where(['name ILIKE ? OR email ILIKE ? OR school.name ILIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
else
all
end
end
This works without the join and school.name. Contact belongs to school and has a school_id column. The exact error is:
PG::AmbiguousColumn: ERROR: column reference "name" is ambiguous
I'm guessing the ambiguous error is because I am trying to search both contact.name and school.name. Looking for a suggestion to allow searching both without adding another search field or needing the user to specify the search type.
Edit:
Good suggestions below to use contact.name to deal with the ambiguity, but that leads to another error:
PG::UndefinedTable: ERROR: missing FROM-clause entry for table "contact"
LINE 1: ...ON "schools"."id" = "contacts"."school_id" WHERE (contact.na...
^
: SELECT "contacts".* FROM "contacts" INNER JOIN "schools" ON "schools"."id" = "contacts"."school_id" WHERE (contact.name ILIKE '%joseph%' OR email ILIKE '%joseph%' OR school.name ILIKE '%joseph%') ORDER BY name asc LIMIT 50 OFFSET 0
I thought this was due to the inner join moving the entire query into the schools table, but the error persists even if I remove the other two queries and ONLY search on school.name.
The ambiguous errors is caused by PG not knowing which name column the query reffers to - contacts.name or schools.name. You can fix it by changing your query to:
joins(:school).where(['contacts.name ILIKE ? OR email ILIKE ? OR schools.name ILIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
if columns that same names is more then must add alias
try this, i add contacts.name
def self.search(search)
if search
joins(:school).where(['contacts.name ILIKE ? OR email ILIKE ? school.name ILIKE ?', "%#{search}%", "%#{search}%", "%#{search}%"])
else
all
end
end

Rails Queries Made By User

I am building a rails app where users can post, must like a form. I want users to be able to search through the posts with a text field, and then all records will be returned where the post content is similar to the user query. For example, a user enters:
'albert einstein atomic bomb'
Then, I want a to run a query where every word is checked, along with the query itself. Something like:
query_result = Hash.new
query_result << Post.where('content ILIKE ?', "%albert%")
query_result << Post.where('content ILIKE ?', "%einstein%")
query_result << Post.where('content ILIKE ?', "%atomic%")
query_result << Post.where('content ILIKE ?', "%bomb%")
query_result << Post.where('content ILIKE ?', "%albert einstein atomic bomb%")
This will not work of course, but I hope you get the idea. Any and all input would be appreciated.
You can use sunspot gem for stuff like this. Once it's setup you can do searches like so
# Posts with the exact phrase "great pizza"
Post.search do
fulltext '"great pizza"'
end
# One word can appear between the words in the phrase, so "great big pizza"
# also matches, in addition to "great pizza"
Post.search do
fulltext '"great pizza"' do
query_phrase_slop 1
end
end
and more. See the info in the link.
What about something like this?
query = 'albert einstein atomic bomb'
sub_queries = query.split("\n") << query
query_results = []
sub_queries.each { |q| query_results << Post.where('content ILIKE ?', "%#{q}%") }
You probably need to flatten the query_results array and uniq to remove duplicates.

Rails3: Searching for Users by Second nad First name?

I want to write a simple search method in my User model where it checks agisnt the Second name and first name and returns matching users. I have this at the moment but throws an error:
def self.search(search)
if search
where("first_name like ? or second_name like ?", "%#{search}%")
else
all
end
end
the error is: wrong number of bind variables (1 for 2) in: first_name like ? or second_name like ?
How can i fix this?
Thanks
You have two ? which means the where method is expecting two arguments:
def self.search(search)
if search
where("first_name like ? or second_name like ?", "%#{search}%", "%#{search}%")
else
all
end
end
I'm not sure if you can streamline those likes to use one argument instead of the duplicate two, but you could clean it up a little:
def self.search(search)
if search
q = "%#{search}%"
where("first_name like ? or second_name like ?", q, q)
else
all
end
end
You can use
where("first name like :name or second name like :name", :name => "%foo%")

Resources