Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ruby-on-rails/54.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails 为什么ActiveRecord在初始化后和查找回调后文档提到块级别变量?_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails 为什么ActiveRecord在初始化后和查找回调后文档提到块级别变量?

Ruby on rails 为什么ActiveRecord在初始化后和查找回调后文档提到块级别变量?,ruby-on-rails,ruby,Ruby On Rails,Ruby,我在我的用户模型中定义了一个后初始化和一个后查找回调: 请假设我的用户也有一个名为电子邮件的属性 class User < ApplicationRecord after_initialize do |user| puts "You have initialized an object! Email: #{email}" end after_find do |user| puts "You have found an object! Email: #{emai

我在我的
用户
模型中定义了一个
后初始化
和一个
后查找
回调:

请假设我的
用户
也有一个名为
电子邮件
的属性

class User < ApplicationRecord
  after_initialize do |user|
    puts "You have initialized an object! Email: #{email}"
  end

  after_find do |user|
    puts "You have found an object! Email: #{email}"
  end
end

我的问题是,为什么回调的文档中提到存在块局部变量
user
?正如我在上面所经历的,虽然没有使用
用户
局部变量,但我仍然可以访问实例化的
用户
实例和/或查找的
实例。

这些没有
记录项
的回调(在您的例子中是
用户
实例)的意义要小得多(如果有的话)-除了测试目的(如您刚刚通过调用
puts
确认已找到记录时的情况)之外,通常情况下,在实际用例中,您可能需要在应用程序中使用该对象之前读取/修改该对象

因此,当您定义回调时,
ActiveRecord
将它们存储在内部
ActiveRecord
假设您将需要此实例,并且在调用块时
do。。。结束
,它使用找到的记录(
用户
)来完成。 理论上(我没有在
ActiveRecord
codebase中检查实际实现)可能看起来像:

 record = find_record
 if after_find_callback
   after_find_callback.call(record)
 end

它不是必需的,是可选的。您可以执行以下任一操作并获得相同的结果。假设
User
具有
:name
属性:

after_initialize do |user|
  puts user.name
end

after_initialize do
  puts name
end
我猜文档使用了
| user |
变量,因为当有显式接收器时,它更清晰,特别是对于新的Ruby/Rails开发人员


换句话说,第一个选项不会改变执行的上下文(或“词法范围”)和
self
的定义,而第二个选项会改变,这一点一开始可能会让人困惑。

我认为它只是用于文档,这样人们就可以知道块内发生的事情是针对
用户的,是的,它实际上没有被使用

您可以在不使用
用户
变量的情况下定义:

after_initialize do
  puts "You have initialized an object! Email: #{email}"
end
从:

以及:

所以,块的变量是什么并不重要

顺便说一句,您也可以像其他回调一样使用方法而不是块来使用
after\u initialize
after\u save,after\u create
):


检查活动记录回调和
ActiveRecord::Callbacks
。已经检查了,请不要忽略sandno。这不是必需的。我已经修改了问题的内容,以证明它不是必需的。那么为什么不直接回答问题呢?你随意编辑了那个问题,因为我没有时间搜索/调查文档中有这个
user
block-level变量的原因。同时,我看到@thanh发布了一个答案,这可能是一个好答案。它读起来和最初的问题完全不同,以至于他们需要不同的答案@p.matsinopoulost这是不正确的。我已经修改了问题内容,以表明
user
block-level变量是无用的。您仍然可以访问正在初始化和/或找到的实例。这不是正确的源代码。您正在查看Railtie初始值设定项的源代码。@m.simonborg您是否尝试过在上面的代码初始化后调试
,以查看它的去向?在初始化
后尝试
而不使用
user
变量?我已经研究了ActiveRecord回调的实现,您引用的代码不是它。我从不直接将块传递给回调方法,但更喜欢传递符号。我不在乎是否将回调与块或方法一起使用!我的问题是“你有没有在用块初始化后尝试
,以查看实际运行的代码以及它从哪里开始”,而不是仅仅查看实现过程
?OP询问的是块,而不是方法引用(符号)。是的,我将它与块一起使用,以查看运行的是什么。如果您希望在实例的上下文中执行块(即更改
self
的值),但也可以选择显式接收器(如当前示例中,
|user |
是可选的),则可以使用
base.instance_eval(&block)
,而不是
block.call(base)
<代码>块。调用(base)
需要块中的显式变量。除此之外,ActiveRecord回调肯定不会在
Railtie::Configuration
中实现。另外,初始化后的ActiveRecord
占用的参数比一个块多。
after_initialize do
  puts "You have initialized an object! Email: #{email}"
end
def after_initialize(&block)
  ActiveSupport.on_load(:after_initialize, yield: true, &block)
end
# Declares a block that will be executed when a Rails component is fully
# loaded.
def on_load(name, options = {}, &block)
  @loaded[name].each do |base|
    execute_hook(base, options, block)
  end

  @load_hooks[name] << [block, options]
end

def execute_hook(base, options, block)
  if options[:yield]
    block.call(base)
  else
    base.instance_eval(&block)
  end
end
if options[:yield]
  block.call(base)
...
after_initialize :after_initialize_method
def after_initialize_method
  puts "You have initialized an object! Email: #{email}"
end