Skip to content

Instantly share code, notes, and snippets.

@mkdynamic
Created March 3, 2012 11:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mkdynamic/1965557 to your computer and use it in GitHub Desktop.
Save mkdynamic/1965557 to your computer and use it in GitHub Desktop.
ActiveSupport::Concern — why?
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
@mkdynamic
Copy link
Author

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?

@bri3d
Copy link

bri3d commented Mar 13, 2012

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.

@mkdynamic
Copy link
Author

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...

@bri3d
Copy link

bri3d commented Mar 13, 2012

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment