I have such AR code:
#types = Type.find(:all,
:conditions => { :TYP_MOD_ID => params[:models],
:TYP_PCON_START => params[:year] },
:order => "TYP_HP_FROM")
but how can i do that i see TYP_PCON_START without first 2 symbols and compare?
for example :TYP_PCON_START.to_s[4...6]
Also i need to compare not =, but >= > condition. How to do this?
Use where instead of find. Also i didn't understand what you mean by how can i do that i see TYP_PCON_START without first 2 symbols and compare?.
#types = Type.where("TYP_MOD_ID = ? AND substring(TYP_PCON_START FROM 4 to 6) >= ?",
params[:models], params[:year]).order("TYP_HP_FROM")
Related
Thanks in advance for your help. I'm following the example I found here (Rails Find when some params will be blank) and trying to put together a bunch of conditions for a search form. This is for a Rails 2.3 legacy application. The below works for me, but I'm not sure how to do anything other than "=". For example, how can I make the programs_offered_category condition be a LIKE statement? I tried doing
majorcategories = params[:majorcategories]
Above the conditions statement and adding
conditions['programs_offered_category LIKE ?', "%#{majorcategories}%"]
but I get "wrong number of arguments (2 for 1)". Also, how can I do greater than and less than signs in this setup? Thanks!
search_controller.rb
conditions = {}
conditions[:city] = params[:city] unless params[:city].blank?
conditions[:state] = params[:state] unless params[:state].blank?
conditions[:geo_region] = params[:geo_region] unless params[:geo_region].blank?
conditions[:size_category] = params[:size_category] unless params[:size_category].blank?
conditions[:programs_offered_category] = params[:majorcategories]
#location_matches = Masterlocation.find(:all, :conditions => conditions, :order => 'nickname ASC').paginate(:page => params[:page], :per_page => 20)
I would suggest to use regular expression as follow
conditions['programs_offered_category'].map {|k,v| (k =~ /majorcategories/) ? v : nil}
It will return array of results if there is more than one matches otherwise single value
I am sending data via get and I need to put it into a int array to be used in a find.
here is my code :
#found = Array.new
params['candidate'].each do |c|
#found << c.to_i
end
My url looks like this
http://localhost:3000/export/candidate?candidate[]=3&candidate[]=4&commit=Export
If it makes any difference I am using it for this find
#candidate = Candidate.find(:all, :conditions => ["candidates.id IN ?", #found])
But currently it doesn't put it in a real array because I get this error
Mysql::Error: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '4)' at line 1: SELECT * FROM `candidates` WHERE (candidates.id IN 4,2)
The brackets are missing around the array
Thanks and good morning!
Alex
Just put parentheses around your ?
#candidate = Candidate.find(:all, :conditions => ["candidates.id IN (?)", #found])
Also, your first snippet can be collapsed down to:
#found = params['candidate'].map(&:to_i)
The entire conversion you are making is unnecessary. You can pass the string array as a input to the query (as long as the string values represent numbers).
You can get what you need in one line:
Candidate.find_all_by_id(params[`candidate`])
Which is same as:
Candidate.find(:all, :conditions => {:id => params[`candidate`]})
Which is same as:
Candidate.find(:all, :conditions => ["id IN (?)",params[`candidate`]])
Your original attempt did not work because you did not put brackets after the IN clause.
Hi i'm using this for getting data:
Topic.find(:all, :include => ...,
:conditions => #core ? ["cores_topics.id = ? AND visible = 1 AND (distance < ? OR cores.id IN (?))",#core.id, #user_location[3].to_i, #user_friends] :
["visible = 1 AND (distance < ? OR cores.id IN (?))", #user_location[3].to_i, #user_friends],
...
how can i rewrite the conditions shorter?
how can i rewrite the conditions
shorter?
User smaller variable names.
OK, really. Read the docs for named_scope. Your code is crying out for them.
I have a class called Deal.
Deal has vote_scores.
I would like to see how many vote_scores are in Deal that are greater than 2.
My guess :
for vote_scores > 2 in Deal
count
end
Doesn't really work :D
Edit:
I tried everyone's ideas. But note that :
Deal.vote_scores
Doesn't work because vote_scores is not an attribute of Deal, but rather an attribute of one of its Deals. So if I did this :
Deal.find(1).vote_scores
would return a #.
vote_scores is instantiated within the haml here:
.deal_summary{:id => "deal_#{deal_view.id}"}
.score
= deal_view.vote_scores
in the model here:
def vote_scores
self.votes.inject(0){|sum, vote| sum + vote.value}
end
If you just want to know how many, the more efficient code will be:
Deal.count(:conditions => ["vote_scores > ?", 2])
This will be faster since the counting is done in sql rather than in ruby.
EDIT
Okay, we can try this:
Deal.find(:all).select {|e| e.vote_scores > 2}.count
This will return total number of deal object that has vote_scores > 2
Hopefully that is what you want to do.
Deal.find(:all, :conditions => ["vote_scores > ?", 2]).length
deal = Deal.first #or whatever... Deal.find(10)
deal.votes.count :conditions => ['value > ?', 2]
for all Votes
Vote.count(:conditions => ['value > ?', 2'])
Say I have model 'Car' and controller 'cars', and a method 'display'.
I have multiple attributes like:
in_production, year, make
I can easily do something like this to find cars that match all the parameters passed:
def display
#cars = Car.find(:all, :conditions => { :in_production => #{params[:in_production]}, :year => #{params[:year]}, :make => #{params[:make]} })`
end
So what I'm doing is coding hard links in the menu, so if I wanted to find all Nissan cars from 2009 that were in production, I would pass those values as parameters in my link.
On another page I want to show every car from 2009 that is in_production, only two params instead of three. What's the best way to dynamically alter the conditions so it will work with one, two, or three params, whilst using the same action?
Any ideas?
First of all, using
:conditions => "in_production = '#{params[:in_production]}' AND year = '#{params[:year]}' AND make = '#{params[:make]}'"
is vulnerable to SQL injection. You need to escape the user provided parameters before using them in database conditions.
Something like this should let you add conditions more dynamically depending on whether or not the parameters exist. I did not test it, so I may edit it shortly...
def display
conditions = []
conditions << [ "in_production = ?", params[:in_production] ] if params[:in_production].present?
conditions << [ "year = ?", params[:year] ] if params[:year].present?
conditions << [ "make = ?", params[:make] ] if params[:make].present?
#cars = Car.all(:conditions => conditions )
end
Certainly escape the params and ensure that you only query against fields you want to be exposed. Beyond that, you could use what is built into Rails:
Car.find_all_by_in_production_and_year_and_make(in_production, year, make)
Hand-rolling the conditions may allow for additional logic to be applied (search by year only if the year is between x and y, etc). Using the rails finders (which in turn use method_missing) keeps the API clean and flexible without having to stare at direct SQL conditions.
You could construct a Car#search method that takes the entire params hash as input, where the params are sanitized and stripped of non-exposed fields, and construct the Car#find_all_by* method call using the param names themselves. Adding new conditions to search by is then as simple as passing them in the params.
You might check out searchlogic. It uses some method missing magic to construct named_scopes that would do what you want.
http://github.com/binarylogic/searchlogic
I use SmartTuple for stuff like this. Simple, powerful, designed specifically for the task.
#cars = Car.all(:conditions => (SmartTuple.new(" AND ") +
({:in_production => params[:in_production]} if params[:in_production].present?) +
({:year => params[:year]} if params[:year].present?) +
({:make => params[:make]} if params[:make].present?)
).compile)
or
#cars = Car.all(:conditions => [SmartTuple.new(" AND "),
({:in_production => params[:in_production]} if params[:in_production].present?),
({:year => params[:year]} if params[:year].present?),
({:make => params[:make]} if params[:make].present?),
].sum.compile)
or
keys = [:in_production, :year, :make]
#cars = Car.all(:conditions => (SmartTuple.new(" AND ").add_each(keys) do |k|
{k => params[k]} if params[k].present?
end).compile)
Pick the one you like the most. :)