こんにちは、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もできます。