Name: concerning
Owner: Basecamp
Description: Bite-sized separation of concerns
Created: 2013-07-02 18:17:27.0
Updated: 2017-05-06 14:24:24.0
Pushed: 2014-02-23 18:45:29.0
Size: 211
Language: Ruby
GitHub Committers
User | Most Recent Commit | # Commits |
---|
Other Committers
User | Most Recent Commit | # Commits |
---|
(Note! Module#concerning is included in Rails 4.1. You can still use this library, but it will defer to Active Support's implementation if available.)
We often find ourselves with a medium-sized chunk of behavior that we'd like to extract, but only mix in to a single class.
Extracting a plain old Ruby object to encapsulate it and collaborate or delegate to the original object is often a good choice, but when there's no additional state to encapsulate or we're making DSL-style declarations about the parent class, introducing new collaborators can obfuscate rather than simplify.
The typical route is to just dump everything in a monolithic class, perhaps with a comment, as a least-bad alternative. Using modules in separate files means tedious sifting to get a big-picture view.
s Todo
Other todo implementation
...
Event tracking
s_many :events
fore_create :track_creation
ter_destroy :track_deletion
f self.next_by_event
# ...
d
ivate
def track_creation
# ...
end
Noisy syntax.
s Todo
Other todo implementation
...
dule EventTracking
extend ActiveSupport::Concern
included do
has_many :events
before_create :track_creation
after_destroy :track_deletion
end
module ClassMethods
def next_by_event
# ...
end
end
private
def track_creation
# ...
end
d
clude EventTracking
Once our chunk of behavior starts pushing the scroll-to-understand it boundary, we give in and move it to a separate file. At this size, the overhead feels in good proportion to the size of our extraction, despite diluting our at-a-glance sense of how things really work.
s Todo
Other todo implementation
...
clude TodoEventTracking
By quieting the mix-in noise, we arrive at a natural, low-ceremony way to separate bite-sized concerns.
ass Todo
# Other todo implementation
# ...
concerning :EventTracking do
included do
has_many :events
before_create :track_creation
after_destroy :track_deletion
end
class_methods do
def next_by_event
# ...
end
end
private
def track_creation
# ...
end
end
d
do.ancestors
=> Todo, Todo::EventTracking, Object
This small step has some wonderful ripple effects. We can