Avoiding extra actions on resourceful Rails controllers
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.