Always use eager loading on a specific model?

Let's say I've got the following models:

Book MyBook User Author

Where books and user has_many :through => my_books, author has_many books, and books belongs_to author and user.

If books/index showed me all of the books with each author's name, I could use eager loading like so:

@books = Book.find(:all, :include => :author)

So that when I iterate through a hundred books and authors, I've already loaded the author. If I want to do the same, but with my_books/ index, I don't know how to include :author, b/c it looks like this:

@books = current_user.books

I'll get all the the books, but I'll have to load all the authors for each song. The same is true if I were to use:

@books = MyBook.find_all_by_user_id(current_user, :include => song)

Which means that when I'm iterating through books, I have to hit the database every for every book to get its author. Is there any way to use eager loading for models once removed, like author is in this example? (i.e., User -> Book -> Author or MyBook -> Book -> Author)

Hopefully I got that all across. Is there a better way?

Adam wrote:

Let's say I've got the following models:

Hopefully I got that all across. Is there a better way?

AFAIK, eager loading does not work past one db relation. If this would be possible, imagine the load it would put on your db. Your options are:

1) find_by_sql 2) create a view in your db that goes across the relations and make a first class model on top 3) use find() but with a huge :join clause that will make your code next to unreadable. 4) rethink your relations, as you have them now, a book can't have more than one author 5) rethink how you want to access your models.

hth

ilan

Adam wrote:

Let's say I've got the following models:

Book MyBook User Author

Where books and user has_many :through => my_books, author has_many books, and books belongs_to author and user.

If books/index showed me all of the books with each author's name, I could use eager loading like so:

@books = Book.find(:all, :include => :author)

So that when I iterate through a hundred books and authors, I've already loaded the author. If I want to do the same, but with my_books/ index, I don't know how to include :author, b/c it looks like this:

@books = current_user.books

I'll get all the the books, but I'll have to load all the authors for each song. The same is true if I were to use:

@books = MyBook.find_all_by_user_id(current_user, :include => song)

Which means that when I'm iterating through books, I have to hit the database every for every book to get its author. Is there any way to use eager loading for models once removed, like author is in this example? (i.e., User -> Book -> Author or MyBook -> Book -> Author)

Hopefully I got that all across. Is there a better way?

You can include in an association.

class ForumPost < ActiveRecord::Base   belongs_to :forum   belongs_to :person   belongs_to :parent_post, :class_name => 'ForumPost', :foreign_key => 'parent_id'   has_one :most_recent_reply, :class_name => 'ForumPost', :foreign_key => 'parent_id', :order => 'created_at desc', :include => :person   has_many :replies, :class_name => 'ForumPost', :foreign_key => 'parent_id', :include => :person, :order => 'created_at'

Notice the has_one :most_recent_reply and has_many :replies. So when you do current_user.books, if you have

has_many :books, :include => :author

it *should* work like you want.

Peace, Phillip

Oh wow, I didn't realize you could use :include in the associations, that does the trick perfectly. Thanks Phillip!