在Rails中使用duration作为哈希键

时间:2013-07-29 01:56:24

标签: ruby-on-rails ruby ruby-on-rails-2 duration ruby-1.8.7

由于我在Rails应用程序中处理了很多持续时间,我还想在某些地方使用它们作为哈希键。但是,它似乎对我没有预期效果。

创建初始哈希工作正常。例如,以下内容将起作用:

>> hash = {1.week => 'abc', 1.month => 'def'}

但是,无法从散列中检索值:

>> hash[1.month]
=> nil

进一步调查显示了我的原因:

>> 1.week.eql? 1.week
=> false

这是非常意外的

此外,似乎这些对象的行为与FixNum类的普通对象不同。对于普通的FixNum对象,object_id的值似乎总是相同的,例如:

>> 15.object_id
=> 31
>> 15.object_id
=> 31

对于持续时间,这是不同的,虽然它们来自同一个班级

>> 1.month.class
=> Fixnum
>> 1.month.object_id
=> 70305513092140
>> 1.month.object_id
=> 70305513086860

因此,似乎对象总是不同的,这就是为什么哈希不起作用的原因。唯一的解决方案是使用完全相同的对象访问:

>> a = 1.month
=> 1 month
>> hash = {a => 'b'}
=> {1 month=>"b"}
>> hash[a]
=> "b"

显然,如果你有很多具有动态创建持续时间的对象,这并不总是可行的。

按持续时间分组也不起作用:

>> limits.group_by(&:duration)
=> #<OrderedHash {1 month=>[#<Limit:0x7fe28e441380>], 1 month=>[#<Limit:0x7fe28e4290c8>]}>

所以,我想知道是否有可能以某种方式将持续时间作为哈希键工作?到目前为止,我还没有找到一个好的解决方案,我不确定是否有一个。重要的是,像(Time.now - duration)这样的函数应该继续工作。

仅供参考:我的Ruby版本 - 1.8.7,Rails版本 - 2.3.18

1 个答案:

答案 0 :(得分:0)

哇,这是一个奇怪的发现。这确实有效,我还没能打破它,但它看起来有点脆弱:

hash = {1.year.inspect => "val1", 2.month.inspect => "val2", (1.year-4.days).inspect => "val3"}
 => {"1 year"=>"val1", "2 months"=>"val2", "1 year and -4 days"=>"val3"}

hash[2.months.inspect]
 => "val2" 

hash[(1.year-4.days).inspect]
 => "val3" 

并获得持续时间

hash.keys.collect{|k| eval(k.gsub(" and ","+").split(" ").join("."))}
 => [1 year, 2 months, 1 year and -4 days]