Rubyでの文字列のsnake_caseからCamelCaseへの変換


171

名前をスネークケースからラクダケースに変換しようとしています。組み込みのメソッドはありますか?

例:"app_user""AppUser"

(私は"app_user"それをモデルに変換したい文字列がありますAppUser)。

回答:


251

Railsを使用している場合、探しているのはString#camelizeです。

  "active_record".camelize                # => "ActiveRecord"
  "active_record".camelize(:lower)        # => "activeRecord"

実際のクラスを取得したい場合は、その上でString#constantizeを使用する必要があります。

"app_user".camelize.constantize

44
これは、StringへのRailsの追加であることを追加する必要があります。純粋なRubyでは機能しません。
iGEL 2013年

2
タグ付けされているruby-on-railsので、問題ないと思います。しかし言及してくれてありがとう。
セルジオTulentsev 2013

6
定数化する前にラクダ化する必要はありません。#classify代わりに使用してください。"some_namespace/module/class_name".classify => "SomeNamespace::Module::ClassName"
Chris Heald、2013年

5
@chris #classify:同じではありません。#classifyは文字列を返しますが、#constantizeはコンテキストで定数を検索します(キャメル化が必要です)。'active_record'.constantizeはエラーを出し、' active_record'.camelize.constantizeは定数ActiveRecordを返し、 'active_record'.classifyは文字列' ActiveRecord 'を返します。また、 'no_class'.camelize.constantizeを実行した場合、エラーが発生します(そのような定数NoClassはありません)が、' no_class'.classifyは 'NoClass'文字列を正常に返します。
Kanat Bolazar、2015

純粋なRubyからRailsのこれらのメソッドを使用するにrequire "active_support/core_ext/string"は、Railsがすでにインストールされていれば十分です。
坂野雅

120

これはどう?

"hello_world".split('_').collect(&:capitalize).join #=> "HelloWorld"

ここのコメントにあります: Ruby文字列の分類

ウェイン・コンラッドのコメントを見る


10
あなたは素晴らしいです、ありがとう。この小さなタスクのためだけにRailsライブラリを含める必要はありませんでした。美しいです。:)
Gerry

11
これは、質問に対する唯一の本当の答えの1つです。Railsライブラリを使用していません。
ルイスオルテガアラネダ2014

40

Railsを使用する場合は、を使用しclassifyます。エッジケースをうまく処理します。

"app_user".classify # => AppUser
"user_links".classify   # => UserLink

注意:

この回答は、質問で指定された説明に固有です(質問のタイトルに固有ではありません)。文字列をキャメルケースに変換しようとしている場合は、セルジオの答えを使用する必要があります。質問者は彼が(ではない)に変換app_userしたいと述べているため、この答えは..AppUserApp_user


4
Rails環境では、これは完璧です。
ghayes 2013

classify文字列を返すことに注意してくださいconstantize。実際のクラスに変換するには、後で呼び出す必要があります。
Stefan

1
重要な注意点classifyは、複数形の文字列が単数になることです...に'age_in_years'.classifyなるAgeInYear
br3nt

@ br3ntはactiverecord以降、複数形にはなりません4.2.11
Ulysse BN

23

ソース:http : //rubydoc.info/gems/extlib/0.9.15/String#camel_case-instance_method

学習目的:

class String
  def camel_case
    return self if self !~ /_/ && self =~ /[A-Z]+.*/
    split('_').map{|e| e.capitalize}.join
  end
end

"foo_bar".camel_case          #=> "FooBar"

そしてlowerCaseバリアントの場合:

class String
  def camel_case_lower
    self.split('_').inject([]){ |buffer,e| buffer.push(buffer.empty? ? e : e.capitalize) }.join
  end
end

"foo_bar".camel_case_lower          #=> "fooBar"

6
@pguardiarioホイールがActiveSupportと呼ばれる場合は、再発明してください。
shime 2015年

lowerCaseバリアントは間違っていると思います。:注入ブロックは、直接バッファを操作するが、バッファに新しい値を返すべきではありませんself.split('_').inject([]){ |buffer,e| buffer + [buffer.empty? ? e : e.capitalize] }.join
スヴェンKoschnicke

19

純粋なRubyソリューションのベンチマーク

私は純粋なルビコードでそれを行うために考えていたすべての可能性を取りました、ここにあります:

  • 大文字とgsub

    'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
  • &短縮形を使用して分割およびマッピング(user3869936の回答に感謝)

    'app_user'.split('_').map(&:capitalize).join
  • 分割してマッピング(Black氏の回答に感謝)

    'app_user'.split('_').map{|e| e.capitalize}.join

そして、これらすべてのベンチマークがここにあります。gsubはこれに対してかなり悪いことがわかります。126 080語を使用しました。

                              user     system      total        real
capitalize and gsub  :      0.360000   0.000000   0.360000 (  0.357472)
split and map, with &:      0.190000   0.000000   0.190000 (  0.189493)
split and map        :      0.170000   0.000000   0.170000 (  0.171859)

11

キャメルケースからスネークケースまで、あなたの質問の逆を探してここに来ました。そのためにアンダースコアを使用します(デカメル化しないでください):

AppUser.name.underscore # => "app_user"

または、すでにキャメルケースの文字列がある場合:

"AppUser".underscore # => "app_user"

または、テーブル名を取得する場合は、おそらく蛇のケースが必要なのはこのためです。

AppUser.name.tableize # => "app_users"


なぜ使用しないのAppUser.table_nameですか?また、app_usersではなく、他の場所で定義されているものである場合は、真のテーブル名を使用することもできます。
Ulysse BN

3

ここに答えを追加するのが少し不安です。@ ulysse-bnの優れたベンチマークを無視して、最も読みやすく最小限の純粋なルビーアプローチを採用することを決定しました。一方で:classモードは、@ user3869936のコピーである、:methodモードは私がここに他の回答には表示されません。

  def snake_to_camel_case(str, mode: :class)
    case mode
    when :class
      str.split('_').map(&:capitalize).join
    when :method
      str.split('_').inject { |m, p| m + p.capitalize }
    else
      raise "unknown mode #{mode.inspect}"
    end
  end

結果は次のとおりです。

[28] pry(main)> snake_to_camel_case("asd_dsa_fds", mode: :class)
=> "AsdDsaFds"
[29] pry(main)> snake_to_camel_case("asd_dsa_fds", mode: :method)
=> "asdDsaFds"

1
キャメルケースは実際には最初に低いです。それ以外の場合は、PascalCase(またはキャメルの大文字)と呼ばれます。この質問ではあいまいですが!
Ulysse BN

2
@ UlysseBN、tbh私は言葉の歴史には入っていない。ウィキペディアの主張PascalCaseはのサブセットですCamelCase。また、これは私が知っていることです-そのキャメルケースは両方に適用されました。しかし、私は調査したことがありません。PascalCaseについて言及していただきありがとうございます。en.wikipedia.org/wiki/Camel_case
akostadinov '28 / 03/18

2
これは、imoページの最良の答えです。:methodバージョンがdowncase最初に実行され、lower_snake_caseとの両方で使用できるようにすると便利ですUPPER_SNAKE_CASE
skagedal 2018

0

ここにリストされている他のメソッドのほとんどはRails固有です。純粋なRubyでこれを行う場合は、以下が私が思いついた最も簡潔な方法です(提案された改善のために@ ulysse-bnに感謝します)。

x="this_should_be_camel_case"
x.gsub(/(?:_|^)(\w)/){$1.upcase}
    #=> "ThisShouldBeCamelCase"

「ラクダケース」の定義が限定的すぎます。Java、およびRubyでクラス名は、例えば、あるキャメルケースMyFavoriteClass ...しかし、彼らはまた、下ケース入り最初の手紙を持っていません。キャメルケースには最初にキャップが付いていることがあります。時々それはしません。
ますこみ2016年

1つしか使用できない2つの正規表現を使用するのはやりすぎです。:あなたは唯一の非キャプチャグループを使用することができますx.gsub(/(?:_|^)(\w)/){$1.upcase}
ユリスBN

@UlysseBN、そして私たちはあなたのgsubソリューションに戻ってきました、それはソリューションと比較して遅いようmapです。
akostadinov

0

Camelizeを追加するための文字列の拡張

純粋なRubyでは、Railsのまったく同じコードを使用して文字列クラスを拡張できます .camelize

class String
  def camelize(uppercase_first_letter = true)
    string = self
    if uppercase_first_letter
      string = string.sub(/^[a-z\d]*/) { |match| match.capitalize }
    else
      string = string.sub(/^(?:(?=\b|[A-Z_])|\w)/) { |match| match.downcase }
    end
    string.gsub(/(?:_|(\/))([a-z\d]*)/) { "#{$1}#{$2.capitalize}" }.gsub("/", "::")
  end
end
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.