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: