“Fat model, skinny controller” is a mantra. It’s a good mantra. But since `ApplicationController` is an abstract class, that’s not exactly easy (or good practice.)
As the complexity of your application grows, you’ll find yourself in `application_controller.rb` quite a bit: adding methods and helpers for analytics, error handling, tracked events, roles/authorization, feature flags, etc. It’s easy to just pile everything into one file, but that’s gross and not very maintainable.
Thankfully, Ruby allows us to modify/change objects at runtime with incredible ease, and
ActiveSupport allows us to manage these objects and sprinkle their parts on top its predefined layer in a memory-efficient way.
Setup is simple: create a directory called
Let’s pretend we have a
User table with the usual
Let’s create a file called
roles_dependency.rb inside our newly-created
app/controllers/application_controller directory. It looks like this:
class ApplicationController helper_method ::employee?, :developer?, :biztools_user?, :site_admin? def employee? user_signed_in? && current_user.employee? end def developer? user_signed_in? && current_user.developer? end def biztools_user? user_signed_in? && (current_user.biztools_user? || current_user.site_admin?) end def site_admin? user_signed_in? && current_user.site_admin? end end
If you’re a novice or even junior Rails developer, you might be freaking out that we reopened our
ApplicationController class, let alone have a directory of
app/controllers/application_controller. You might also be asking “why isn’t this a module called Roles”, or thinking “well why not make this a concern?”
The argument against a concern
Simply put, this isn’t really a mix-in. We’re just taking code that would otherwise live in
application_controller.rb and putting it in a more manageable spot.
ApplicationController code, after all.
It is, however, acceptable to introduce this as a concern to novice Rails developers.
Doing the dirty
ActiveSupport has a module called
Dependencies that does a lot of the heavy lifting for us as far as loading and caching but also making things behave the way we expect.
ActiveSupport::Dependencies there’s a method called
require_dependency. It’s cool.
Back to ApplicationController
application_controller.rb we don’t need to do anything weird but simply add
require_dependency 'application_controller/roles_dependency' inside our class definition.
class ApplicationController < ActionController::Base require_dependency 'application_controller/roles_dependency' end
And there you have it.
You can apply this same concept to other parts of your fat files, like
User, with no additional steps.