LoginSignup
1
0

More than 3 years have passed since last update.

ActiveSupport の underscore は camelize の逆変換じゃない

Posted at

複数の単語からなる言葉を識別子に使うとき,スペースを含めることができないので,何らかの方法で単語の区切りを表さなければなりません。
たとえば以下のようなさまざまな表記方法が使われています。

  • 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"

これを見ると,underscorecamelize は互いの逆変換になっており,

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"

URLCSV のように大文字だけで構成される単語を含むケースです。
underscore メソッドは,人間が期待するとおり,CSVFileCSVFile に分割して snake_case 化してくれました。
しかし,これにより,変換後の urlcsv がもともと大文字だけで綴られていたという情報が失われてしまうので,これらを camelize しても元には戻らないのです。

require "active_support/inflector"

p "OfficialURL".underscore.camelize # => "OfficialUrl"
p "CSVFile".underscore.camelize     # => "CsvFile"

便利なメソッドも仕様をよく理解して使わないと落とし穴に落ちる可能性がある,という例でした。
(つか,ハマったんだよ2,実際に!)


  1. lowerCamelCase に変換するには camelize(:lower) のようにします。 

  2. 当初 gsub(/.(?=[A-Z])/){ $& + "_" }.downcase みたいなコードで snake_case 化してて,あとで ActiveSupport を使った処理を混ぜたときに不具合が生じたという。 

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0