所以,我在自定义注册页面中自定义设计,这需要我在创建帐户以及其他一些操作后 sign_in 用户。创建资源后我做了
sign_in resource if resource.active_for_authentication?
并在用户中签名。我的控制器继承了 ApplicationController的 而我还没有包含任何这样的模块
include Devise::Controllers::SignInOut
rails如何知道
sign_in
方法
答案 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