Akshat
Akshat

Reputation: 655

Difference between redefining self.included and passing block to included

What's the difference between

module A
  def self.included(klass)
    puts klass
  end
end

and

module A
  include ActiveSupport::Concern
  included do
    puts self
  end
end

Which one is a better and which one to use when?

Upvotes: 3

Views: 707

Answers (2)

Simone Carletti
Simone Carletti

Reputation: 176552

Both snippets produce the same result. However, there is a small but important difference.

The first code is pure Ruby. It means it will work without any dependency.

The second piece of code depends on ActiveSupport that is an external dependency. If you want to use it you need to include the gem in your project. In a Rails application, there is almost no overhead because the application already depends on ActiveSupport. But in a non-Rails application, it may not be convenient.

Moreover, ActiveSupport::Concern does a lot more than simply adding some syntactic sugar for the Ruby included hook. In fact, the primary scope of such module was to manage multiple dependencies between modules.

In the Rails codebase it's very common to define small piece of features into separate modules. A good example is ActiveSupport itself. However, you may have that the feature A may require some feature defined in the module B, so if you include B in your code, then the module should make sure to require and mix also A, otherwise your code will crash.

It also implements a very common pattern based on the included hook: class-level extensions. The following Ruby code

module A
  def self.included(base)
    base.extend ClassMethods
  end

  module ClassMethods
    def bar
      "bar"
    end
  end
end

class Foo
  include A
end

Foo.bar
# => "bar"

becomes

module A
  extend ActiveSupport::Concern

  module ClassMethods
    def bar
      "bar"
    end
  end
end

class Foo
  include A
end

Foo.bar
# => "bar"

My personal advice is to avoid using the ActiveSupport::Concern if

  • You don't need to use its advanced features
  • The code you are writing, can be easily written with a few code with no dependency on Concern
  • The app does not already include ActiveSupport as dependency

Upvotes: 4

sawa
sawa

Reputation: 168249

In your second piece of code, included is called once during when A is defined. It does not do anything unless you had defined included to do something. The block passed to included would have no effect unless you had overwritten included to take a block and do something with it. In short, your second piece of code does not make sense.

Upvotes: -1

Related Questions