# ActiveRecord.find.each do

**URL:** <https://www.ruby-forum.com/t/activerecord-find-each-do/147728>\
**Category:** Rails\
**Created:** [September 4, 2008, 7:00pm UTC](https://www.ruby-forum.com/t/activerecord-find-each-do/147728 "2008-09-04T19:00:10Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![capnregex](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/59ef9b/32.png) [@capnregex](https://www.ruby-forum.com/u/capnregex)\
**Post date:** [September 4, 2008, 7:00pm UTC](https://www.ruby-forum.com/t/activerecord-find-each-do/147728/1 "2008-09-04T19:00:10Z")

</div>

I have noticed that when I use the construct…

ActiveRecordChild.find(:all).each do |record|  
record.do\_something  
end

That it still returns the array of all records. With larger datasets  
this can be murder on memory…  
I was trying to do this with one of my migrations and my computer  
choked after the migration had consumed 1.8GB of memory.  
I ended up having to rewrite the migration as…

max = ActiveRecordChild.maximum(:id)  
1.upto(max).each do |i|  
if record = ActiveRecordChild.find\_by\_id(i)  
record.do\_something  
end  
end

What I would like to propose is having find accept a block like this.

ActiveRecordChild.find(:all) do |record|  
record.do\_something  
end

where instead of even composing a array of ActiveRecord objects, it  
would just pass in to the block each record as it gets it processed,  
and then forget about it as soon as the block exits.

A possible additional feature might be to collect the results of the  
block like a ‘collect’ call and possibly even omitting that when the  
block returns something that evaluates as false ( false or nil ). Over  
all however, I think for memory considerations, I would rather have  
the form of find with a block return nothing, as if I really want to  
collect the results, I can alwase push something to an array.

–  
-Robert Ferney ( Kolbe 4357 Demonstrator / Myer Brigs INTJ )

---

<div class="post-metadata">

**Author:** ![capnregex](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/59ef9b/32.png) [@capnregex](https://www.ruby-forum.com/u/capnregex)\
**Post date:** [September 4, 2008, 9:14pm UTC](https://www.ruby-forum.com/t/activerecord-find-each-do/147728/2 "2008-09-04T21:14:46Z")

</div>

On Sep 4, 2008, at 12:59 PM, Robert Ferney wrote:

> choked after the migration had consumed 1.8GB of memory.
> 
> block returns something that evaluates as false ( false or nil ). Over  
> all however, I think for memory considerations, I would rather have  
> the form of find with a block return nothing, as if I really want to  
> collect the results, I can alwase push something to an array.
> 
> –  
> -Robert Ferney ( Kolbe 4357 Demonstrator / Myer Brigs INTJ )

That would cause a query for each record and performance would very  
likely suffer. When I’ve had to do a similar thing over a table with  
many (100,000+) records, I’ve done something like:

total = Model.count(to\_refresh)  
limit = [100, total].min  
0.step(total-1, limit) do |offset|  
Model.find(:all, :limit =\> limit, :offset =\> offset).each do |model|  
# do stuff  
end  
end

If you have a condition that limits what comes back, you might have to  
tweak the offset if the “stuff” you do causes records to fall out of  
the condition.

Of course, if the “do\_something” is simple enough you can  
use .update\_all (but that’s a small subset of all the things that you  
_could_ do).

-Rob

Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
removed\_email\_address@domain.invalid

---

<div class="post-metadata">

**Author:** ![capnregex](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/59ef9b/32.png) [@capnregex](https://www.ruby-forum.com/u/capnregex)\
**Post date:** [September 4, 2008, 9:17pm UTC](https://www.ruby-forum.com/t/activerecord-find-each-do/147728/3 "2008-09-04T21:17:07Z")

</div>

If you’re using will\_paginate (why wouldn’t you be using it anyway)  
you can just call:

Image.paginated\_each( :per\_page =\> 20, :conditions =\> { :cached =\>  
false }, :order =\> ‘created\_at asc’) do |image|  
#do something with your image here  
end

The paginated\_each method will automatically paginate your objects so  
you won’t have to load them all.

On Thu, Sep 4, 2008 at 4:13 PM, Rob B.  
[removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > end  
> > and then forget about it as soon as the block exits.  
> > -Robert Ferney ( Kolbe 4357 Demonstrator / Myer Brigs INTJ )  
> > end  
> > -Rob
> 
> Rob B. [http://agileconsultingllc.com](http://agileconsultingllc.com)  
> removed\_email\_address@domain.invalid

–  
Maurício Linhares  
[http://alinhavado.wordpress.com/](http://alinhavado.wordpress.com/) (pt-br) | [http://blog.codevader.com/](http://blog.codevader.com/)  
(en)  
João Pessoa, PB, +55 83 8867-7208

---

<div class="post-metadata">

**Author:** ![capnregex](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/c/59ef9b/32.png) [@capnregex](https://www.ruby-forum.com/u/capnregex)\
**Post date:** [September 4, 2008, 10:58pm UTC](https://www.ruby-forum.com/t/activerecord-find-each-do/147728/4 "2008-09-04T22:58:40Z")

</div>

On 4 Sep 2008, at 18:59, “Robert Ferney” [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> I have noticed that when I use the construct…
> 
> ActiveRecordChild.find(:all).each do |record|  
> record.do\_something  
> end
> 
> That it still returns the array of all records.  
> It’s just a normal array on which you call find. What each returns is  
> immaterial - as far as memory concerns go it’s already too late.

> end  
> end

Yuck. Would have been faster to fetch them in chunks.

> A possible additional feature might be to collect the results of the  
> block like a ‘collect’ call and possibly even omitting that when the  
> block returns something that evaluates as false ( false or nil ). Over  
> all however, I think for memory considerations, I would rather have  
> the form of find with a block return nothing, as if I really want to  
> collect the results, I can alwase push something to an array.

Do the database adapters allow you to page through results before  
they’ve received them all?
