Nicer routes in RESTful Rails...?

Hi all

Recently I updated my whole website to RESTful Rails. Before I had nice
hierarchical routes like

music/ => MusicController
music/artists => MusicArtistsController
music/albums => MusicAlbumsController
music/labels => MusicLabelsController

This was quite easy using custom routes. But now, I'm just using

map.resources :music
map.resources :music_artists
map.resources :music_albums
map.resources :music_labels

which causes that I don't have this cool hierarchy in the domain like
before, only

music/ => MusicController
music_artists => MusicArtistsController
music_albums => MusicAlbumsController
music_labels => MusicLabelsController

Is there an easy way to gain the hierarchy back? :slight_smile:

Thanks
Josh

map.resources :music do |music|
  music.resources :artists
  music.resources :albums
  music.resources :labels
end

can be nested deeper, too
and map.namespace allows for something like an admin namespace

Thorsten Mueller wrote:

map.resources :music do |music|
  music.resources :artists
  music.resources :albums
  music.resources :labels
end

can be nested deeper, too
and map.namespace allows for something like an admin namespace

Looks good, but when using

map.resources :music do |music|
  music.resources :music_artists
end

I will get

music/music_artists

But I'd like to have

music/artists

:slight_smile:

i'm sure, you can fix that... :wink:

Could you be a little more specific? You don't mean that I should rename
my controllers, do you?

Joshua Muheim wrote:

Could you be a little more specific? You don't mean that I should rename my controllers, do you?
  

That's what I would do.

Jon Garvin wrote:

Joshua Muheim wrote:

Could you be a little more specific? You don't mean that I should rename
my controllers, do you?
  

That's what I would do.

--
http://www.5valleys.com/
http://www.workingwithrails.com/person/8078

That's OK, but what if I don't only have the model MusicArtist but also
DecorationArtist?

You didn’t read the solution well enough. You’re best of renaming your controller to artists_controller.

I guess I slowly get the idea... With RESTful Rails you can only use
route structures that are logically tied to the models and their
relations, right?

(I have renamed my model MusicArtist to Artist in the meanwhile.)

class Music < ActiveRecord::Base
  has_many :artists
end

class Artist < ActiveRecord::Base
  belongs_to :music
end

In this case this will work:

map.resources :music do |music|
  map.resources :artists
end

But this doesn't really make sense in my case. I want to be able to
structure it semantically, my models Music and Artist don't have any
relation to each other!

My website has different main parts, e.g. music, info etc. For each of
these main parts I have a controller: MusicController, InfoController
etc. When accessing

example.com/music

the MusicController delivers me with some common information about what
I can find in the sub sections of "music", e.g. a listing of music
artists in

example.com/music/artists

So the relation between MusicController (which doesn't even have its own
model!) and ArtistsController is only a semantically one, there's no
"real" relation between them!

So is it possible somehow to add the prefix "music/" to the routes of
Artist?

Ah, well I guess, I should use :path_prefix for this, right? There's no
easier, DRYer way to do this? Because at the moment my routes look like
this:

map.music 'music/:action/:id'
map.resources :artists, :path_prefix => '/music'
map.resources :labels, :path_prefix => '/music'
map.resources :styles, :path_prefix => '/music'

It would be nicer to have something like

map.path_prefix :music do |prefix|
  prefix.resources :artists
  prefix.resources :labels
  prefix.resources :styles
end

Thanks for informations. :slight_smile:
Josh

@Joshua -- REST, even in its Rails incarnation, does not have any
requirement about the naming of models/controllers or their
interaction. A resource, in the REST vernacular, is simply an
addressable object that understands how to respond to a particular set
of commands. Technically speaking, a resource could be a front for
one object (the Rails standard from script/generate scaffold) but you
could also have a resource that is composed of many objects (e.g., a
blog post with comments could be represented as a single resource) and
even one with no models (e.g., the Session from
restful_authentication).

In your particular case it really sounds like you want to look into
namespacing routes. This would allow you to create a hierarchy of
controllers (app/controllers/music, app/controllers/film) and have
separate controllers for each 'namespace'... but all of them could be
fronts for the same set of models. As Thorsten mentions, this is
often done with 'admin', allowing an index with edit links and an edit
page only for admins while the rest of the community may see only an
index and show.

map.namespace :music do |music|
  music.resources :artists
  music.resources :albums
end

map.namespace :film do |film|
  film.resources :artists
  film.resources :movies
end

=>
/music/artists
/music/albums

/film/artists
/film/movies

etc

HTH,
AndyV

Thanks for your explanation, Andy.

I figured it out how to achieve the results that I want on my own:

map.resources :artists,
  :name_prefix => 'music_',
  :path_prefix => '/music',
  :controller => 'music_artists'

But now I tried it with namespace:

map.namespace :music do |music|
  map.resources :artists, :name_prefix => '_music'
end

But now I'm getting the error "No action responded to artists".

What am I doing wrong?

Thanks again,
Josh

You need to do:

  map.namespace :music do |music|
    map.resources :artists, :controller => 'music_artists'
  end

I suggest you read David Black's eBook on Rails routing, The Rails Way
by Obie Fernandez, or read one of the various RESTful routing PDF's
out there. It will explain all of this. :slight_smile:

--Jeremy

Thanks for your help! But

  map.namespace :music do |music|
    map.resources :artists, :controller => 'music_artists'
  end

gives me

Unknown action
No action responded to artists

and

  map.namespace :music do |music|
    music.resources :artists, :controller => 'music_artists'
  end

gives me

NameError in Music/music artistsController#show
uninitialized constant Music

Any idea? :wink:

Ah stupid typos on my part. Also, when you namespace, you need to
move them into their own directory. So, for example, you'd need to
move app/controllers/artists_controller.rb into
app/controllers/music/artists_controller.rb.

Then, this should work:

map.namespace :music do |music|
  music.resources :artists
end

And you should get url's like 'music/artists' with the ability to have
something like 'painting/artists' too.

--Jeremy

Cool! Does this work with models, too? Instead of having

music_styles.rb
music_artists.rb

I could use

music/styles.rb
music/artists.rb

Jeremy McAnally wrote:

You need to do:

  map.namespace :music do |music|
    map.resources :artists, :controller => 'music_artists'
  end

I suggest you read David Black's eBook on Rails routing, The Rails Way
by Obie Fernandez, or read one of the various RESTful routing PDF's
out there. It will explain all of this. :slight_smile:

--Jeremy

But now I tried it with namespace:
Thanks again,
Josh
--
Posted via http://www.ruby-forum.com/.

>

--
http://jeremymcanally.com/
http://entp.com

Read my books:
Ruby in Practice (http://manning.com/mcanally/)
My free Ruby e-book (http://humblelittlerubybook.com/)

Or, my blogs:
http://mrneighborly.com
http://rubyinpractice.com

What is the best way to map example.com/admin/orders/:action to
./app/controllers/admin/orders_controller.rb

I had some problems in production (no idea why it only showed there or
how to troubleshoot it), but I finally got it working with the following
code:

map.resources :orders, :controller => 'admin/orders', :name_prefix =>
'admin_', :path_prefix => 'admin'

What is the impact of this? ie: suppose I wanted a public viewable list
orders from example.com/orders/list

Also, for whatever reason, example.com/admin/orders/list still gives me
a 404, but without the action it works fine.

Anthony:

http://frozenplague.net/2008/03/16/administration-namespacing/