Rails advises to keep controllers and its actions resourceful buy providing resourceful routes helpers to create routes with default CRUD actions. However, very often, we find ourselves in a situation where we need to add more actions to a controller than those that are provided by resourceful routes. Lets look at such an example and see how we can better address such situations.

class JobsController < ApplicationController
  def index
    ...
  end

  def show
    ...
  end
end

In above example, Job is a resource, index and show actions are part of basic CRUD operations. Setting the routes for these actions is very simple in Rails with:

  resource :jobs, only: [:index, show]

Now, we want to add an option for the users to get a shareable link for the job. This link is to be generated dynamically with tracking parameters to recognise the user who shared this job. This link is not required to be stored anywhere.

Its easy to think of adding a new action shareable_link to the controller and add a respective route:

resource :jobs, only: [:index, :show] do
  member do
    get 'shareable_link'
  end
end

This is fine until we have many such extra actions in the controller. Our controller will quickly grow huge. The best way to deal with this is to rethink those actions and see if there can actually be their own resources.

Resources doesn’t have to be models.

Its a common misconception that resourceful routes in Rails are only for models.

In our above example, we don’t have a model that’s called ShareableLink but we can still see that as a resource nested under job. We can simply create a new controller assuming ShareableLink as a resource and add a resourceful route as follows:

# app/controllers/shareable_links_controller.rb
class ShareableLinksController < ApplicationController
  def create
    ...
  end
end

# config/routes.rb
resource :jobs, only: [:index, :show] do
  resource :shareable_links, only: [:create]
end

This way, we can keep our controllers more resourceful and lean making it easier to maintain them.

Summary

If we are adding too many actions to a controller that are not part of the basic resourceful route actions (index, create, show, update and delete), its best if we rethink those actions and see if they can be treated as different resources.

Also, a controller in Rails doesn’t have to be associated to an ActiveRecord model.