Anytime your controllers start to accumulate non-standard CRUD (Create, Read, Update, Delete) action names, you may consider extracting the action into a new controller where the action can become one of the standard CRUD action names. Often times, you’ll find that this reveals a hidden resource in your domain model, in addition to keeping your controllers lean and easy to reason about.
Keep in mind, Rails is optimized for doing CRUD operations — it’s where Rails shines brightest. From the resourceful routing DSL all the way to the simple ActiveRecord persistence, Rails makes these standard operations a breeze. While Rails is very flexible about allowing you to deviate from that path, I’ve found that the the more you can adhere to that convention the easier your application becomes to maintain.
Let’s look at an example:
class UsersController < ApplicationController
def show
#...
end
# profile is a non-standard CRUD action name, can we move it elsewhere?
def profile
#...
end
end
You can extract the profile action into a ProfilesController!
class UsersController < ApplicationController
def show
#...
end
end
class ProfilesController < ApplicationController
def show
#...
end
end
We can also use namespacing to help clarify relationships post-split - for example:
You could move
ProjectsController#cancel
toProjects::CancellationsController#create
.- Maybe this is revealing a hidden resource/model:
Project::Cancellation
?
- Maybe this is revealing a hidden resource/model:
Shift
UsersController#settings
toUsers::SettingsController#edit
.Relocate
OrdersController#refund_status
toOrders::RefundStatusesController#show
.- 👆 Just based on naming, this might be an example of where you might not extract a controller. I’m not entirely sure
RefundStatusesController
is more intuitive or justifies it’s own model/resource. I left it in here as an example of how these things aren’t always black and white.
- 👆 Just based on naming, this might be an example of where you might not extract a controller. I’m not entirely sure
This approach has been directly mentioned by DHH in the past, and is referenced in a number of other places. Feel free to read about that here: How DHH Organizes His Rails Controllers