I need to build a query to select records by two criteria (two models): Branch(id) and Plan(created_at)
I tried following queries:
#branches = Branch.where(id: 2).includes(:plans).where("created_at > ?", 1.week.ago)
#branches = Branch.where(id: 2).includes(:plans).where(plans: { "created_at > ?", 1.week.ago })
#branches = Branch.includes(:plans).where(branches: { id: 2 }, plans: { "created_at > ?", 1.week.ago })
I have an error
syntax error, unexpected '}', expecting keyword_end ... "created_at >
?", 1.week.ago })
How can I fix it?
Just from reading your code, the problem is with incorrect syntax of your hash:
{ "created_at > ?", 1.week.ago }
Which should be an array:
[ "created_at > ?", 1.week.ago ]
But for your use case, I think you need something like:
#branches = Branch.where(id: 2)
.joins(:plans)
.includes(:plans)
.where("plans.created_at > ?", 1.week.ago)
In order to be able to use a Plan's column created_at, includes is not enough - in that case the error will be thrown of unknown plans. This is why you need to specify joins to properly build whole query.
Hope that helps!
Good luck!
{ "created_at > ?", 1.week.ago } isn't correct hash syntax, it should be in an array:
[ 'created_at > ?', 1.week.ago ]
May this works for you,
Branch.includes(:plans).where(["id = ? and plans.created_at > ?", 2, 1.week.ago])
Related
I am working in rails 2, I want to execute Query
PunchingInformation.all(
:select => "users.id, login, firstname, lastname,
sec_to_time(avg(time_to_sec(punching_informations.punch_in_time))) as 'avg_pit',
sec_to_time(avg(time_to_sec(punching_informations.punch_out_time))) as 'avg_pot'",
:joins => :user,
:group => "users.id",
:conditions => {
"punching_informations.date between '#{start_date}' and '#{end_date}'",
["punching_informations.user_id IN (?)", employees.map { |v| v.to_i } ]
}
)
But it always return error like
Mysql::Error: Unknown column 'punching_informations.date between '2012-09-01' and '2012-09-25'' in 'where clause': SELECT users.id,login, firstname,lastname, sec_to_time(avg(time_to_sec(punching_informations.punch_in_time))) as 'avg_pit',
sec_to_time(avg(time_to_sec(punching_informations.punch_out_time))) as 'avg_pot' FROM punching_informations INNER JOIN users ON users.id = punching_informations.user_id AND (users.type = 'User' OR users.type = 'AnonymousUser' ) WHERE (punching_informations.date between '2012-09-01' and '2012-09-25' IN ('punching_informations.user_id IN (?)','--- \n- 28\n- 90\n')) GROUP BY users.id
Need your help.
It is a bit unclear what you meant (you have array, but taken in curly braces {} like a hash), but it seems ruby treats first string ("punching_informations.date between '#{start_date}' and '#{end_date}'") as a column, and second array, as array of expected values, thus making the invalid IN condition.
Perhaps it would work if rewritten as
:conditions => {
[ "(punching_informations.date between '#{start_date}' AND '#{end_date}') AND punching_informations.user_id IN (?)", employees.map { |v| v.to_i } ]
}
or even better
:conditions => {
[ "(punching_informations.date between ? AND ?) AND punching_informations.user_id IN (?)", start_date, end_date, employees.map { |v| v.to_i } ]
}
add punching_informations.date and punching_informations.user_id in select
:select => "punching_informations.date, punching_informations.user_id, users.id, ....
#messages = current_user.message_participantions.where(:read => false, :updated_at > 5.days.ago)
The updated_at 5 days ago errors. Do I need to use a format like so:
find(:all, :conditions => ["created_at > ?", 5.days.ago])
You could do:
#messages = current_user.message_participantions.where("read = ? AND updated_at > ?", false, 5.days.ago)
Or if for some reason you need to use the hash:
#messages = current_user.message_participantions.where(:read => false, :updated_at => 5.days.ago..Time.now)
As the values of the hash argument to the where method can be exact values or ranges: http://api.rubyonrails.org/classes/ActiveRecord/Base.html
#messages = current_user.message_participantions.where(:read => false).where("updated_at > ?", 5.days.ago)
I would:
#messages = current_user.message_participantions.where(["read = 0 AND updated_at > ?", 5.days.ago])
Is there a better way of writing this? Is it possible to do cleanly in one line?
conditions = ["category = ?", params[:category]] if params[:category]
#events = CalendarEvent.all( :conditions => conditions )
Not really too much to consolidate but you don't have a lot going on so shouldn't matter.
def action
options = {:conditions => ['category=?', params[:category]]} if params[:category]
#events = CalendarEvent.find(:all, options)
end
#events = CalendarEvent.all(
:conditions => (params[:category] ? ["category = ?", params[:category]] : nil))
I need to select some dynamic price ranges submitted from a search form. How should I approach this with scopes? I am looking for something like this
Painting.price_range(['1..500', '2000..5000'])
SELECT * FROM paintings WHERE price BETWEEN 1..500 **OR** BETWEEN 2000..5000 etc.
Best regards.
Asbjørn Morell.
named_scope :price_range, :conditions => ["(price BETWEEN 1 AND 500) OR (price BETWEEN 2000 AND 5000)"]
OR
named_scope :price_range, :conditions => ["(price ?) OR (price ?)", (1..500).to_s(:db), (2000..5000).to_s(:db)]
Dynamic
named_scope :price_between, lambda { |from, to| { :conditions => ['price > ? AND price <= ?', from, to] } }
named_scope :price_between, lambda { |from, to| { :conditions => ['price BETWEEN ? AND ?', from, to] } }
->
MyModel.price_between(1,100)
You'll need to use a lambda on the named_scope. The following should work:
named_scope :price_range, lambda { |ranges|
{
:conditions => ["(" +
ranges.collect {"price between ? and ?"}.join(" or ") +
")"] +
ranges.collect {|r| [r.min, r.max]}.flatten
}
}
The first ranges.collect creates as many "between ? and ?" checks as you have ranges and then the second ranges.collect flattens out the ranges and adds them as values to be sanitized into the conditions. I've stuck brackets round the ors just to be on the safe side.
Where is the error in this I can't see it:
news = News.find(:all, :conditions => [":simulation_id => session[:sim_id] AND :created_at > session[:last_login]"])
Try this:
news = News.find(:all, :conditions => ["simulation_id = ? AND created_at > ?", session[:sim_id], session[:last_login]])
Your conditions string won't be evaluated as you expect:
[":simulation_id => session[:sim_id] AND :created_at > session[:last_login]"]
change that to
["simulation_id = ? AND created_at > ?", session[:sim_id], session[:last_login]]
You can also call Model.all instead of Model.find(:all) which would look something like this:
news = News.all(:conditions => ["simulation_id = ? AND created_at > ?", session[:sim_id], session[:last_login]])