即使没有导入模块

时间:2016-06-29 14:39:44

标签: ruby-on-rails ruby authentication devise

所以,我在自定义注册页面中自定义设计,这需要我在创建帐户以及其他一些操作后 sign_in 用户。创建资源后我做了

sign_in resource if resource.active_for_authentication?

并在用户中签名。我的控制器继承了     ApplicationController的 而我还没有包含任何这样的模块

include Devise::Controllers::SignInOut

rails如何知道

sign_in

方法

1 个答案:

答案 0 :(得分:2)

基本答案 - 模块Devise :: Controllers :: Helpers(包括你发现的Devise :: Controllers :: SignInOut)由一个名为“devise”的Devise初始化程序自动包含在ApplicationController中.url_helpers”。通过添加Devise gem包含初始化程序,其内容在rails应用程序启动期间运行。

更深入

Devise是一个Rails引擎 - 您可以查看this文章进行简要回顾。

  

发动机可以被认为是提供的微型应用   其主机应用程序的功能。一个Rails应用程序是   实际上只是一个“增压”引擎,使用Rails :: Application   class从Rails :: Engine继承了很多行为。

     

...

     

引擎也与插件密切相关。

然后,您将在Devise的rails.rb中找到以下调用(gem root devise.rb文件需要此rails.rb - 见下文)here

   initializer "devise.url_helpers" do
      Devise.include_helpers(Devise::Controllers)
   end

要说明,initializer这里不是一个方法定义,但是实际调用带有字符串名参数和块参数的类方法。它是在类加载时执行的(即由require加载类的结果)。同时,传递的块作为此调用的参数,并且在此特定情况下保存以便稍后执行 - 请参阅下面的初始化程序说明。

引擎上的

旁注(事实上是铁路)初始化概念

初始化程序是Rails基本类之一Railtie的概念。概念描述为here

  

初始化程序 - 要从Railtie到Rails启动过程添加初始化步骤,您只需创建一个初始化程序块:

  #   class MyRailtie < Rails::Railtie
  #     initializer "my_railtie.configure_rails_initialization" do
  #       # some initialization behavior
  #     end
  #   end

初始化器逻辑的实现是Initilizable module的一部分,它是included到Railtie类中。特定的初始化类方法基本上将传递的块添加到类初始化器数组source

  def initializer(name, opts = {}, &blk)
    ...
    initializers << Initializer.new(name, nil, opts, &blk)
  end

它没有立即执行。它是通过run调用按特定顺序对初始值设定项执行run_initializers方法运行的,这也是Initializable module的一部分。此方法可用于rails Application,其继承自Engine(包括Initializable模块)。

def run_initializers(group=:default, *args)
  return if instance_variable_defined?(:@ran)
  initializers.tsort_each do |initializer|
    initializer.run(*args) if initializer.belongs_to?(group)
  end
  @ran = true
end

run_initializers方法由应用程序的initialize!调用(稍后见下文)触发。

关于通过Rails应用程序收集所有初始化程序的附注。

同时,initializers这里是Application类中的重载method

def initializers #:nodoc:
  Bootstrap.initializers_for(self) +
  railties_initializers(super) +
  Finisher.initializers_for(self)
end

此方法将加载应用程序的所有初始化程序,以便进一步订购和运行。 在内部,railties_initializers将调用ordered_railties,它将使用引擎类的railties获取者(继承自哪个应用程序)。此getter是following

def railties
  @railties ||= Railties.new
end

Railties(复数)服务类与Railtie不同。它实际上只是通过查看Engine和Railtie类的所有子类来收集所有railties

 def initialize
    @_all ||= ::Rails::Railtie.subclasses.map(&:instance) +
      ::Rails::Engine.subclasses.map(&:instance)
  end

最后,subclasses是一个来自Ruby基类扩展的方法,为方便起见,它使用Rails extend

  def subclasses
    subclasses, chain = [], descendants
    chain.each do |k|
      subclasses << k unless chain.any? { |c| c > k }
    end
    subclasses
  end
end

按应用程序返回运行初始化程序。如上所述,run_initializers由Application类的initialize! call调用:

   def initialize!(group=:default) #:nodoc:
      raise "Application has been already initialized." if @initialized
      run_initializers(group, self)
      @initialized = true
      self
    end

Rails.application.initialize!文件中的environment.rb电话会触发哪个Rails应用程序 - 请参阅generator source

这些初始化程序如何添加到正在运行的队列中?这是通过添加Devise gem(例如,通过Bundle.require)来加载lib/devise.rb gem root文件,并在最底部跟随require

require 'devise/rails'

由于这会加载Devise类,因此通过查看Engine的子类,它将由Railties类发现。

返回以设计devise.url_helpers初始化程序 如果你看include_helpers电话,那就是does

 def self.include_helpers(scope)
    ActiveSupport.on_load(:action_controller) do
      include scope::Helpers if defined?(scope::Helpers)
      include scope::UrlHelpers
    end

    ActiveSupport.on_load(:action_view) do
      include scope::UrlHelpers
    end
  end

ActiveSupport on_load调用是lazy_load组件的Rails功能。 source

  

#lazy_load_hooks允许Rails懒洋洋地加载很多组件   从而#使应用程序启动更快。

在这种情况下,那些包含控制器的命令将在加载控制器时执行,但不会在服务器启动时执行。查看this或有关该概念的任何其他文章。

这是运行懒惰块的地方 - source

module ActionController
  # Action Controllers are the core of a web request in \Rails. They are made up of one or more actions that are executed
  # on request and then either it renders a template or redirects to another action. An action is defined as a public method
  # on the controller, which will automatically be made accessible to the web-server through \Rails Routes.
  #
  # By default, only the ApplicationController in a \Rails application inherits from <tt>ActionController::Base</tt>. All other
  # controllers in turn inherit from ApplicationController. This gives you one class to configure things such as
  # request forgery protection and filtering of sensitive request parameters.
 ...
  class Base < Metal
    ...
    ActiveSupport.run_load_hooks(:action_controller, self)
  end
end

BTW,由Rails生成的ApplicationController继承自ActionController :: Base