[Rails5] Active Support Core ExtensionsのIntegerクラス: ordinalize、multiple_of?など

こんにちは、hachi8833です。ActiveSupport探訪シリーズ、Durationが当初の予想より長くて深く、しかもCore Extensionsの外に出てしまっていました。
そこで久しぶりに、Core Extensionsの中から小粒でかわいらしいIntegerクラスにお邪魔いたします。? ?

条件

active_support/core_ext/integer/

active_support/core_ext/integerの以下のファイルが対象です。

例によってコメントを取り除いてあります。

inflector.rb

require 'active_support/inflector'

class Integer
  def ordinalize
    ActiveSupport::Inflector.ordinalize(self)
  end

  def ordinal
    ActiveSupport::Inflector.ordinal(self)
  end
end

開けてみれば、ActiveSupport::Inflector丸投げ委譲しています。以下の表はIntegerクラスのメソッドで表します。

Integer#ordinalize
数値に序数の接尾語(suffix)を追加する
ordinalize(1) # => "1st"
ordinalize(2) # => "2nd"
ordinalize(1002) # => "1002nd"
ordinalize(1003) # => "1003rd"
ordinalize(-11) # => "-11th"
ordinalize(-1021) # => "-1021st"
Integerr#ordinal
数値に対応する序数の接尾語(suffix)を返す
ordinal(1) # => "st"
ordinal(2) # => "nd"
ordinal(1002) # => "nd"
ordinal(1003) # => "rd"
ordinal(-11) # => "th"
ordinal(-1021) # => "st"

いかにも英語圏で欲しいヘルパーメソッドという感じですね。活用(Inflection)系メソッドのうち、数値をIntegerクラスで扱うのは納得です。

0thに一瞬ぎょっとしてしまいましたが、一応Wikipediaにも記載があります。考えてみれば数学や工学などの専門用語としての「ゼロ次数」は普通にありますね。熱力学第零法則なんてものもあります。

なお、専門用語でないzerothにはやや異なるニュアンスがこもるようです。

参考: 序数の国際化について

Railsで英語以外の言語の序数を活用できるかどうかネットで探してみましたが、それらしいものは見当たりませんでした。

単語の単数形複数形をinitializers/inflections.rbに記述したり、locales/ロケール名.ymlで月名や日時フォーマットを記述する、といったことならある程度まで可能ですが、アルゴリズムによる国際化の困難な言語要素はいろいろとあり、序数もそのひとつです。

たとえばスペイン語では序数にジェンダー(男性形・女性形)があるために、序数を機械的に活用できません。数値が使われるコンテキストを人間や人工知能が読み取らないと序数のジェンダーを決定できないので実に厄介です。

Railsに限らず国際化にはさまざまな困難がともないます。日本語は数値に「番目」さえつければ序数になるのでありがたいですね。

time.rb

require 'active_support/duration'
require 'active_support/core_ext/numeric/time'

class Integer
  def months
    ActiveSupport::Duration.months(self)
  end
  alias :month :months

  def years
    ActiveSupport::Duration.years(self)
  end
  alias :year :years
end

こちらは以前のTechRacho記事でおなじみのActiveSupport::Durationにまるっと委譲しています。

multiple.rb

class Integer
  def multiple_of?(number)
    number != 0 ? self % number == 0 : zero?
  end
end

三項演算子を使ったワンライナーです。引数がゼロの場合はレシーバを#zero?でチェックすることで、ゼロ除算を回避しています。
個人的には、これ以上複雑になったら三項演算子はやめたい気がします。

Integer#multiple_of?
レシーバのIntegerが引数で割り切れるかどうかを論理値で返す
0.multiple_of?(0) # => true
6.multiple_of?(5) # => false
10.multiple_of?(2) # => true

関連記事

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

この記事の著者

hachi8833

Twitter: @hachi8833 コボラー、ITコンサル、ローカライズ業界を経てなぜかWeb開発者志願。 これまでにRuby on Rails チュートリアルの大半、Railsガイドのほぼすべてを翻訳。 かと思うと、正規表現の粋を尽くした日本語エラーチェックサービス enno.jpを運営。 仕事に関係ないすっとこブログ「あけてくれ」は2000年頃から多少の中断をはさんで継続、現在はnote.muに移転。

hachi8833の書いた記事

週刊Railsウォッチ

インフラ

Rubyスタイルガイドを読む

BigBinary記事より

ActiveSupport探訪シリーズ