Search multiple colums in model rails 3 - ruby-on-rails-3

I have a search form where I can search one column in my Recipe model using
#countrysearch = Recipe.where(:dish_name => params[:search]).all
So when i search for a dish say lasagne I get a result, however i would like to be able to search another 3 columns within the recipe model, country_of_origin, difficulty and preperation_time.
I have tried this
#countrysearch = Recipe.where({:dish_name => params[:search], :country_of_origin => params[:search], :difficulty => params[:search], :preperation_time => params[:search]}).all
but this does not seem to work either
Can anyone offer a suggestion?

Your code uses AND but you want OR I think:
#countrysearch = Recipe.where("dish_name = ? OR country_of_origin = ? OR difficulty = ? OR preperation_time = ?",
params[:search],
params[:search],
params[:search],
params[:search]
)
If you don't want to use an SQL string you can use the arel_table:
at = Recipe.arel_table
search = params[:search]
#countrysearch = Recipe.where(at[:dish_name].eq(search).or(at[:country_of_origin].eq(search)).or(at[:difficulty].eq(search)).or(at[:preperation_time].eq(search)))
But for the current version of Rails I would prefere the first method because this is better readable. In Rails 5 you will have better methods for this sort of queries. (I will update this post if this becomes available.)

Related

rails - find with condition in rails 4

I recently upgraded my rails to Rails 4.1.6.
This query used to work :
#user = User.find(:all, :conditions => { :name => 'batman' })
Now I get this error message:
Couldn't find all Users with 'id': (all, {:conditions=>{:name=>"batman"}}) (found 0 results, but was looking for 2)
When I check the logs I can see that rails is trying to do a completely different query :
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" IN ('all', '---
:conditions:
:name: batman
')
It looks like, it's trying to get all the users with the id "all" and "{:conditions=>{:name=>"batman"}}". Please help.
UPDATE:
My real question behind that was I want to get a specific user and add to it his cars, only the cars that are blue. For example this is my query, the user id is 20.
#user = User.joins(:cars).find(20, :cars => {:color => "blue"})
But I get this error:
Couldn't find all Users with 'id': (20, {:cars=>{:color=>"blue"}})
(found 41 results, but was looking for 2)
You should definitely read this ActiveRecord Query Interface quide
User.where(name: "batman")
Some others already pointed out: The query syntax changed. Try this:
#user = User.joins(:cars).where(:cars => { :color => "blue" }).find(20)
Note that this will raise an exception if that record is not found, to return an array empty instead call:
#user = User.joins(:cars).where(:id => 20, :cars => { :color => "blue" })
I suggest to read: http://guides.rubyonrails.org/active_record_querying.html
If you want to load the user even if he does not have any cars and than display only his blue cars, I would do it like this:
#user = User.find(20) # returns the user
#user.cars.where(:color => 'blue') # returns the user's blue cars (or an empty array)
The find method is deprecated in this version of Rails (see the reference).
Instead, you must use the where method.
In your case, you should write #user = User(:name => 'batman') or #user = User(name: 'batman')

Ruby on Rails - search in database based on a query

I have a simple form, where I set up a query that I want to browse, for example panasonic viera.
This is on how I search the term in database:
Product.where("name ilike ?", "%#{params[:q]}%").order('price')
The query looks like %panasonic viera%, but I would need to search the query this way: %panasonic%viera% - I need to find all products, where is in the title the word panasonic or viera... but how to make this query?
One solution would be to break up your query into individual terms and build a set of database queries connected by OR.
terms = params[:q].split
query = terms.map { |term| "name like '%#{term}%'" }.join(" OR ")
Product.where(query).order('price')
If you're using PostgreSQL, you can use pg_search gem. It's support full text search, with option any_word:
Setting this attribute to true will perform a search which will return all models containing any word in the search terms.
Example from pg_search:
class Number < ActiveRecord::Base
include PgSearch
pg_search_scope :search_any_word,
:against => :text,
:using => {
:tsearch => {:any_word => true}
}
pg_search_scope :search_all_words,
:against => :text
end
one = Number.create! :text => 'one'
two = Number.create! :text => 'two'
three = Number.create! :text => 'three'
Number.search_any_word('one two three') # => [one, two, three]
Number.search_all_words('one two three') # => []
How about via ARel
def self.search(query)
words = query.split(/\s+/)
table = self.arel_table
predicates = []
words.each do |word|
predicates << table[:name].matches("%#{word}%")
end
if predicates.size > 1
first = predicates.shift
conditions = Arel::Nodes::Grouping.new(predicates.inject(first) {|memo, expr| Arel::Nodes::Or.new(memo, expr)})
else
conditions = predicates.first
end
where(conditions).to_a
end
This isn't working?
WHERE name LIKE "panasonic" OR name LIKE "viera"

Ruby on Rails 3 - retrieved data always zero

I can't find a working solution for the following piece of code:
def search_last_rate
self.rate = Rate.find(:first, :select => "rateconverted", :conditions => ["dominant_id = ? and converted_id = ?", self.currency_bought_iso, self.currency_sold_iso], :order => 'ratedate, dateloaded, timeloaded DESC')
end
When I execute this in the console I retrieve the appropriate value:
`=> #<Rate rateconverted: 0.8131>`
All columns are defined in MYSQL2 as an decimal but when I'm using it in the model and new html page it's always saving the value 0.0.
Please advice :)
decimal and integer are different in mysql. if u want the data to be numeric then use 'integer' in migrations else 'float'. checkout Decimal VS Int in MySQL?
Make sure that self.rate is not an integer
Try
self.rate = Rate.find(:first, :select => "rateconverted", :conditions => ["dominant_id = ? and converted_id = ?", self.currency_bought_iso, self.currency_sold_iso], :order => 'ratedate, dateloaded, timeloaded DESC').to_f

Configuring rails database query so that blank string parameters are ignored

I'm making a rails application so that users can search a database of midi records and find midi files that correspond to the attributes that I've given them.
For example, a user might enter data into an html form for a midi file with name = "blah" composer= "buh" and difficulty = "insane".
This is all fine and well, except that I would like when the user enters no data for a field, that field is ignored when doing the select statement on the database.
Right now this is what my select statement looks like:
#midis=Midi.where(:name => params[:midi][:name],
:style => params[:midi][:style],
:numparts => params[:midi][:numparts],
:composer=> params[:midi][:composer],
:difficulty => params[:midi[:difficulty])
This works as expected, but if for example he/she leaves :composer blank, the composer field should not considered at all. This is probably a simple syntax thing but i wasn't able to find any pages on it.
Thanks very much!
Not sure if Arel supports that directly, but you could always do something like:
conditions = {
:name => params[:midi][:name],
:style => params[:midi][:style],
:numparts => params[:midi][:numparts],
:composer=> params[:midi][:composer],
:difficulty => params[:midi[:difficulty]
}
#midis=Midi.where(conditions.select{|k,v| v.present?})
Try this:
# Select the key/value pairs which are actually set and then convert the array back to Hash
c = Hash[{
:name => params[:midi][:name],
:style => params[:midi][:style],
:numparts => params[:midi][:numparts],
:composer => params[:midi][:composer],
:difficulty => params[:midi][:difficulty]
}.select{|k, v| v.present?}]
Midi.where(c)

Will_Paginate and order clause not working

I'm calling a pretty simple function, and can't seem to figure out whats going on. (I'm using rails 3.0.3 and the master branch of 'will_paginate' gem). I have the following code:
results = Article.search(params) # returns an array of articles
#search_results = results.paginate :page => params[:page], :per_page=>8, :order => order_clause
No matter what I make the order_clause (for example 'article_title desc' and 'article_title asc'), the results are always the same in the same order. So when I check using something like #search_results[0], the element is always the same. In my view, they are obviously always the same as well. Am I totally missing something?
I'm sure its something silly, but I've been banging my head against the wall all night. Any help would be much appreciated!
Edited to Add: The search clause does the following:
def self.search(params)
full_text_search(params[:query].to_s).
category_search(params[:article_category].blank? ? '' : params[:article_category][:name]).
payout_search(params[:payout_direction], params[:payout_value]).
length_search(params[:length_direction], params[:length_value]).
pending.
distinct.
all
end
where each of these guys is a searchlogic based function like this:
#scopes
scope :text_search, lambda {|query|
{
:joins => "INNER JOIN users ON users.id IN (articles.writer_id, articles.buyer_id)",
:conditions => ["(articles.article_title LIKE :query) OR
(articles.description LIKE :query) OR
(users.first_name LIKE :query) OR
(users.last_name LIKE :query)", { :query => "%#{query}%" }]
}
}
scope :distinct, :select => "distinct articles.*"
#methods
def self.payout_search(dir, val)
return no_op if val.blank?
send("payment_amount_#{dir.gsub(/\s+/,'').underscore}", val)
end
def self.length_search(dir, val)
return no_op if val.blank?
send("min_words_#{dir.gsub(/\s+/,'').underscore}", val)
end
Thanks.
If you look at the example from the will_paginate github page you can spot one important difference between their use of the :order clause and yours:
#posts = Post.paginate :page => params[:page], :order => 'created_at DESC'
This calls paginate on the Post object (with no objects being selected yet - no SQL has been executed before paginate comes along). This is different in your example: as you state in the first line of code "returns an array of articles". The simplest I can come up with showing the problem is
results = Model.limit(5).all
#results = results.paginate :order => :doesnt_matter_anymore
won't sort, but this will:
results = Model.limit(5)
#results = results.paginate :order => :matters
It should suffice to take the all out of the search method. It makes ActiveRecord actually perform the SQL query when calling this method. Will_paginate will do that for you when you call paginate (if you let it...). Check out the section on Lazy Loading in this post about Active Record Query Interface 3.0