# Model and lazy loading

**URL:** <https://www.ruby-forum.com/t/model-and-lazy-loading/103035>\
**Category:** Rails\
**Created:** [May 1, 2007, 1:17am UTC](https://www.ruby-forum.com/t/model-and-lazy-loading/103035 "2007-05-01T01:17:08Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![mario](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8e7dd6/32.png) [@mario](https://www.ruby-forum.com/u/mario)\
**Post date:** [May 1, 2007, 1:17am UTC](https://www.ruby-forum.com/t/model-and-lazy-loading/103035/1 "2007-05-01T01:17:08Z")

</div>

Is there a concept of having a model attribute loaded only when  
necessary. For example, I have a model called product with an  
attribute called file which is stored in the database as a blob. I  
would like to be able to retrieve a bunch of products as an array  
without having to load the file BLOB. Only loading it when necessary.

Your help is much appreciated.

Mario

---

<div class="post-metadata">

**Author:** ![mario](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8e7dd6/32.png) [@mario](https://www.ruby-forum.com/u/mario)\
**Post date:** [May 1, 2007, 4:49am UTC](https://www.ruby-forum.com/t/model-and-lazy-loading/103035/2 "2007-05-01T04:49:19Z")

</div>

You could wrap the file into its own object, and have the “product”  
model refer to the file object using has\_one or has\_many. This way,  
when you use the product model, the file model will not be loaded due  
to the default lazy-loading, and when you need the file, you can just  
go to product.file, which will load the necessary blob.

Hope that helps,  
~Ian

---

<div class="post-metadata">

**Author:** ![mario](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8e7dd6/32.png) [@mario](https://www.ruby-forum.com/u/mario)\
**Post date:** [May 1, 2007, 10:11am UTC](https://www.ruby-forum.com/t/model-and-lazy-loading/103035/3 "2007-05-01T10:11:38Z")

</div>

Hi,

> Is there a concept of having a model attribute loaded only when  
> necessary. For example, I have a model called product with an  
> attribute called file which is stored in the database as a blob. I  
> would like to be able to retrieve a bunch of products as an array  
> without having to load the file BLOB. Only loading it when necessary.  
> Not sure if my suggestion is the best since it’s not 100% automatic, but  
> almost 😉

You could use the :select clause of find, so you select only those  
attributes you want to retrieve always. Then for the rest of the  
attributes if you try to read them from the object you would have an  
error, since they weren’t loaded from db.

So here comes the trick…

In your :select clause don’t forget to include the id as one of the  
selected fields. That way you could use it to get the rest of the data  
from db when you need it.

Easiest way of doing this would be a find with a select clause for your  
blob/clob field.

obj=MyHeavyModel.find(:first,:select=\>‘id,name,any\_other\_simple\_fields’)  
puts obj.id  
puts obj.name  
puts obj.blob\_field #this would cause an exception since it’s not  
loaded

puts MyHeavyModel.find(obj.id,:select=\>‘blob\_field’).blob\_field #but  
this would work

In case you have several blob/clob fields in your table, maybe you want  
to reload them all directly. In that case you don’t even have to write a  
new find, but just invoke reload over your object.The good thing is  
reload will not take into account the original select clause, but  
directly use the id to retrieve the complete row/object from database.

obj=MyHeavyModel.find(:first,:select=\>‘id,name,any\_other\_simple\_fields’)  
puts obj.id  
puts obj.name  
puts obj.blob\_field #this would cause an exception since it’s not  
loaded

obj.reload #everything gets retrived from db, even not  
previously selected fields  
puts obj.blob\_field #now you have here your field

Any of those solutions, should work fine, but you can still make it a  
bit more transparent if the find/reload looks artificial in your code;  
you could play with method\_missing of your model so if it’s being called  
for an attribute which is in your “column\_names” list, it can  
automatically reload/find the object and return the value of the  
attribute back.

If you go with this approach, just take into account method\_missing is  
already overwritten in AR classes, so alias the old method and don’t  
forget to call it before executing your part.

Regards,

Javier R.

- 

* * *

Estamos de estreno… si necesitas llevar el control de tus gastos  
visita [http://www.gastosgem.com](http://www.gastosgem.com) !!Es gratis!!

---

<div class="post-metadata">

**Author:** ![mario](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8e7dd6/32.png) [@mario](https://www.ruby-forum.com/u/mario)\
**Post date:** [May 3, 2007, 5:06am UTC](https://www.ruby-forum.com/t/model-and-lazy-loading/103035/4 "2007-05-03T05:06:45Z")

</div>

I have another question. If I do product.save (where product is an  
instance of my Product model), here is what the mysql adapter for Ruby  
will do:

SQL: INSERT INTO `PRODUCT` COLUMNS(NAME, PRICE, FILE) VALUES(‘PROD1’,  
4.56, X’00DEF033423023220’)

All is hunky dory for as long as my BLOB is not too big. If the blob  
is say 8MB (not that big actually),there is a problem:

The buffer used by the mysql server(max\_allowed\_packet) to hold the  
commands must be at least 16MB (two bytes for hexadecimal  
representation). This is an unecessarily huge number for holding SQL  
commands.

Is there a way to tell ruby to use a host variable in the SQL  
statement (i.e. VALUES(‘PROD1’, 4.56, :blobvar) instead of the literal  
format in the example above. I cannot believe this problem has never  
been seen before? Imagine if the BLOB data I need to store is 100MB?

Your help is much appreciated.

---

<div class="post-metadata">

**Author:** ![mario](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/8e7dd6/32.png) [@mario](https://www.ruby-forum.com/u/mario)\
**Post date:** [May 1, 2007, 2:12pm UTC](https://www.ruby-forum.com/t/model-and-lazy-loading/103035/5 "2007-05-01T14:12:54Z")

</div>

On 4/30/07, Ian B. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> You could wrap the file into its own object, and have the “product”  
> model refer to the file object using has\_one or has\_many. This way,  
> when you use the product model, the file model will not be loaded due  
> to the default lazy-loading, and when you need the file, you can just  
> go to product.file, which will load the necessary blob.
> 
> Hope that helps,  
> ~Ian

This is how my attachment\_fu/acts\_as\_attachment plugin was originally  
written. Does a Product have a blob for an attached file, or does it  
have a relation to a ProductFile model with its own metadata?

–  
Rick O.  
[http://lighthouseapp.com](http://lighthouseapp.com)  
[http://weblog.techno-weenie.net](http://weblog.techno-weenie.net)  
[http://mephistoblog.com](http://mephistoblog.com)
