複数の単語からなる言葉を識別子に使うとき,スペースを含めることができないので,何らかの方法で単語の区切りを表さなければなりません。
たとえば以下のようなさまざまな表記方法が使われています。
- UpperCamelCase
- lowerCamelCase
- snake_case
ActiveSupport にはこれらの間の変換をする便利なメソッド群が用意されています。
CamelCase を snake_case に変換するには String#underscore
が使えます。
snake_case を UpperCamelCase に変換するには String#camelize
が使えます1。
以下のように:
require "active_support/inflector"
p "BookTitle".underscore # => "book_title"
p "book_title".camelize # => "BookTitle"
これを見ると,underscore
と camelize
は互いの逆変換になっており,
require "active_support/inflector"
p "BookTitle".underscore.camelize # => "BookTitle"
p "book_title".camelize.underscore # => "book_title"
のように両者を重ねると(常に)元に戻るように思えます。
しかし,そうならない場合もあります。それは
require "active_support/inflector"
p "OfficialURL".underscore # => "official_url"
p "CSVFile".underscore # => "csv_file"
の URL
や CSV
のように大文字だけで構成される単語を含むケースです。
underscore
メソッドは,人間が期待するとおり,CSVFile
を CSV
と File
に分割して snake_case 化してくれました。
しかし,これにより,変換後の url
や csv
がもともと大文字だけで綴られていたという情報が失われてしまうので,これらを camelize
しても元には戻らないのです。
require "active_support/inflector"
p "OfficialURL".underscore.camelize # => "OfficialUrl"
p "CSVFile".underscore.camelize # => "CsvFile"
便利なメソッドも仕様をよく理解して使わないと落とし穴に落ちる可能性がある,という例でした。
(つか,ハマったんだよ2,実際に!)