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の概要をつかむ

Ruby on RailsによるWEBシステム開発、Android/iPhoneアプリ開発、電子書籍配信のことならお任せください この記事を書いた人と働こう! Ruby on Rails の開発なら実績豊富なBPS

この記事の著者

hachi8833

Twitter: @hachi8833、GitHub: @hachi8833

コボラー、ITコンサル、ローカライズ業界、Rails開発を経てTechRachoの編集・記事作成を担当。
これまでにRuby on Rails チュートリアル第2版の半分ほど、Railsガイドの初期翻訳ではほぼすべてを翻訳。その後も折に触れてそれぞれ一部を翻訳。
かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。
実は最近Go言語が好き。
仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

BPSアドベントカレンダー

週刊Railsウォッチ

インフラ

BigBinary記事より

ActiveSupport探訪シリーズ