*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