如何使用 String#between?使用 DateTime 对象在 Rails 中工作?

How does using String#between? with DateTime objects work in Rails?

使用 Ruby 2.3.2, Rails 5.0.0.1

在Ruby控制台中

2.3.2 :001 > date_time_str = "2015-01-08 08:17:15 UTC"
 => "2015-01-08 08:17:15 UTC" 
2.3.2 :002 > date_time_range_start = "2015-01-08 08:16:15 UTC"
 => "2015-01-08 08:16:15 UTC" 
2.3.2 :003 > date_time_range_end = "2015-01-08 08:20:15 UTC"
 => "2015-01-08 08:20:15 UTC" 

2.3.2 :008 > require 'date'
 => true 

2.3.2 :009 > date_time_str.between?(DateTime.parse(date_time_range_start), DateTime.parse(date_time_range_end))

ArgumentError: comparison of String with DateTime failed
    from (irb):9:in `between?'
    from (irb):9
    from /home/jignesh/.rvm/rubies/ruby-2.3.2/bin/irb:11:in `<main>'

我在尝试将 String 实例与 DateTime 实例进行比较时预期会出现上述行为。但是,当我在 rails 控制台中尝试相同操作时,它 returns 预期结果如下所示。

在Rails控制台中

Loading development environment (Rails 5.0.0.1)
2.3.2 :001 > date_time_str = "2015-01-08 08:17:15 UTC"
 => "2015-01-08 08:17:15 UTC" 
2.3.2 :002 > date_time_range_start = "2015-01-08 08:16:15 UTC"
 => "2015-01-08 08:16:15 UTC" 
2.3.2 :003 > date_time_range_end = "2015-01-08 08:20:15 UTC"
 => "2015-01-08 08:20:15 UTC" 
2.3.2 :004 > date_time_str.between?(DateTime.parse(date_time_range_start), DateTime.parse(date_time_range_end))
 => true 
2.3.2 :005 > date_time_str_2 = "2015-01-08 08:21:15 UTC"
 => "2015-01-08 08:21:15 UTC" 
2.3.2 :006 > date_time_str_2.between?(DateTime.parse(date_time_range_end), DateTime.parse(r_e))
 => false 

任何人都可以帮助我了解 Rails 在内部做了什么来完成上述工作吗?

String#<=> in ruby 试图将自己与另一个对象进行比较。如果另一个对象无法比较(不是字符串),则字符串的具体实现 (c-source here) 将另一个对象与接收字符串进行比较。

换句话说,"str" <=> obj相当于

if obj.is_a?(String)
  # compare bytes
elsif obj.respond_to?(:to_str)
  obj = obj.to_str
  # compare bytes
else
  # a few safety checks
  -1 * (obj <=> "str")
end

现在我们 "str" <=> obj 沸腾到 obj <=> "str"。到目前为止,这只是 Ruby,没有 Rails。由于 Datetime#<=> 没有对字符串进行特殊处理,因此它 returns 为零,故事到此结束。

在Rails中,他们重新定义了Datetime#<=> and defined String#to_datetime