Marcus V. wrote:
This is a bit of a long question, but to those of you with some
experience, it should be fairly simple I think.
This is a bit of a long reply, but I tried to keep my solution as close
to the
“Rails-way” as I could.
I have a notes page that should list all notes the user has entered for
all books chronologically like this.
Book One: This is the note.
Book Four: This is the note.
Book One: A different note, entered later.
Hmm… that’s kind of a strange way to display the notes that user has
entered,
but it’s not too difficult to get what you want.
Right now my models are:
User
has_many :books
Book
has_many :notes
belongs_to :user
Note (has column book_id)
belongs_to :book
has_one :book
As Josh mentioned in his reply, you have to remove the “has_one :book”
from the
Note model class. Since there’s no note_id column in the books table,
the
association you’re specifying is invalid.
The NotesController has:
@books = current_user.books.find(:all)
@notes = @books.notes
Also, as Josh mentioned, @books is an array, it won’t have a notes
method for
you to access. Second, you don’t need to do a find on the
current_user.books,
since you want all of their books. So that line can just be:
@books = current_user.books
I would also recommend that when you do the find to set current_user,
that you
add an “:include => :books” option to the find, so that you get the
books in the
first SQL call. But you don’t have to do that for “current_user.books”
to get
you the @books collection.
Finally, each item in the @books array, which is a book model item, will
have a
notes method, but you don’t actually want to loop over them, because
those notes
won’t be in the order that you specified above. They will be tied to the
order
of the books that were found.
To get the notes in a special order you need to perform a find on the
Note
class, so you can specify a sort order for the notes. Here’s how I would
probably do it, assume these lines of code come after my revised @books
statement:
book_ids = @books.collect { |b| b.id} # this gets you a list of book
ids
@notes = Note.find( :all,
:include => :book,
:order => “notes.created_on”,
:conditions => [“notes.book_id in ?”, book_ids])
What this Find does, it bring back all the notes for the current user,
since we
only find the notes for the current user’s books, and sorts them by the
date/time each note was created. In addition, it tells ActiveRecord to
also grab
the book information for each note found.
In my views/notes/list.rhtml I can get all the notes fine, but what I
can’t get is what book they belong to.
<% for note in @notes %>
Doesn’t work: <%= note.book.title %>
Works: <%= note.description %>
I can’t figure out a clean way to display which book a note belongs to.
Now, using the @notes collection returned by the custom Find, you should
be able
to use your views/notes/list.rhtml template as you have it defined
above.
There are probably other ways to arrive at the same thing, but what I
put above
is definitely how I would go about getting the notes for a given user,
in their
creation order, with each note’s associated book info. It’s not the most
efficient way of working with your model, since it means duplicating the
book
info for every book that has more than one note, but it will give you
the result
you said you were looking for…
-Brian