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
