我遇到了用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
来实现的,但是如果它只是一个只在一个类加载时才会执行一次的方法调用,它是如何在渲染操作之前调用的?
答案 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_action
或after_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
例如:
上面的 validates :name, presence: true
来自班级ActiveRecord::Validations
,文件是
与assosciations
,timezones
,attributes
,enums
等许多来自同一模块的方法相同。
这同样适用于控制器,
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
强>
所以我们在模型中使用的所有方法都来自这个类。
------- 注意:强> --------
从上到下逐行执行。
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