こんにちは、hachi8833です。
小ネタですが、RailsのActiveSupport::Duration
で数値にどうやってパッチを当てているのかが気になったので見てみました。
ActiveSupport::Duration
での挙動
1.month
や2.days
などでDuration
になります。
require 'active_support/all'
a = 1.month
#=> 1 month
a.class
#=> ActiveSupport::Duration
ついでに1
のクラス階層も見てみます。
1.class
#=> Integer
1.class.ancestors
#=> [ActiveSupport::ToJsonWithActiveSupportEncoder,
ActiveSupport::NumericWithFormat,
Integer,
JSON::Ext::Generator::GeneratorMethods::Integer,
Numeric,
Comparable,
ActiveSupport::ToJsonWithActiveSupportEncoder,
Object,
JSON::Ext::Generator::GeneratorMethods::Object,
ActiveSupport::Tryable,
PP::ObjectMixin,
Kernel,
BasicObject]
どうやらNumericWithFormat
でやっているようです。
numeric/conversions.rbだった
あっさり見つかりました。
module ActiveSupport::NumericWithFormat
...
end
# Ruby 2.4+ unifies Fixnum & Bignum into Integer.
if 0.class == Integer
Integer.prepend ActiveSupport::NumericWithFormat
else
Fixnum.prepend ActiveSupport::NumericWithFormat
Bignum.prepend ActiveSupport::NumericWithFormat
end
Float.prepend ActiveSupport::NumericWithFormat
BigDecimal.prepend ActiveSupport::NumericWithFormat
Module#prepend
を使ってInteger
にパッチを当てていました。
Ruby 2.4以前の場合はFixnum
とBignum
にパッチを当てています。
Float
やBigDecimal
にも当たっているので、1.1.hours
もできます。