Refining an ActiveRecord search

Hi,

I am doing an ActiveRecord find against the database, bringing back a
number of objects that have a created_on date between two dates.

After this fetch, I want to check if the result contains an object with
a specific date (actually I want to iterate through all days in a range,
and if the result contains a record, I want to get that record out of
the result array and interrogate it).

I know how to do this by doing a new ActiveRecord find for each date in
my iteration range, but I don’t want to do that as the overhead of so
many calls is too high. ]

So I need to keep my one hit on the database, but then query the result,
something like:

all_results = Item.where(— created in my date range —)
(start_date…end_date).each do |current_date|
if all_results.contains(:created_on => current_date)
… do something
else
do something else
end
end

My ActiveRecord is very poor - created_on is a field on the Item model,
but I can’t find out how to efficiently query an ActiveRecord result in
this way.

Any help much appreciated!

Thanks.

On 16 December 2010 11:46, Peter L. [email protected] wrote:

I know how to do this by doing a new ActiveRecord find for each date in
else
do something else
end
end

I don’t understand, why not just use start_date and end_date as the
range for your Item.where( ) call, then all the items returned will
have been created in that range, do you can iterate through them all
and do your ‘…do something’ action

Colin

My approach is this way because I can’t guarantee that there will be a
record with a certain date, yet I want to produce an array of results
for a full contiguous range of dates. In the case that there isn’t a
record with a certain date, I still want to put in a ‘placeholder value’
for that date in the array I’m creating.

On 16 December 2010 12:09, Peter L. [email protected] wrote:

Please quote the previous message so individual messages in the thread
make sense.

My approach is this way because I can’t guarantee that there will be a
record with a certain date, yet I want to produce an array of results
for a full contiguous range of dates. In the case that there isn’t a
record with a certain date, I still want to put in a ‘placeholder value’
for that date in the array I’m creating.

OK, I misunderstood. Going back to your original question then, you
say:

I know how to do this by doing a new ActiveRecord find for each date in
my iteration range, but I don’t want to do that as the overhead of so
many calls is too high.

How do you know that the overhead is too high?

Colin

Please quote the previous message so individual messages in the thread
make sense.

Sure, sorry.

My approach is this way because I can’t guarantee that there will be a
record with a certain date, yet I want to produce an array of results
for a full contiguous range of dates. In the case that there isn’t a
record with a certain date, I still want to put in a ‘placeholder value’
for that date in the array I’m creating.

OK, I misunderstood. Going back to your original question then, you
say:

I know how to do this by doing a new ActiveRecord find for each date in
my iteration range, but I don’t want to do that as the overhead of so
many calls is too high.

How do you know that the overhead is too high?

I’ve tried this approach, where I request each date in a range
individually, iterating over the range of dates I require. But the dates
may span 30-60 days or even more, and this causes ~60 separate sql
requests on the database. The result is a noticeable pause when loading
the page (backed up by benchmark figures), and a solution which doesn’t
scale to larger ranges of dates.

On 16 December 2010 11:46, Peter L. [email protected] wrote:

Hi,

I am doing an ActiveRecord find against the database, bringing back a
number of objects that have a created_on date between two dates.

After this fetch, I want to check if the result contains an object with
a specific date

You could use Enumerable::group_by to collect-up your records by date,
and see if the resultant collection includes the date in question (and
if not, add it if you need to)

all_results = Item.where(— created in my date range —)
grouped_all_results = all_results.group_by{|result|
result.created_at.strftime(“%Y%d%m”)}
if grouped_all_results.include?(current_time.strftime(“%Y%d%m”))
… do something
else
do something else
end

You might make your group_by date and your lookup date by some other
method (like “date_value.to_s” or something), but as long as they end
up in the right format, it should work…

or Array.select to return all the matches…
Basically, the Array and Enumerable APIs will probably have something
for you - have a read :wink:

class Array - RDoc Documentation
module Enumerable - RDoc Documentation

I think Array.select is the one for me, thanks!

On 16 December 2010 13:16, Michael P. [email protected] wrote:

and see if the resultant collection includes the date in question (and
if not, add it if you need to)

oh… or if you want it even simpler, just can use Enumerable.detect
to find out yes/no on whether the collection contains any values with
that date:

all_results = Item.where(— created in my date range —)
date_in_range = !!all_results.detect{|result|
result.created_at.strftime(“%Y%d%m”)}

or Array.select to return all the matches…
Basically, the Array and Enumerable APIs will probably have something
for you - have a read :wink:

http://ruby-doc.org/core/classes/Array.html
http://ruby-doc.org/core/classes/Enumerable.html