Symmetrical Routes for Nested Resources
|
|
I’m having trouble setting up nested resources in a particular way that makes sense to me. Given rules like these:
I have a many-to-many relationship of Owners-to-Books with the “link” table (we’ll call it “Ownerships” since I can’t think of a nice name) having an attribute for tracking the number of copies of a book an owner owns. I have no problem listing all books, or listing all owners: What I can’t figure out is how to set up my routes/controllers to list all books owned by a particular owner, and all owners that own a particular book (i.e. what I call “symmetrical routes for nested resources”). I’d like the URLs to look something like this:
What’s extra tricky is that I want the listings to also contain the number of copies from the “link” table. So, for example, http://127.0.0.1:3000/owners/7/books.xml might return the equivalent of this as XML: To Kill A MockingBird, 2 The Zombie Survival Guide, 1 War and Peace, 4 Please help this noob :-) Thanks, Mike |
|
|
Hey Mike, Be forewarned I haven’t tried any of the following to check my syntax, and I’m assuming you’re on Rails 2.0 or higher…. I assume you’ve already done something like this to get the “normal” routes working: map.resources :books map.resources :owners But it may not be obvious that you can do this: map.resources :books, :has_many => :owners map.resources :owners, :has_many => :books This means that the OwnersController’s So a common approach is to use a before_filter to find out which scenario we’re in. Also, it sounds like once you find the owners, you need to transform those to the ownerships: class OwnersController < ApplicationController before_filter :find_book def index # If we're being used as an "inner" resource, then # only get the owners for the given book @owners = @book.owners if @book # Otherwise, we should get all books @owners ||= Owner.find(:all) # Or you can do Owner.all in Rails 2.1 or above) respond_to do |format| format.html # render html template format.xml # render xml template end end def find_book # Find the "outer" resource if necessary @book = Book.find(params[:book_id]) if params[:book_id] end In your XML template, you can loop through all the ownerships, and whenever you need the number of copies, use the ownership data:
xml.book_data do
@owners.each do |owner|
xml.title owner.ownership.book.title
xml.copies owner.ownership.copies
end
end
Does this help at all? |
|
|
Wow. I can’t imagine a better response to a software development question. It’s precisely what I needed, and it worked like a charm. Thanks! |
|
|
Great! |