ActiveRecordの複数形処理

ActiveRecordは要素クラスの名前を複数形に変えてテーブル名としてくれるのですが、なんだか不思議な感じがします。

# Users テーブルへアクセス
class User < ActiveRecord::Base
end

# People テーブルへアクセス
class Person < ActiveRecord::Base
end

Usersはわかるのですが、なぜPersonsにならないのだろう?


正体はActiveSupportに含まれるInflector(active_support/inflector.rb)にありました。ここには英文用の各種変換が含まれ、Inflector.pluralize(word)で複数形に変換できます。
そして重要なのがactive_support/inflections.rbです。Inflector定義の最後で読み込まれているのですが、ここに実際の変換ルールが定義されています。

  inflect.irregular('person', 'people')
  inflect.irregular('man', 'men')
  inflect.irregular('child', 'children')
  inflect.irregular('sex', 'sexes')
  inflect.irregular('move', 'moves')

  inflect.uncountable(%w(equipment information rice money species series fish sheep))

なるほど、例外処理されています。納得。

うまく複数形に変換できなかった単語があれば、require後に次のようなルール定義をすればよいようです。

Inflector.inflections do |inflect|
  inflect.plural /^(ox)$/i, '\1\2en'    # 複数形化のルール
                                        # gsub!で実装されているので、gsub同様の引数になります。
  inflect.singular /^(ox)en/i, '\1'     # 単数形化のルール

  inflect.irregular 'octopus', 'octopi' # 1:1で結びつく場合

  inflect.uncountable "equipment"       # 不可算名詞
end

そもそも複数形変換を利用しないのも手ですね。

# 自動変換を無効にする
ActiveRecord::Base.pluralize_table_names = false
# テーブル名を明示する
class User < ActiveRecord::Base
  set_table_name :User
end