Corey Haines has already masterfully expounded on why ActiveSupport::Concern will lead to you having a Real Bad Time - and you really should read it, but I wanted to write a quick cautionary tale to those thinking about using Concerns and highlight a couple of the more practical pains explicitly.

The Headless Horseman

ActiveSupport::Concern may not have been intended to be used this way, but I see it used this way in a lot of Rails projects I’ve worked on since the introduction of Concerns. I’m talking about discorporated methods:

require 'active_support/concern'

module MonsterConcern
  extend ActiveSupport::Concern

  included do
    def can_fangs_be_seen_by_children?
      nearby_children.can_see?(:fangs)
    end

    def shaggy_monster
      make_coat_type(:shaggy)
    end

    def engage_rage
      ...
    end

    def chew_bones
      ...
    end
  end
end

We have four disembodied methods here, stuck in a file. We get no indication of whom includes this file - if we’re lucky the name might reflect that information, but it’s still not exact. Where should we go to see where the nearby_children method is defined?

The Goose Chase

Let’s say we want to look at the make_coat_type method. Where is it? It could be on the Monster model, but it’s not. If we’re lucky, maybe we spy a file called monster_coat_type.rb, but chances are it’s bundled into something bigger. Eventually we find the appropriate method, but it’s in another concern file that we didn’t expect.

Hunt and Peck

New developers might look through a couple of files before they hit the thing they are looking for, because Concerns give no indication of what they contain at the file name level. Better developers will grep immediately, but even then they might waste time optimistically looking in a couple of file that seem likely first.

Conclusion

ActiveSupport::Concern actually makes your code base worse. They make it:

  • Harder to reason about the code you are currently reading. You must satisfy several mental dependencies before you can make any kind of informed change in the code you are looking at. This increased mental barrier also makes it more likely that a developer will make a mistake in the code they are changing inside a concern.

  • Harder to navigate the codebase. If I want to look at the make_coat_type method, I have to already know that it:

    • Doesn’t live on the main Monster model.
    • Is actually inside another file which contains a different Concern
  • Encourage a use of Modules that is just as bad as ‘The Kitchen Drawer’ approach to using the lib directory that we know is bad, but this time it’s at a much more fine grained line-of-code level.

This is all symptomatic of the Rails world only now just coming to terms with some of the Domain Driven Design concepts of Services, and at the same time having the project leader stand behind a really badly thought out approach to handling complex large software projects.

Your Models don’t deserve this fate - tearing methods away from them and placing them in the Phantom Zone that is ActiveSupport::Concerns. Give them and anyone who might read the code other than you a chance for a better life, and if you need further guidance, there’s this excellent CodeClimate post which shows SEVEN ways not to use Concerns.