I wrote a little search query in rails:
.where("bezeichnung or nummer like ?", "%#{search}%")
It somehow wont work corectly, i dont get a error but it seems like it only makes a search query on the nummer field. Then i tried:
.where("bezeichnung like ?", "%#{search}%")
With the same search param i got a lot more recors. What did i wrong? Thanks
To match on two terms with an or using a single where call, you'll need to pass the search to both clauses, and separate them with the or:
.where("bezeichnung LIKE ? OR nummer LIKE ?", "%#{search}%", "%#{search}%")
Related
So I have an active record query that returns some records, lets say it looks like this.
jobs = Job.where(:user_id => current_user.id)
As you would expect this returns the current_user's jobs. Assume that the job has two dates, deadline_date and due_date. If I want to order on deadline_date I can do something like..
jobs.order("deadline_date asc")
That works as expected, now image I have something in the job model like this.
class Job < ActiveRecord::Base
def deadline_date
self.read_attribute(:deadline_date) || self.due_date
end
end
So the job will display its deadline_date if it is not nil else it will fallback to use the due_date. So to sort this I have done the following...
jobs.sort_by{|job| job.deadline_date}
jobs.sort_by{|job| job.deadline_date}.reverse
This solves my problem but I wondered it there were better alternatives, is it possible to achieve this using SQL? Also this produces some repeated code in that I have a sort_order variable in my controllers that I can pass directly like this...
jobs.order(sort_order)
Now it looks more like this...
if params[:sort] == "deadline_date"
if params[:order] == "asc"
jobs.sort_by{|job| job.deadline_date}
else
jobs.sort_by{|job| job.deadline_date}.reverse
end
else
jobs.order(sort_order)
end
Note: This is a arbitrary example in reality it is a bit messy but you get the idea. So I'm looking for an SQL alternative or a suggestion on how it could be improved. Cheers
If I understand you correctly, you should be able to do this using the COALESCE SQL function:
jobs.order(Arel.sql("COALESCE(deadline_date, due_date)"))
That's pretty much the same as deadline_date || due_date in Ruby.
I believe it to be a standard SQL thing, so it should work for most SQL dialects.
Suddenly I've realized that while this works in groovy just like it is expeceted:
Sql.newInstance(connectionParams).rows("SELECT FROM ITEMS WHERE id = ?", [200])
this won't work
Sql.newInstance(connectionParams).rows("SELECT FROM ITEMS WHERE name LIKE '%?%'", ["some"])
All you can get is
Failed to execute: SELECT FROM ITEMS WHERE name LIKE '%?%' because:
The column index is out of range: 1, number of columns: 0.
My questions are:
Is it intentionally implemented this way? I've never needed to have a parametrized text search, so I'm not sure where this behaviour is typical or not.
How can I nevertheless safely parametrize statement with text search in it?
I believe you want to include the %'s in the parameter, like:
Sql.newInstance(connectionParams).rows("SELECT FROM ITEMS WHERE name LIKE ?", ["%some%"])
I have a model named Topic, that has a name as a field.
So say I have a term I'm searching for, apple.
If I do a
Topic.find_by_name("apple")
I get a record back with the name apple. That's good -- but how do I change find_by_name so that it can find "apple juice" as well as "apple" -- basically, find names that contain the original query or exactly match the original query?
Edit:
Thanks for all the response. I guess I should've been a little more clear earlier, but what if I want to find by a variable name (obviously I'm not going to want to find by the name "apple" everytime :) )?
How do I manipulate Topic.where to accommodate for this?
So something like...
#topic = Topic.where(......., #name)
I think something like this should work:
Topic.where("name like ?", "%apple%")
To accomodate for your edit:
Topic.where("name like ?", "%#{#search}%")
Basic string interpolation, you're using the value of #search inside the string %%, so you #search = "apple" then you end up with %apple%
With PostgreSQL you can also use match operators:
Topic.where("name ~* ?", #search)
Looks like in Rails 3 you would want to use the where:
Topic.where("name ILIKE ?", "%apple%")
Don't put string directly like that. Its called SQL injection. You should instead use .where:
Topic.where("name like '?%' ", params[:name])
Try
Topic.where("name like ?",'%apple%')
Topic.find(:all, :conditions => ["name like ?","%apple%"])
I'm fairly new and playing around with searching databases in Rails. I have a model and database that has a list of names under the 'name' attribute. I want to be able to enter search keywords into a single search field and this input can be one word or two words or more, depending on how specific a result the user wants.
Right now, I'm using something ugly as shown below, which will do a maximum of 3 search terms. Is there a way to make this dynamic for 'search_length' keywords? The find method is clearly repetitive, but I'm not sure how to automate it and haven't found any useful suggestions elsewhere online.
def self.search(search)
if search
search_length = search.split.length
find(:all, :conditions => ['name LIKE ? AND name LIKE ? AND name LIKE ?',
"%#{search.split[0]}%", "%#{search.split[1]}%",
"%#{search.split[search_length1]}%"])
else
find(:all)
end
end
Other than this, loving Rails so far.
Thanks Much,
Lev
The code from Łukasz Śliwa works great if you close the name variable with the other % sign.
The complete code from above working for me. Great 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
Use something like this:
find(:all, :conditions => [(['name LIKE ?'] * search_length).join(' AND ')] + search.split.map { |name| "%#{name}" })
I looks strange but, first generate search_length times string 'name LIKE ?':
['name LIKE ?'] * search_length
then you have array with some keys, so let's join all of them with ' AND ':
["name LIKE ? ", "name LIKE ? ", "name LIKE ? "].join(' AND ')
and finally merge with another array.
formatted_columns = format_column_names(Sub.column_names)
where(formatted_columns.map {|cn| "#{cn} like ?" }.join("or "), *(["%#{search}%"] * formatted_columns.size))
this takes care of all columns as well as the correct amount of fields
I'm trying to query an OR WHERE into an acts-as-taggable-on query, like so...
Business.tagged_with(params[:query], :any => true)
But I'd also like to perform at the same time an or_where like this...
Business.tagged_with(params[:query], :any => true).or_where('name LIKE ?', "%#{params[:query]}%")
This obviously doesn't work as there is no or_where method but would someone know how to perform this correctly?
In short, I'm trying to find a match against any tags OR business name. Thanks.
You can OR two queries together by using the | operator like so:
Business.tagged_with(params[:query], :any => true) | Business.where('name LIKE ?', "%#{params[:query]}%")
Note that this will eager load the results, so you can't apply any more conditions after this, like ordering. It will return an array with all of the matching results in it, excluding duplicates.