Rails 3.1 - quick rewrite on deprecated query needed - ruby-on-rails

I have this:
Product.find(:all, :conditions => ['release_date >=? AND release_date <=?', #start, #start + #weeks.weeks], :order => "initial_stock DESC")
I understand conditions is now deprecated. This works fine locally but when I upload to heroku the order doesn't work, so probably best I rewite right? Problem is each thing i've tried throws an error. Can anyone help?
Thanks!

This should do it:
Product.where("release_date >= ? AND release_date <= ?", #start, #start + #weeks.weeks).order("initial_stock DESC")

If this is used across the app I generally like to create a scope on the model for it. I haven't tested this code but here's what I would do:
# scope on Product.rb
scope :by_release_date, lambda { |date| where("release_date BETWEEN ? AND ?", date.beginning_of_day, date.end_of_day) }
# query anywhere in app
Product.by_release_date('2012-06-11 00:00:00').order('initial_stock DESC')

Related

Rails 3 Query - IN (?) can be blank

This query won't return any records, when hidden_episodes_ids is empty.
:conditions => ["episodes.show_id in (?) AND air_date >= ? AND air_date <= ? AND episodes.id NOT IN (?)", #show_ids, #start_day, #end_day, hidden_episodes_ids]
If it's empty, the SQL will look like NOT IN (null)
So my solution is:
if hidden_episodes_ids.any?
*mode code*:conditions => ["episodes.show_id in (?) AND air_date >= ? AND air_date <= ? AND episodes.id NOT IN (?)", #show_ids, #start_day, #end_day, hidden_episodes_ids]
else
*mode code*:conditions => ["episodes.show_id in (?) AND air_date >= ? AND air_date <= ?", #show_ids, #start_day, #end_day]
end
But it is rather ugly (My real query is actually 5 lines, with joins and selects etc..)
Is there a way to use a single query and avoid the NOT IN (null)?
PS: These are old queries migrated into Rails 3, hence the :conditions
You should just use the where method instead as that'll help clean all of this up. You just chain it together:
scope = Thing.where(:episodes => { :show_id => #show_ids })
scope = scope.where('air_date BETWEEN ? AND ?', #start_day, #end_day)
if (hidden_episode_ids.any?)
scope = scope.where('episodes.id NOT IN (?)', hidden_episode_ids)
end
Being able to conditionally modify the scope avoids a lot of duplication.

Active Record Query Using Associated Model in Find Clause

I'm having a blonde moment and probably a brain freeze.
In my rails3 app, I have users and tasks. My users have many tasks...
I have due and overdue tasks as follows:
#due = Task.find(:all, :conditions => ["dueddate >= ? AND AND status = ?", Date.today, false], :include => :taskcategories, :order => "dueddate asc")
What I want to do in my tasks view, is list the users with due tasks...
For some reason, I can't get my head around it. I have tried this, but it's not working:
#task = Task.all
#user = User.find(:all, :conditions => ["#task.dueddate <= ? AND
#task.status = ?", Date.today + 7.days, false])
I'm sure this is easy, can anyone help me!!?
I guess this should work
updated
User.joins(:tasks)
.where("tasks.dueddate <= ? AND tasks.status = ?", Date.today + 7.days, false).group(:id)
This should work with SQLite and MySQL. However, PostgreSQL requires that you supply all the columns of the table. If it's a small table, you could simply type the names. Or you could add this method to the model:
def self.column_list
self.column_names.collect { |c| "#{self.to_s.pluralize.downcase}.#{c}"}.join(",")
end
and change .group(:id) to .group(User.column_list)

Rails 3: How can I find rows in a table that were created today?

Preferably I'd like to use a statement like...
current_user.workouts.find_by_created_at(Time.now.day)
but that doesn't work, I'm guessing because the times don't match up. I'm going to keep reading through the docs, but I thought I'd post this question to seek help while I'm reading.
Thanks!
UPDATE
Using the new Rails 3 support for ARel and named scopes, I refactored the query to...
Model
class Workout < ActiveRecord::Base
scope :from_today, where(" created_at between ? AND ?", Time.zone.now.beginning_of_day, Time.zone.now.end_of_day)
.
.
.
end
Controller
def create
workouts = current_user.workouts.from_today
.
.
.
end
If you are using MySQL you can do the following:
Rails 3:
current_user.workouts.where('DATE(created_at) = ?', Date.today)
Rails 2:
current_user.workouts.find(:all, :conditions => ['DATE(created_at) = ?', Date.today])
current_user.workouts.find(:all, :conditions => [" YEAR(created_at) = ? AND MONTH(created_at) = ? AND DAY(created_at) = ?", Time.zone.now.year, Time.zone.now.month, Time.zone.now.day])
or
current_user.workouts.find(:all, :conditions => [" created_at between ? AND ?", Time.zone.now.beginning_of_day, Time.zone.now.end_of_day])
not sure which is more optimized
I wrote a gem for this kind of operation, it's called by_star. With it, you could do this to get all records created today:
current_user.workouts.today
There's plenty of other helpful methods too. Give it a go.

Need help optimizing some Rails 2.3 ActiveRecord code

(Hi Dr. Nick!)
I'm trying to tighten things up for our app admin, and in a few places we have some pretty skeezy code.
For example, we have Markets, which contain Deals. In several places, we do something like this:
#markets = Market.find(:all, :select => ['name, id'])
#deals = Deal.find(:all, :select => ['subject, discount_price, start_time, end_time'], :conditions => ['start_time >= ? AND end_time <= ?', date1 date2])
Then in the corresponding view, we do something like this:
#markets.each do |m|
=m.name
end
#deals.sort!{ |a,b| a.market.name <=> b.market.name }
#deals.each do |d|
=d.subject
=d.market.name
end
This runs a stupid amount of queries: one to get the market names and ids, then another to get all the deal info, and then for each deal (of which there are thousands), we run yet another query to retrieve the market name, which we already have!
Tell me there is a way to get everything I need with just one query, since it's all related anyway, or at least to clean this up so it's not such a nightmare.
Thanks
You can write like this way ..
#deals_with_market_name = Deal.find(:all, :include => :market,
:select => ['subject, discount_price, start_time, end_time,market.name as market_name'],
:conditions => ['start_time >= ? AND end_time <= ?', date1 date2],
:order => "market.name")
And in view ...
#deals.each do |a|
=a.subject
=a.market_name
end
Try it...
If you use :include => :market when searching the deals you won't run a query to retrieve the market name for each deal. It'll be eager loaded.
#deals = Deal.find(:all, :include => :market)
Hope it helps.

How do I use .find for the last five days in ruby on rails?

Have a model called contact_email.date_sent
I want to be able to run a report which displays all those where the date_sent range is between date.today and date.today 5 days ago.
I assume I use something like
#send_emails = Contact_Email.find(:conditions=> ???)
But not clear what exactly is the best way. Thanks!
Try this:
ContactEmail.all(:conditions => ["date_sent >= ?", 5.days.ago.to_date])
This approach is faster than using BETWEEN clause( assuming date_sent is indexed)
Caveat:
Value of date_sent column should be less than current date.
Edit 1
To add an index in migration:
add_index :contact_emails, :date_sent
ContactEmail.find(:conditions => ['date_sent BETWEEN ? AND ?', Date.today, 5.day.ago.to_date])
If it's something you will use regularly, why not put a named_scope in the model:
named_scope :recent, lambda { |*args| {:conditions => ["date_sent > ?", (args.first || 5.days.ago)]} }
which will let you write:
ContactEmail.recent
for the last 5 days worth, or use the arg to specify your own time frame e.g. the last two weeks:
ContactEmail.recent(2.weeks.ago)

Resources