-
-
Save mkdynamic/1965557 to your computer and use it in GitHub Desktop.
require 'active_support/concern' | |
module Foo | |
extend ActiveSupport::Concern | |
included do | |
class_eval do | |
def self.method_injected_by_foo | |
# ... | |
end | |
end | |
end | |
end | |
module Bar | |
extend ActiveSupport::Concern | |
include Foo | |
included do | |
self.method_injected_by_foo | |
end | |
def method_by_bar | |
# ... | |
end | |
end | |
class Host | |
include Bar # works, Bar takes care now of its dependencies | |
end |
module Foo | |
def self.included(base) | |
base.class_eval do | |
def self.method_injected_by_foo | |
# ... | |
end | |
end | |
end | |
end | |
module Bar | |
def self.included(base) | |
base.send(:include, Foo) | |
base.method_injected_by_foo | |
end | |
def method_by_bar | |
# ... | |
end | |
end | |
class Host | |
include Bar | |
end |
I think the idea is that ActiveSupport::Concern abstracts away the need to walk dependencies manually (in your example, base.send(:include, Foo)
). It literally makes zero sense in the example you give, with only one module, but the idea is that as you have increasingly complex (especially multi-level) module graphs, they manage their dependencies themselves.
Personally, I don't like it - like a lot of ActiveSupport, it makes everything really "magical" but is actually about ten lines of code that I'd rather see repeated when the pattern is in use for clarity's sake.
I like a lot of ActiveSupport, but this seems like an abstraction too far. Even in the multi-level module graphs scenario, I still don't see how it really provides any benefit. Like, the example above would work fine right? Can you share an example of a complex module graph where it breaks down? I cannot think of one...
Well, let's say I wanted to switch Foo and Bar in this example (so I'd have Host includes Foo includes Bar). With ActiveSupport::Concern, I need to swap only includes. Without, I need to modify where I'm sending :include to base, because otherwise base will be pointing to the parent module rather than the host class (where I want it to end up).
Again, though, I don't like it either - I'd rather have to understand what I'm doing and move a couple lines of code around.
How is the
ActiveSupport::Concern
example above (from http://api.rubyonrails.org/classes/ActiveSupport/Concern.html) any better or clearer than the plain Ruby version below?