What does #self.included(base) do in Ruby on Rails

2019-03-08 00:56发布

问题:

I thought we would do

helper_method :current_user, :logged_in?, :authorized?

to make these controller methods available for use as helper methods in views. But in Restful Authentication's lib/authenticated_system.rb, I see:

# Inclusion hook to make #current_user and #logged_in?
# available as ActionView helper methods.
def self.included(base)
  base.send :helper_method, :current_user, :logged_in?, :authorized? if base.respond_to? :helper_method
end

Why is it done this way instead of that single line? Also, I don't see included being called anywhere.

回答1:

The self.included function is called when the module is included. It allows methods to be executed in the context of the base (where the module is included).

More info: a ruby mixin tutorial.



回答2:

When the AuthenticatedSystem method is included using the include method, the self.included method is triggered with whatever it was included into being the argument of base.

The code you've shown calls helper_method and defines some helpful helpers, but only if the base has a helper_method method.

It's done that way so including the module can set up the helper methods as well as adding additional methods to the class.



回答3:

Out of the same reason which Peter has mentioned I would like to add an example so that it's easy for the newbie developers to understand self.included(base) and self.extended(base) :

module Module1
 def fun1
    puts "fun1 from Module1"
 end

 def self.included(base)
    def fun2
        puts "fun2 from Module1"
    end
 end
end

module Module2
 def foo
    puts "foo from Module2"
 end

 def self.extended(base)
    def bar
        puts "bar from Module2"
    end
 end
end


class Test
include Module1
extend Module2
 def abc
    puts "abc form Test"
 end
end

Test.new.abc #=> abc form Test

Test.new.fun1 #=> fun1 from Module1

Test.new.fun2 #=> fun2 from Module1

Test.foo #=> foo from Module2

Test.bar #=> bar from Module2

extend : methods will be accessible as class methods

include : methods will be available as instance methods

"base" in self.extended(base) / self.included(base) :

The base parameter in the static extended method will be either an instance object or class object of the class that extended the module depending whether you extend a object or class, respectively.

When a class includes a module the module’s self.included method will be invoked. The base parameter will be a class object for the class that includes the module.



回答4:

As it is the first result when searching Google for "self.included(base)" I will try to give a small example on how it works. I don't know how much it differs from the restful-authentication-approach.

It is basically used to make methods from one module available in another module.

module One
  def hello
    puts 'hello from module One'
  end
end

module Two
  def self.included(base)
    base.class_eval do
      include One
    end
  end
end

class ExampleClass
  include Two
end

ExampleClass.new.hello # => hello from module One


回答5:

Want to digger into self.included and self.extended ?

Please look at here: https://ruby-doc.org/core-2.2.1/Module.html#method-i-included