Tao
Tao

Reputation: 990

why do people use extend in a module definition?

for example, the rubygem Devise has the following piece of code in lib/devise/controllers/helpers.rb

    module Helpers
      extend ActiveSupport::Concern

why use extend here? Will include do the same?

Upvotes: 2

Views: 177

Answers (2)

Jörg W Mittag
Jörg W Mittag

Reputation: 369624

Basically, Object#extend is just:

class Object
  def extend(*ms)
    ms.each do |m|
      class << self
        include m # Obviously, this won't work since m isn't in scope
      end
    end
  end
end

So, it's easy to see that they are obviously not the same, since the methods end up in different classes.


A working, but less obvious version of Object#extend would be:

class Object
  def extend(*ms)
    ms.each do |m|
      singleton_class.send :include, m # Because Module#include is private
    end
  end
end

Upvotes: 2

Chowlett
Chowlett

Reputation: 46685

No, include will not do the same.

extend and include perform similar but distinct roles. include takes the instance methods of the included module and makes them available to instances of the including module. In effect, include inserts the included module as a superclass of the including (in fact, #ancestors will even show the included module).

extend, on the other hand, adds the methods of the named module to the receiver. In the case of calling extend during a module definition, that means that the "extended" module's instance methods will become class methods of the "extending" module. It's often used to import decorators (really just calls to class methods) into a class or module being defined.

So, in brief, the snippet above will take the instance methods of ActiveSupport::Concern and make them class methods of Helpers.

Upvotes: 3

Related Questions