ActiveSupportのマイナーだけど 便利なメソッド

公開:2020/10/22
更新:2020/10/22
2 min読了の目安(約2400字TECH技術記事

先日勤務先の株式会社 iCARE の DevMeetup #14 にて、
「ActiveSupportのマイナーだけど 便利なメソッド」というタイトルでLTしました。

ありがたいことにTwitterで実況していただき、

のようなリアクションをしていただきました。ありがとうございます🙏

このエントリではスライドでは紹介できなかった実際のコードをいくつか紹介したいと思います。

in?

  def in?(another_object)
    another_object.include?(self)
  rescue NoMethodError
    raise ArgumentError.new("The parameter passed to #in? must respond to #include?")
  end

https://github.com/rails/rails/blob/b738f1930f3c82f51741ef7241c1fee691d7deb2/activesupport/lib/active_support/core_ext/object/inclusion.rb#L12

レシーバと引数を逆にして include? を使っているだけ。とてもシンプルですね。
こういうちょっとしたコードでもより楽しくかけるようになるということがわかります。

ordinalize

1だったら1st、3だったら3rdなどの文字(序数文字列)を付与できるメソッドです。

> 1.ordinalize
=> "1st"
> 3.ordinalize
=> "3rd"
> 13.ordinalize
=> "13th"

この実装はどうなっているかというと

def ordinal(number)
  I18n.translate("number.nth.ordinals", number: number)
end

def ordinalize(number)
  I18n.translate("number.nth.ordinalized", number: number)
end

https://github.com/rails/rails/blob/b738f1930f3c82f51741ef7241c1fee691d7deb2/activesupport/lib/active_support/inflector/methods.rb#L344
https://github.com/rails/rails/blob/b738f1930f3c82f51741ef7241c1fee691d7deb2/activesupport/lib/active_support/inflector/methods.rb#L357

I18n.translate を実行しています。意外。
それはどうやっているかというと

# frozen_string_literal: true

{
  en: {
    number: {
      nth: {
        ordinals: lambda do |_key, options|
          number = options[:number]
          case number
          when 1; "st"
          when 2; "nd"
          when 3; "rd"
          when 4, 5, 6, 7, 8, 9, 10, 11, 12, 13; "th"
          else
            num_modulo = number.to_i.abs % 100
            num_modulo %= 10 if num_modulo > 13
            case num_modulo
            when 1; "st"
            when 2; "nd"
            when 3; "rd"
            else    "th"
            end
          end
        end,

        ordinalized: lambda do |_key, options|
          number = options[:number]
          "#{number}#{ActiveSupport::Inflector.ordinal(number)}"
        end
      }
    }
  }
}

https://github.com/rails/rails/blob/master/activesupport/lib/active_support/locale/en.rb

なんとロケールで lambda を使っています。こういうことができるとは知りませんでした。

このようにソースコードを読むことで新たな気付きも得られます。

ぜひ ActiveSupport のソースコードを覗いてみてください!