Search code examples
ruby-on-railsassociationsmodelsnested

I've read not to nest resources more than 2. How should I nest my Hotel/Room/Visit Model?


I've read in the past that nesting multiple resources is not good practice.

I've got models, Hotel, Room, and Visit. (H has_many R, R has many V)

If you're not supposed to nest this many times, like below...

  resources :hotels do
    resources :rooms do
      resources :visits
    end
  end

then what is the best practice?

I would like to be able to retrieve all the visits for a specific room via something like room/3/visits... but I would be unable to do that currently as the above code would break best practice nesting.


Solution

  • Shallow Nesting

    "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."

    See Rails Guide on Routing Section 2.7.2 Shallow Nesting for more information

    In your case, you'd be looking at:

    resources :hotels do
      resources :rooms, shallow: true
    end
    
    resources :rooms, only: [] do
        resources :visits
    end
    

    this is equivalent to:

    resources :hotels do
      resources :rooms, only: [:index, :new, :create]
    end
    resources :rooms, only: [:show, :edit, :update, :destroy]
    

    and would provide you with the following routes:

                     GET    /hotels/:hotel_id/rooms(.:format)            rooms#index
                     POST   /hotels/:hotel_id/rooms(.:format)            rooms#create
      new_hotel_room GET    /hotels/:hotel_id/rooms/new(.:format)        rooms#new
           edit_room GET    /rooms/:id/edit(.:format)                    rooms#edit
                room GET    /rooms/:id(.:format)                         rooms#show
                     PATCH  /rooms/:id(.:format)                         rooms#update
                     PUT    /rooms/:id(.:format)                         rooms#update
                     DELETE /rooms/:id(.:format)                         rooms#destroy
              hotels GET    /hotels(.:format)                            hotels#index
                     POST   /hotels(.:format)                            hotels#create
           new_hotel GET    /hotels/new(.:format)                        hotels#new
          edit_hotel GET    /hotels/:id/edit(.:format)                   hotels#edit
               hotel GET    /hotels/:id(.:format)                        hotels#show
                     PATCH  /hotels/:id(.:format)                        hotels#update
                     PUT    /hotels/:id(.:format)                        hotels#update
                     DELETE /hotels/:id(.:format)                        hotels#destroy
         room_visits GET    /rooms/:room_id/visits(.:format)             visits#index
                     POST   /rooms/:room_id/visits(.:format)             visits#create
      new_room_visit GET    /rooms/:room_id/visits/new(.:format)         visits#new
     edit_room_visit GET    /rooms/:room_id/visits/:id/edit(.:format)    visits#edit
          room_visit GET    /rooms/:room_id/visits/:id(.:format)         visits#show
                     PATCH  /rooms/:room_id/visits/:id(.:format)         visits#update
                     PUT    /rooms/:room_id/visits/:id(.:format)         visits#update
                     DELETE /rooms/:room_id/visits/:id(.:format)         visits#destroy