问题描述
我是Ruby和Rails的新手,并且试图完全理解我正在阅读的内容。
我正在查看一些Rails源代码,在这种情况下为action_controller/Metal/instrumentation.rb
。
def render(*args)
render_output = nil
self.view_runtime = cleanup_view_runtime do
Benchmark.ms { render_output = super }
end
render_output
end
我知道*args
正在使用splat运算符将参数一起收集到一个数组中。但是在那之后,这对我来说就不再有意义了。
我无法理解为什么将render_output
设置为nil,然后再将其重新分配为等于super
,然后再不加任何参数地对其进行调用。我收集到一些速度测试已经完成,但是来自其他语言,我希望它更像是Benchmark.ms(render_output)
或Benchmark.start
,然后是render_output
,然后是{{1} }。我很难按照这里的工作方式进行操作。
但更重要的是,我并不真正理解为什么不再使用Benchmark.end
。为什么要麻烦定义不使用的参数?我的意思是,显然它正在被使用-我只是不知道如何使用。这里有一些我尚未了解的隐藏机制。
解决方法
在这种情况下,重要的是要注意super
的工作方式,因为在某些情况下它会隐式传递参数,而您可能不希望这样做。
当您拥有类似方法
def method(argument)
super
end
然后,super将使用与当前方法完全相同的参数隐式调用method
的重写实现。这意味着在此示例中,super实际上将调用super(argument)
。
当然,您仍然可以定义一个方法调用,以将其他参数显式发送到原始实现,如本例所示:
def method(argument)
super(argument + 1)
end
另一个重要的极端情况是,当您希望不带任何参数的情况下显式调用super时,尽管当前方法是使用参数进行调用的,那么您需要像这样非常显式
def method(argument)
super() # note the empty parentheses
end
,
让我尝试向您描述我认为这段代码的作用。
*args*
使用splat运算符将参数一起收集到一个数组中
那是完全正确的,但是他们没有使用它,如果您要转到master分支,他们只是将其更改为*
。问为什么定义和不使用它,我认为这是关于不良设计的问题。他们应该将其命名为_args
,或者至少现在像现在只是单个splat *
。
render_output
由于范围而设置为nil,必须在block,lambda,proc中显式定义以便在其中存储值,否则它的可见性将仅锁定于这些lambda,proc,block执行。请参阅this article
Benchmark.start
。块是伟大的红宝石建筑。您完全正确地完成了速度测试,我们可以看到它只是benchmark
库的装饰器。
source。
您想知道为什么我们不能仅将其传递为Benchmark.ms(render_output)
,这是因为基准ms
函数将得到什么?将得到结果,如<div> my html </div
。以及如何测量此字符串结果-否。这就是为什么我们在此块中调用超级权限,我们想访问父类函数并将其包装在块中,所以我们不调用它,我们只是构造它,而将在benchmark
lib内部调用它并进行测量像
class Benchmark
...
def realtime # :yield:
r0 = Process.clock_gettime(Process::CLOCK_MONOTONIC)
yield
Process.clock_gettime(Process::CLOCK_MONOTONIC) - r0
end
...
end
所以这里我们可以计算函数执行的实时性,这是original library
中的代码