Reputation: 243
I know many rails developers say that nesting your resources more then 2 levels deep is wrongdoing. I also agree because it gets messy when your urls looks like mysite.com/account/1/people/1/notes/1. I am trying to find a way to use nested resources but without nesting them 3 levels deep.
This is the wrong way of doing it since rails developers do not recommend it and also it's very difficult figuring out how to nest this in the controller or form view.
resources :account do
resources :people do
resources :notes
end
end
The correct way rails developer say this should be done is like so
resources :account do
resources :people
end
resources :people do
resources :notes
end
Here's the problem that I always run into. When ever I visit account/1/people I can add a person to the account and lets say the url is like so mysite.com/account/1/people/1 and that works fine.
Now if I try to access the mysite.com/people/1/notes from account 1 I get the error
Can't find people without and account id
How can get this to work properly?
Upvotes: 9
Views: 5116
Reputation: 12837
You nest the routes as deep as you like as rails 3.x allows you to flatten them using shallow: true
Try experimenting with
resources :account, shallow: true do
resources :people do
resources :notes
end
end
Use rake routes to see what you get :)
UPDATE in response to comment
As I said, play with rake routes to see what url's you can get
resources :account, shallow: true do
resources :people, shallow: true do
resources :notes
end
end
gets you these routes
:~/Development/rails/routing_test$ rake routes
person_notes GET /people/:person_id/notes(.:format) notes#index
POST /people/:person_id/notes(.:format) notes#create
new_person_note GET /people/:person_id/notes/new(.:format) notes#new
edit_note GET /notes/:id/edit(.:format) notes#edit
note GET /notes/:id(.:format) notes#show
PUT /notes/:id(.:format) notes#update
DELETE /notes/:id(.:format) notes#destroy
account_people GET /account/:account_id/people(.:format) people#index
POST /account/:account_id/people(.:format) people#create
new_account_person GET /account/:account_id/people/new(.:format) people#new
edit_person GET /people/:id/edit(.:format) people#edit
person GET /people/:id(.:format) people#show
PUT /people/:id(.:format) people#update
DELETE /people/:id(.:format) people#destroy
account_index GET /account(.:format) account#index
POST /account(.:format) account#create
new_account GET /account/new(.:format) account#new
edit_account GET /account/:id/edit(.:format) account#edit
account GET /account/:id(.:format) account#show
PUT /account/:id(.:format) account#update
DELETE /account/:id(.:format) account#destroy
As can be seen, you have access to all models at whatever level you decide you need. The rest is down to whatever you put in your controller actions.
You really have to work on the actions to make sure you take appropriate action when id params are not passed in, so if you make use of an id for a specific model then check that the id is in the params list and if not take alternative action. e.g. if you don't pass the account id in then make sure you don't try to use it
your comment states that you already use shallow routes, but that's not what you posted in your question?
Upvotes: 12