Cleaning up your icky ApplicationController

C

“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

Setup is simple: create a directory called application_controller in app/controllers

Usage

Let’s pretend we have a User table with the usual id and email attributes, but also a boolean of employee , site_admin?,biztools, and developer.

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.

This is 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.

Inside ActiveSupport::Dependencies there’s a method called require_dependency. It’s cool.

Back to ApplicationController

Inside our 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.

outside controllers

You can apply this same concept to other parts of your fat files, like User, with no additional steps.

By Josh