Rails:ControllerClass的第一行中提到的方法何时执行?

时间:2017-03-01 12:49:10

标签: ruby-on-rails

我遇到了用ControllerClass Scope编写的方法调用,类似于(在here中):

class MoviesController < ApplicationController
  # Is this a before_action or after_action or just an alias or something else?
  pagination_header :index                    # <----- when will this be called

  def index
  # some logic here
  end

end

什么时候执行它们,以及它们究竟是如何内部绑定(它们是否附加到某处的回调)

编辑:我知道pagination_header是一个应该在index内的render方法之前执行的方法。如何构建这样的方法呢?

这可能是通过在after_action方法中包含pagination_header来实现的,但是如果它只是一个只在一个类加载时才会执行一次的方法调用,它是如何在渲染操作之前调用的?

3 个答案:

答案 0 :(得分:2)

您正在查看的方法只是一种类方法。没有控制器范围,但我理解你的直觉告诉你的。

在Ruby中,有许多&#34;范围门&#34;,如class关键字,def关键字,module关键字。每次通过范围门时,隐式的消息接收者都会发生变化。隐式接收器是关键字self引用的对象。请记住,Ruby中的所有方法都是消息,传递给显式或隐式接收器。可以通过点符号(receiver.method)轻松识别显式接收器。

每当你在Ruby中遇到一行代码时,你应该问自己:&#34;谁现在是自我?&#34;。如果你回答这个问题,你就会知道在哪里寻找方法定义。

在您的示例中,class关键字(class MoviesController)启动了一个范围。这意味着隐式接收器(或self)就是类本身。试试这个

class MyClass
  self #=> MyClass
end

我能找到的一本优秀的初学者教程是this post。如果你想深入研究Ruby对象模型,我推荐P. Perotta的Metaprogramming Ruby。

答案 1 :(得分:2)

rails中的所有内容都是与这些对象关联的一个或多个对象。

让我们举一个例子,就像您询问before_actionafter_action

一样

让我们首先考虑** model :**

class Subscription < ActiveRecord::Base
  before_create :record_signup

  private
    def record_signup
      self.signed_up_on = Date.today
    end
end

rails中存在的许多内置函数都来自 ActiveRecord::Base ,它们属于一类 的 ActiveRecord module

所以我们在模型中使用的所有方法都来自这个类。

例如:

上面的

before_create来自班级ActiveRecord::Callbacks,文件是。{ activerecord/lib/active_record/callbacks.rb

Active record Callbascks

例如:

上面的

validates :name, presence: true来自班级ActiveRecord::Validations,文件是

Active record Validations

assosciationstimezonesattributesenums等许多来自同一模块的方法相同。

Active record class main URL

这同样适用于控制器,

class PostsController < ApplicationController
  def index
    @posts = Post.all
  end

  def create
    @post = Post.create params[:post]
    redirect_to posts_path
  end
end

应用程序控制器继承自ActionController::Base

class ApplicationController < ActionController::Base
  before_action :require_login

  private

  def require_login
    unless logged_in?
      flash[:error] = "You must be logged in to access this section"
      redirect_to new_login_url # halts request cycle
    end
  end
end

rails中存在的许多内置函数都来自 ActionController::Base ,它们属于一类 的 ActionController module

所以我们在模型中使用的所有方法都来自这个类。

Action controller

------- 注意: --------

从上到下逐行执行。

before_action正在调用方法,因此直接调用它。

def index
end

以上是定义,但我们没有调用它,所以在我们通过路由调用它之前不会执行。

答案 2 :(得分:1)

Rails使用ActiveDispatch :: Callbacks中间件来确保运行回调。这是一个与Rack兼容的中间件,这意味着它可以添加到中间件链中的任何位置。当请求命中Rails时,它会决定哪个控制器操作将为请求提供服务,它基本上会在回调之前和之后包装控制器操作。

只要中间件实现了Rack的界面,您就可以按照自己喜欢的顺序调用它们。所以,我猜before_action回调是运行调用Rack接口的“call”方法,然后执行相同的操作,最后执行after_action回调。响应会在此过程中得到增强(或不增加)。可能会添加一些标题,响应正文中会发生某些变化,或者根本没有变化,例如日志记录。

如果你想了解更多关于回调如何成功的信息,你应该看看ActiveSupport::Callbacks,虽然你很容易自己动手。

class ARailsController
  def self.after_action(callback)
    @@after_callbacks ||= []
    @@after_callbacks << callback
  end

  def execute_callbacks
    @@after_callbacks.each { |callback| callback.call() }
  end
end

class MyController < ARailsController
  after_action Proc.new { puts "This will be executed afterwards" }
  after_action Proc.new { puts "Save this for later" }
end

controller = MyController.new
controller.execute_callbacks