Reading code: concerns

Zat weer even te kijken hoe anderen in Ruby coderen. Voor het integreren van een forum in een applicatie, zat ik met altered_beast te werken. De manier hoe functionaliteit aan een User object toegevoegd werd was nieuw voor mij.

Een User model in een forum heeft verschillende 'concerns', functionaliteiten die je bij elkaar kunt groeperen zoals: authenticatie, posten van reacties, etc. Deze zijn gegroepeerd in aparte modules i.p.v. in een grote User class.

ActiveRecord word uitgebreid met een concerned_with methode om dependencies te laden.

1
2
3
4
5
6
7
class << ActiveRecord::Base
  def concerned_with(*concerns)
    concerns.each do |concern|
      require_dependency "#{name.underscore}/#{concern}"
    end
  end
end

In het User model geef je aan wat geladen moet worden, zoals posting.

1
2
3
4
class User < ActiveRecord::Base
  concerned_with :validation, :states, :activation, :posting
  #...
end

In user/posting.rb heb je dan alleen de functionaliteit m.b.t. het posten van reacties.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class User
  # Creates new topic and post.
  # Only..
  #  - sets sticky/locked bits if you're a moderator or admin 
  #  - changes forum_id if you're an admin
  #
  def post(forum, attributes)
    attributes.symbolize_keys!
    Topic.new(attributes) do |topic|
      topic.forum = forum
      topic.user  = self
      revise_topic topic, attributes
    end
  end
 
 #...
end

Ik heb zelf nog geen oordeel over, ik moest in eerste instantie de code gewoon begrijpen. Het voordeel is dat je i.p.v. wat regels met require_dependency, je een enkele regel hebt met een duidelijke intentie. Je zit niet te denken in het linken van modules, maar in de verantwoordingen van het object. Dit is goed. Het is echter altijd wel even uitzoeken hoe dit soort oplossingen in elkaar zit.