Jump to content

The ultimate community for Ruby on Rails developers.


Photo

[Best practices] Nested resources and shallow: true

shallow nested ressources best practices rails4

  • Please log in to reply
4 replies to this topic

#1 erowlin

erowlin

    Passenger

  • Members
  • 9 posts

Posted 17 February 2014 - 10:27 AM

Hello ! 

 

The following post is based on Rails 4. 

 

I'm actually looking for a good best-practices about the multiple nested resources (more than 1), and the option shallow: true. 

 

First in my routes, there was this : 

resources :projects do 
    resources :collections
  end

The routes associated are : 

project_collections GET    /projects/:project_id/collections(.:format)          collections#index
                        POST   /projects/:project_id/collections(.:format)          collections#create
 new_project_collection GET    /projects/:project_id/collections/new(.:format)      collections#new
edit_project_collection GET    /projects/:project_id/collections/:id/edit(.:format) collections#edit
     project_collection GET    /projects/:project_id/collections/:id(.:format)      collections#show
                        PATCH  /projects/:project_id/collections/:id(.:format)      collections#update
                        PUT    /projects/:project_id/collections/:id(.:format)      collections#update
                        DELETE /projects/:project_id/collections/:id(.:format)      collections#destroy
               projects GET    /projects(.:format)                                  projects#index
                        POST   /projects(.:format)                                  projects#create
            new_project GET    /projects/new(.:format)                              projects#new
           edit_project GET    /projects/:id/edit(.:format)                         projects#edit
                project GET    /projects/:id(.:format)                              projects#show
                        PATCH  /projects/:id(.:format)                              projects#update
                        PUT    /projects/:id(.:format)                              projects#update
                        DELETE /projects/:id(.:format)                              projects#destroy

I readed in the documentation about the llimitation of nested resources : 

 

 

 

Resources should never be nested more than 1 level deep.

 

Source : http://guides.rubyon...mits-to-nesting

 

ok. Then, like the documentation said, I'm gonna use "shallow" in my routes. 

 

shallow do
     resources :projects do 
          resources :collections
     end
end

 

 

The routes associated are : 

project_collections GET    /projects/:project_id/collections(.:format)     collections#index
                       POST   /projects/:project_id/collections(.:format)     collections#create
new_project_collection GET    /projects/:project_id/collections/new(.:format) collections#new
       edit_collection GET    /collections/:id/edit(.:format)                 collections#edit
            collection GET    /collections/:id(.:format)                      collections#show
                       PATCH  /collections/:id(.:format)                      collections#update
                       PUT    /collections/:id(.:format)                      collections#update
                       DELETE /collections/:id(.:format)                      collections#destroy
              projects GET    /projects(.:format)                             projects#index
                       POST   /projects(.:format)                             projects#create
           new_project GET    /projects/new(.:format)                         projects#new
          edit_project GET    /projects/:id/edit(.:format)                    projects#edit
               project GET    /projects/:id(.:format)                         projects#show
                       PATCH  /projects/:id(.:format)                         projects#update
                       PUT    /projects/:id(.:format)                         projects#update
                       DELETE /projects/:id(.:format)                         projects#destroy

The major difference I see is the "show" of collections, this one : 

collection GET    /collections/:id(.:format)                      collections#show

So if I I'm right, the link for the show action for a collection is : 

<%= link_to 'Show", collection_path(collection)%>

 and should return something like this : "http://localhost/collections/1"

 

BUT ! 2 things :

  1. This is not working. I'm getting instead "http://localhost/projects/1". WTF ?
  2. Even if it was working, it's actually pretty bad because I loose the REST basic that say "Collection is child of project, then the url should be "localhost/project/1/collections/1"

I don't understand what is the interest of shallow if it's to loose the big convenient of Rest actions. What is the interest ? And what is the interest to loose the "Show" action ? I Already posted this to SO, but the only comment i got is "It's something normal". WTF? In what actually this is something normal to "remove" an action of the rest API ?

 

* I reproduced the problem on a neutral project, to be sure that I was not doing something wrong, and the same problem happened. So, yes, it may be convenient for the helpers to use shallow, but it's  NOT AT ALL convenient for the rest, you loose all the interest of "one collection is nested to one project, so this is reflected in the URL".

 

I don't know if there is another way to do this, it's true that shallow allow more flexibility about the helpers, but it's false that it's rest compliant. So, is there any chance to get the "helpers" working (it's pretty awesome to have "nested3_path(collection)" instead of "nested1_nested2_nested3([nested1.nested2.nested3, nested1.nested2, nested1])", and keeping the "url part" and keep having "nested1/123/nested2/456/nested3/789 ? 

 

Thanks ! 

 


#2 erowlin

erowlin

    Passenger

  • Members
  • 9 posts

Posted 18 February 2014 - 04:34 AM

UP ?



#3 ringingEars

ringingEars

    Passenger

  • Members
  • 1 posts

Posted 19 February 2014 - 11:48 AM

From what I read about shallow, it makes sense if you want a balance between deep nesting and simple nesting.  Member routes like 'show' and 'edit' are tied to a specific ID of the nested resource, so while it may not read as pretty to give you all the info you need in the URL, it still readable.

 

For your link_to maybe try 

<%= link_to "Show", collection %>

, or 

<%= link_to "Show", collection_path(id: collection)%>

From rails guide:

 

One way to avoid deep nesting (as recommended above) is to generate the collection actions scoped under the parent, so as to get a sense of the hierarchy, but to not nest the member actions. In other words, to only build routes with the minimal amount of information to uniquely identify the resource, like this:

resources :posts do
  resources :comments, only: [:index, :new, :create]
end
resources :comments, only: [:show, :edit, :update, :destroy]

This idea strikes a balance between descriptive routes and deep nesting. There exists shorthand syntax to achieve just that, via the :shallow option.



#4 erowlin

erowlin

    Passenger

  • Members
  • 9 posts

Posted 03 March 2014 - 09:26 PM   Best Answer

Problem has been partially answered on StackOverflow : https://stackoverflo...nd-shallow-true


  • Jamie likes this

#5 Jamie

Jamie

    Controller

  • Moderators
  • 114 posts
  • LocationThe UK

Posted 05 March 2014 - 11:39 AM

Glad this has been solved.

 

Personally I'd look into not using Nested resources for larger scale apps as they become a pain and useless.


Rails developer based in Newcastle, UK.
Web app owner - Twitter lover





Also tagged with one or more of these keywords: shallow, nested ressources, best practices, rails4

0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users