Rails controllers and nested resources

The nested resource I am going to be referencing in this example is a Form nested within a User. The routes are defined like so:

~/config/routes.rb
Rails.application.routes.draw do
  resources :users do
    resources :forms
  end
end

And the resulting route structure:

/users/:user_id/forms/:id

In my forms controller methods I am gettings a form through a user, see the code below:

class FormsController < ApplicationController
  def update
    @user =  User.find(params[:user_id])
    @form = @user.forms.find(params[:id].to_i)
  end
end

This structure works fine, you just need to remember to handle routing/redirections appropriately, like I discuss here. However there is another way to structure this code that to me feels more accurate to it’s function and that is to update the controller to be a user_forms controller that inherits from the forms controller.

With this new setup any routes that need to access forms outside of the user context can query the FormsController and any forms that need to be accessed through a user can be handled through a UserFormsController. The resulting code changes follow.

Update the routes to account for both methods of accessing form resources. For the nested forms you need to explicitly point to the new UserFormsController.

~/config/routes.rb
Rails.application.routes.draw do
  resources :forms
  resources :users do
    resources :forms, controller: "user_forms"
  end
end

Now create a new UserFormsController that inherits from the FormsController to acquire general form behavior and migrate any actions in the FormsController that reference a form through a user to the UserFormsController like the below #update method.

~/app/controllers/user_forms_controller.rb
class UserFormsController < FormsController
  def update
    @user =  User.find(params[:user_id])
    @form = @user.forms.find(params[:id].to_i)
  end
end

Following the controller change your new code structure should function the same as before and now be understood a little more easily.