Ruby での文字列のキャメルケース変換についてのメモです。
ActiveSupport の camelize
最近(?)では、Rails の ActiveSupport の String#camelize でそれができるようです。
require 'active_support/core_ext/string/inflections'
p "foo/bar_baz".camelize #=> "Foo::BarBaz"
Rails ではきっと便利なんだと思うのですが、残念ながら仕様が私の都合にはあいませんでした。
モジュール Camelizable
そこで、古いソースをもとに小さなモジュールを自作しました。
インスタンスメソッドは以下の2つです。
- Camelizable#ucc
- Camelizable#lcc
いずれも、区切り文字列は引数で指定できます。正規表現か文字列で指定します。
区切り文字列のデフォルトは非英数文字の並びです。
module Camelizable
def ucc(sep=/[^[:alnum:]]+/) # 先頭が大文字のキャメルケース変換
split(sep).map(&:capitalize).join
end
def lcc(sep=/[^[:alnum:]]+/) # 先頭が小文字のキャメルケース変換
ucc(sep).sub(/./){ $&.downcase }
end
end
使い方は以下のような感じです。
class String
include Camelizable # String クラスに include する
end
p "foo_bar_baz".lcc #=> "fooBarBaz"
p "foo bar baz".lcc #=> "fooBarBaz"
p "foo/bar_baz".lcc #=> "fooBarBaz"
p "foo_bar_baz".ucc #=> "FooBarBaz"
p "foo bar_baz".ucc #=> "FooBarBaz"
p "foo/bar_baz".ucc #=> "FooBarBaz"
# 引数で区切り文字列を指定できます
p "foo_bar.baz".lcc(/_/) #=> "fooBar.baz"
p "foo_bar_baz".lcc(/_bar_/) #=> "fooBaz"
p "foo_bar_baz".lcc(/[ar]/) #=> "foo_b_bZ" (区切り文字に 'a' か 'r' を指定)
String クラスを拡張したくない場合は、文字列オブジェクトの特異メソッドとして使います。
str = "foo bar_baz"
str.extend Camelizable # 文字列オブジェトに extend する
p str.lcc #=> "fooBarBaz"
p str.ucc #=> "FooBarBaz"
文字列オブジェクトも拡張したくない場合は proc を作ったりします。
to_ucc = -> s, *args { (Camelizable.instance_method :ucc).bind(s).call *args }
p to_ucc.("foo-bar-baz") #=> "FooBarBaz"
ただし、lcc は実装が ucc に依存しているので、この方法はうまくいきません。
(とりあえず間に合ってるので、そこは放置。。。)
おまけ
ActiveSupport の String#camelize をシミュレートすると、(多分)こんな感じです。
(でも、camelize を使う時は、素直に本物を使ってください。)
class String
include Camelizable
def camelize(first_letter=:upper)
send(first_letter == :lower ? :lcc : :ucc, /_/).gsub(%r|/|){'::'}
end
end
Gem 化
※(2014.12.13追記)
Camelizable を Gem 化してアップしました。
インストール方法
$ gem install camelizable
※ (注) Gem版は String クラスに include Camelizable
されています。(String クラスを拡張します)
※(2014/12/27 追記) Gem 版の String クラスへの include は削除しました。