Tech Racho エンジニアの「?」を「!」に。
  • 開発

Rails5: ActiveSupport::Durationでの数値へのパッチ

こんにちは、hachi8833です。

小ネタですが、RailsのActiveSupport::Durationで数値にどうやってパッチを当てているのかが気になったので見てみました。

ActiveSupport::Durationでの挙動

1.month2.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以前の場合はFixnumBignumにパッチを当てています。

FloatBigDecimalにも当たっているので、1.1.hoursもできます。

関連記事

[Rails5] Active Supportの概要をつかむ


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。