*Lazy* loading attributes

Imagine that I have a class Book, and a class Chapter, and Chapter has a
text attribute that contains the text of the chapter. Is there a
convenient railsy way to tell Chapter to only load chapter.text from the
db when/if it's specifically called for? For instance, if I'm using
@book.chapters to build a TOC, I'm not the least bit interested in the
chapter.text for all those chapters at this point, and am worried that
loading all that extra data will slow down the app. I'm wondering if I
can say something like...

class Chapter < ActiveRecord::Base
    lazy_load :text

or maybe...

class Book < ActiveRecord::Base
    has_many :chapters, :lazy_load => [ :text ]

But so far the only option I can think of is to offload the text to it's
own model ChapterText that belongs_to :chapter. I've been digging
through the API off and on for a couple weeks now hoping to stumble on
an elegant solution, but haven't yet. So, I'm thinking it's not
currently possible, except for using an extra model. Ideas?

Jon Garvin wrote:

Imagine that I have a class Book, and a class Chapter, and Chapter has a
text attribute that contains the text of the chapter. Is there a
convenient railsy way to tell Chapter to only load chapter.text from the
db when/if it's specifically called for? For instance, if I'm using
@book.chapters to build a TOC, I'm not the least bit interested in the
chapter.text for all those chapters at this point, and am worried that
loading all that extra data will slow down the app. I'm wondering if I
can say something like...

class Chapter < ActiveRecord::Base
    lazy_load :text

or maybe...

class Book < ActiveRecord::Base
    has_many :chapters, :lazy_load => [ :text ]

But so far the only option I can think of is to offload the text to it's
own model ChapterText that belongs_to :chapter. I've been digging
through the API off and on for a couple weeks now hoping to stumble on
an elegant solution, but haven't yet. So, I'm thinking it's not
currently possible, except for using an extra model. Ideas?

I think the :select option for a find allows you to specify which
columns to return. Something like..

Chapter.find(:all, :select=>'id, title') will return Chapter objects
with only the 'id' and 'title' populated.

Seems like it wouldn't be too difficult to setup a class method that
returns the names of all the columns without the ones you want to lazy
load. You could then override the find method to automatically
populate the 'select' option with these values.

Sounds like a good plugin exercise to me...

_Kevin

_Kevin wrote:

I think the :select option for a find allows you to specify which
columns to return. Something like..

Chapter.find(:all, :select=>'id, title') will return Chapter objects
with only the 'id' and 'title' populated.

Seems like it wouldn't be too difficult to setup a class method that
returns the names of all the columns without the ones you want to lazy
load. You could then override the find method to automatically
populate the 'select' option with these values.

Sounds like a good plugin exercise to me...

_Kevin

The problem there though, is that if you later try to access that data
you didn't load, ActiveRecord raises a "NoMethodError", rather than
going back to the database to get the data. I suppose if used very
carefully though, that could be a viable option.

Jon Garvin wrote:

_Kevin wrote:
> I think the :select option for a find allows you to specify which
> columns to return. Something like..
>
> Chapter.find(:all, :select=>'id, title') will return Chapter objects
> with only the 'id' and 'title' populated.
>
> Seems like it wouldn't be too difficult to setup a class method that
> returns the names of all the columns without the ones you want to lazy
> load. You could then override the find method to automatically
> populate the 'select' option with these values.
>
> Sounds like a good plugin exercise to me...
>
> _Kevin
>
>
The problem there though, is that if you later try to access that data
you didn't load, ActiveRecord raises a "NoMethodError", rather than
going back to the database to get the data. I suppose if used very
carefully though, that could be a viable option.

You might be able to use 'method_missing' to load the 'missing' data
when you need it.

_Kevin