Что делает #self.included(base) в Restful Authentication Ruby on Rails?

Я думал, что мы сделаем

helper_method :current_user, :logged_in?, :authorized?

чтобы сделать эти методы контроллера доступными для использования в качестве вспомогательных методов в представлениях. Но в Restful Authentication lib/authenticated_system.rb я вижу:

# 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

Почему это делается именно так, а не в одной строке? Кроме того, я нигде не вижу вызова included.


person nonopolarity    schedule 01.03.2011    source источник


Ответы (5)


Функция self.included вызывается при включении модуля. Это позволяет выполнять методы в контексте базы (куда включен модуль).

Дополнительная информация: руководство по миксинам ruby.

person nathanvda    schedule 01.03.2011

По той же причине, о которой упомянул Питер, я хотел бы добавить пример, чтобы начинающим разработчикам было легко понять self.included(base) и self.extended(base)< /эм> :

module Module1
 def fun1
    puts "fun1 from Module1"
 end

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

 def self.extended(base)
   def fun3
     puts "fun3 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

class Test2
  extend Module1
end

Test.new.abc #=› форма abc Тест

Test.new.fun1 #=› fun1 из Module1

Test.new.fun2 #=› fun2 из Module1

Test.foo #=› foo из Module2

Test.bar #=› бар из Module2

Test.new.fun3 #=› NoMethodError (неопределенный метод `fun3' ..)

Test2.fun3 #=› fun3 из Module1

extend : методы будут доступны как методы класса

include : методы будут доступны как методы экземпляра

base в self.extended(base) / self.included(base):

Базовый параметр в статическом расширенном методе будет либо объектом экземпляра, либо объектом класса класса, который расширил модуль, в зависимости от того, расширяете ли вы объект или класс соответственно.

Когда класс включает модуль, будет вызван метод модуля self.included. Базовым параметром будет объект класса для класса, включающего модуль.

person FaaduBaalak    schedule 03.01.2017
comment
Хорошее объяснение @FaaduBalak сделало мой день - person Aashish; 03.04.2018
comment
Привет @FaaduBaalak, не могли бы вы вкратце рассказать об «объекте экземпляра или объекте класса», я немного запутался в объекте класса. Разве объект класса не означает экземпляр класса или не то же самое. Если нет, то какая разница? Спасибо. - person codemilan; 13.07.2018
comment
@codemilan извините, я видел это сегодня. Удалось узнать разницу? - person FaaduBaalak; 06.09.2018
comment
Спасибо @FaaduBaalak за ваш ответ. Но в чем разница между fun1 и fun2 — последний определяется в self.included(base), а первый — нет. ясность будет высоко оценена. - person BKSpurgeon; 14.01.2020
comment
@BKSpurgeon Добавил еще 2 примера для большей ясности. Спасибо - person FaaduBaalak; 23.01.2020
comment
Я не знаю, что (если что) изменилось, но в Ruby 2.7.0 Test.new.fun3 работает просто отлично: #=> fun3 from Module1 - person Arta; 27.01.2020
comment
я разместил вопрос в новой теме, stackoverflow.com/questions/61669750/ в основном вам нужно добавить def base.fun3 - person noobyz; 11.05.2020

Когда метод AuthenticatedSystem включается с помощью метода include, метод self.included запускается с тем, что было включено в качестве аргумента base.

Код, который вы показали, вызывает helper_method и определяет несколько полезных помощников, но только если base имеет метод helper_method.

Это сделано таким образом, чтобы включение модуля могло настроить вспомогательные методы, а также добавить дополнительные методы в класс.

person Ryan Bigg    schedule 01.03.2011

Поскольку это первый результат поиска в Google по запросу «self.included(base)», я попытаюсь привести небольшой пример того, как это работает. Я не знаю, насколько это отличается от подхода с спокойной аутентификацией.

Он в основном используется для того, чтобы сделать методы из одного модуля доступными в другом модуле.

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
person Peter Piper    schedule 04.08.2016
comment
спасибо за ответ, но можно просто добавить строку: include One в модуль Two и результат будет тот же, не так ли? В чем преимущество использования подхода self.included(base)? - person BKSpurgeon; 14.01.2020

Хотите покопаться в self.included и self.extended ?

Пожалуйста, посмотрите здесь: https://ruby-doc.org/core-2.2.1/Module.html#method-i-included

person Lane    schedule 24.03.2017