2013-07-29 1 views
2

Поскольку я занимаюсь довольно много с продолжительностью в моем приложении Rails, я также хотел бы использовать их в качестве хеш-ключей в некоторых местах. Однако, похоже, он работает не так, как ожидалось для меня.Использование продолжительности в качестве хеш-ключей в 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), должны продолжать работать.

FYI: Мой рубин версия - 1.8.7, Rails версии - 2.3.18

+2

Пройдите все, используя '' to_i' – oldergod

+1

1 .month.class' лжет вам, это фактически 'ActiveSupport :: Duration', хотя он утверждает, что является' Fixnum'. Похоже, у лжи есть дыры. –

+0

@oldergod Я считал, что использование to_i на самом деле не всегда одинаково. Например, Time.mktime (2013, 3, 6) - 1.month возвращает 6 февраля в качестве ответа, но Time.mktime (2013, 3, 6) - 1.month.to_i дает 4 февраля вместо этого – dominos

ответ

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]