为什么1.send(:hour)在Ruby中返回3600?

时间:2017-03-09 06:09:57

标签: ruby

在我的理解中,1是类Fixnum。

puts 1.class.name

send()允许您在类中调用方法。因此1.send()应该调用类Fixnum的方法。

最后,括号中的内容指定要调用的方法。在这种情况下,我将调用Fixnum类的小时方法。

但是没有"小时" Fixnum的方法,至少从我能看到的one tutorial on the subject开始。相反,它似乎采用Fixnum对象并乘以一小时内的秒数来给出[object]中的秒数:小时。并且......我不跟随 - 您如何看待它为何如此有效?

3 个答案:

答案 0 :(得分:5)

Ruby具有非常灵活的运行时环境,其中类和对象可以随时由程序中的任何代码添加或删除方法。

这种改变现有类并添加新功能的能力称为“猴子修补”,但如果更正式地完成它通常被描述为“核心扩展”,即核心Ruby类的扩展。 Rails有 lot ,其中hours就是其中之一。

查看类文档不一定是找出方法来源的最可靠方法。在大多数情况下,最好的方法是简单地询问,因为Ruby确实支持 reflection ,其中代码可以查询有关事物的代码:

1.method(:hours)

返回描述相关方法的Method对象。其中最有用的部分之一是:

1.method(:hours).source_location

告诉你方法的定义。它会引导你到像active_support/core_ext/numeric/time.rb这样的东西,这意味着它是一个ActiveSupport的东西,它就是这样。如果您对细节感到好奇,这些扩展名为documented on the Rails site

请记住一个简单的值,例如1所有其祖先类中获取方法, plus 应用于它的任何模块扩展(混合)以及以更特别的方式添加的任何其他内容。

如果你问哪些方法来自:

1.class.ancestors

这是现代Rails中非常长的列表。

答案 1 :(得分:4)

这是Numeric类的rails扩展名(读取:monkeypatch)。

答案 2 :(得分:1)

Rails有一个数字猴子补丁,它可以将像1.hour,1.minute甚至1.day这样的单位转换成一个友好的格式,以便使用Ruby类的Time。

所以没有这个数字助手,就像这样:

snapshot_of_time = Time.now

snapshot_of_time + 1
# => Just returns the time when the variable was defined, plus 1 second. 
# To move it forward an hour, I'd have to remember an hour was 3600 seconds.

然而,添加了这个Numeric类方法:

snapshot_of_time = Time.now

snapshot_of_time + 1.hour
# => Predictably provides you with a time that's 1 hour in the future
# of your snapshot!

简单地说,你要么在ruby中运行某种方法扩展,要么在rails控制台中运行。默认情况下,从2.4.0版开始,此助手方法不包含在Ruby中