Почему я получаю это несоответствие при выполнении метапрограммирования с Ruby on Rails ActiveSupport Time Extensions?

Я играл с расширениями ActiveSupport Time Core (rails 4.1.2). И вот проблема, с которой я столкнулся.

Почему я получаю это несоответствие?

2.0.0-p451 :011 >   Time.zone.now
=> Wed, 23 Jul 2014 16:38:21 EDT -04:00 

2.0.0-p451 :012 > 4.months.ago
=> Sun, 23 Mar 2014 16:38:25 EDT -04:00 

2.0.0-p451 :013 > 4.send(:months).send(:ago)
DEPRECATION WARNING: Calling #ago or #until on a number (e.g. 5.ago) is deprecated and  
will be removed in the future, use 5.seconds.ago instead. (called from irb_binding at 
(irb):13)
=> Tue, 25 Mar 2014 16:38:35 EDT -04:00 

Я вижу проблему в последнем утверждении: через 2 дня к тому, что возвращает 4.months.ago. Кроме того, я получаю предупреждение, тогда как при вызове 4.months.ago я его не получаю.

Кто-нибудь знает, почему?


person p.matsinopoulos    schedule 23.07.2014    source источник


Ответы (1)


Объект, возвращаемый 4.months, является ActiveSupport::Duration, который наследуется от ActiveSupport::ProxyObject BasicObject. BasicObject ведет себя не так, как другие объекты, и в данном конкретном случае важно, что BasicObject не имеет метода send:

[7] pry(main)> BasicObject.new.send
NoMethodError: undefined method `send' for #<BasicObject:0x007f9e23997910>

В ActiveSupport::Duration есть реализация для method_missing< /a>, который передает неизвестные методы базовому числовому объекту.

Таким образом, когда вы вызываете 4.send(:months).send(:ago), вы отправляете вызов метода ago базовому объекту Fixnum, а не объекту ActiveSupport::Duration.

Это нарушает расчет months, потому что 4.months становится 120 днями при преобразовании в число:

[9] pry(main)> 4.months.to_i
=> 10368000
[10] pry(main)> 120.days.to_i
=> 10368000

Редактировать. Вы можете обойти это с помощью метода __send__, но на самом деле это не самый предпочтительный способ:

[15] pry(main)> 4.months.__send__(:ago)
=> Sun, 23 Mar 2014 21:14:20 UTC +00:00
[16] pry(main)> 4.months.ago
=> Sun, 23 Mar 2014 21:14:27 UTC +00:00
person Shaun    schedule 23.07.2014