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!