Nested routes don't work for me?

Hi all

I'm quite new to RESTful Rails and tried a bit with a new app, but it seems I don't comprehend something yet.

I have the following two models:

class CompactDisc < ActiveRecord::Base   belongs_to :genre   validates_presence_of :genre end

class Genre < ActiveRecord::Base   has_many :compact_discs end

In routes.rb I have the following route:

ActionController::Routing::Routes.draw do |map|   map.resources :compact_discs

  map.resources :genres do |genre|     genre.resources :compact_discs, :name_prefix => 'genre_'   end

  ... end

When opening localhost:3000/compact_discs it shows me all CD's. When opening localhost:3000/genres/1/compact_discs it still shows me all CD's! Shouldn't it only display the ones that are associated to genre 1 now? Or did I miss something?

I also played with

map.resources :genres, :has_many => :compact_discs

but this didn't help me neither...

Thanks for help :slight_smile: Josh

Hi all

I'm quite new to RESTful Rails and tried a bit with a new app, but it seems I don't comprehend something yet.

I have the following two models:

class CompactDisc < ActiveRecord::Base belongs_to :genre validates_presence_of :genre end

class Genre < ActiveRecord::Base has_many :compact_discs end

In routes.rb I have the following route:

ActionController::Routing::Routes.draw do |map| map.resources :compact_discs

map.resources :genres do |genre| genre.resources :compact_discs, :name_prefix => 'genre_' end

... end

Those routes look good....

When opening localhost:3000/compact_discs it shows me all CD's. When opening localhost:3000/genres/1/compact_discs it still shows me all CD's! Shouldn't it only display the ones that are associated to genre 1 now? Or did I miss something?

I also played with

map.resources :genres, :has_many => :compact_discs

but this didn't help me neither...

Thanks for help :slight_smile: Josh -- Posted viahttp://www.ruby-forum.com/.

When you have nested routes, Rails handles *almost* everything for you, but you need to adjust your index action to be aware of the "parent" resource:

def index   if params[:genre]     @genre = Genre.find(params[:genre])     @compact_discs = @genre.compact_discs   else     @compact_discs = CompactDisc.find(:all)   end

  # continue code here end

In other words, you want to detect if you're nested inside a genre, and in that case, only show the discs for that genre.

There are more elegant ways to do this, too (many people use a before_filter, etc.)

Does this help at all?

Jeff

REST with Rails: Oct 4, 2008, Austin, TX http://www.purpleworkshops.com/workshops/rest-and-web-services

Does this help at all?

Jeff

Thanks a lot, Jeff. Can you point me into some "best practices" on how to make this work? before_filter etc...?

Joshua Muheim wrote:

Does this help at all?

Jeff

Thanks a lot, Jeff. Can you point me into some "best practices" on how to make this work? before_filter etc...?

Well, created one myself. You think this is safe and clean/DRY? :slight_smile:

  private   def prepare_compact_discs     genre = (params[:genre_id] ? Genre.find(params[:genre_id]) : nil)     @compact_discs = (genre ? genre.compact_discs : CompactDisc.find(:all))   end

Btw, in your example before you should have used params[:genre_id], not only params[:genre]. Thanks anyway.

Joshua Muheim wrote: >> Does this help at all?

>> Jeff

> Thanks a lot, Jeff. Can you point me into some "best practices" on how > to make this work? before_filter etc...?

Well, created one myself. You think this is safe and clean/DRY? :slight_smile:

private def prepare_compact_discs genre = (params[:genre_id] ? Genre.find(params[:genre_id]) : nil) @compact_discs = (genre ? genre.compact_discs : CompactDisc.find(:all)) end

It's probably a matter of taste, but I tend to recommend something like this:

before_filter :find_genre

def index @compact_discs = @genre ? @genre.compact_discs || CompactDisc.find(:all)

# ... end

def find_genre   @genre = Genre.find_by_id(params[:genre_id]) # returns nil if not foun end

Some people prefer this:

before_filter :load_for_genre

def index # Find all discs only if we don't have any yet @compact_discs ||= CompactDisc.find(:all) end

def load_for_genre @compact_discs = Genre.find(params[:genre_id]).compact_discs if params[:genre_id] end

Again, I don't think there's a right or wrong necessarily - whatever you think keeps the code the clearest.

Btw, in your example before you should have used params[:genre_id], not only params[:genre]. Thanks anyway.

Good catch.

Jeff

REST with Rails: Oct 4, 2008, Austin, TX http://www.purpleworkshops.com/workshops/rest-and-web-services

Again, I don't think there's a right or wrong necessarily - whatever you think keeps the code the clearest.

Thanks, interesting ways! :slight_smile: Let's me feel like a complete newbie again and again :wink: