Software Development | Ruby on Rails
concerned_with Pattern

Concerned_with is a pattern created by Rick Olsen to divide a model into separate concerns, each within a separate file. This pattern means each file is clean and encapsulates just the functionality related to the specific concern.

Criticisms of concerned_with

This technique, however, has been criticised on several grounds. You'll see several objections in the comments of Paul Barry: Concerned With: Skinny Controller, Skinny Model. In summary people think concerned_with:

  • breaks up the user model and you have to go looking for the pieces
  • puts files in the models directory that are not proper models
  • duplicates the existing capability of modules and plugins to encapsulate behaviour.
  • doesn't have the behaviour sharing capability of modules and plugins . Erik Petersen in particular makes a compelling argument that the model should be the thing and the behaviour should be in a plugin.
  • has an issue with eager loading (Ruby Forum: RSpec > concerned_with, and maybe require_dependency issues only when running specs?)

Altered_beast and concerned_with

Altered_beast uses concerned_with to implement the user model. In user.rb you'll see that the user class has a "states" concern, and an "activation" concern, etc. This is the line that does it:

app/models/user.rb

concerned_with :states, :activation, :posting, :validation 

Concerned_with is defined in the initializer called concerns.rb:

config/initializers/concerns.rb

class << ctiveRecord::Base 
  def concerned_with(*concerns) 
    concerns.each do |concern| 
      require_dependency "#{name.underscore}/#{concern}" 
    end 
  end 
end 

As you see concerned_with assumes the files for each concern are in a sub-folder with the same name as the model. This is exactly what you'll find in the altered_beast models directory. You'll find the user.rb as you'd expect plus several files in the user sub-folder. These files are all part of the user model.

editable.rb

Although lumped into the same folder as the concerns, models/user/editable.rb is a module rather than a part of the User model. It is included in the Post and Topic models and provides the method editable_by?.

  • models/user.rb
  • models/user/activation.rb
  • models/user/posting.rb
  • models/user/states.rb
  • models/user/validation.rb

Conclusion

Having the logic in different files was a little confusing to start with but once I figured out what concerned_with meant it started looking pretty good to me. Makes for clean code. I'm a bit concerned with the issue raised about eager loading but the other criticisms worry me less. As somebody mentioned on Paul Barry: Concerned With: Skinny Controller, Skinny Model this is the same sort of mechanism that implements has_many, has_one, belongs_to etc.

Rating: Good but needs validating