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

2
태그가 붙어 ruby-on-rails있으므로 문제가되지 않습니다. 그러나 언급 해 주셔서 감사합니다.
Sergio Tulentsev

6
일정하기 전에 낙타가 필요하지 않습니다. #classify대신 사용하십시오 . "some_namespace/module/class_name".classify => "SomeNamespace::Module::ClassName"
Chris Heald

5
@ chris #classify : 동일하지 않습니다. #classify는 문자열을 반환하지만 #constantize는 컨텍스트에서 일정하게 조회됩니다 (그리고 camelize가 필요함). 'active_record'.constantize는 오류를 발생시키고'active_record'.camelize.constantize는 상수 ActiveRecord를 반환하고 'active_record'.classify는 문자열'ActiveRecord '를 반환합니다. 그리고 'no_class'.camelize.constantize를 수행하면 오류 (상수 NoClass 없음)가 발생하지만'no_class'.classify는 행복하게 'NoClass'문자열을 반환합니다.
Kanat Bolazar

순수 Ruby에서 이러한 Rails 방법을 사용하려면 require "active_support/core_ext/string"Rails가 이미 설치되어 있으면 충분합니다.
Masa Sakano

120

이건 어때?

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

여기 주석에서 찾을 수 있습니다 : Ruby 문자열 분류

Wayne Conrad의 코멘트보기


10
당신은 굉장합니다, 감사합니다. 나는이 작은 작업을 위해 레일 라이브러리를 포함하고 싶지 않았습니다. 이것은 아름답다. :)
Gerry

11
이것은 질문에 대한 유일한 실제 답변 중 하나입니다. Rails 라이브러리를 사용하지 않습니다.
Luis Ortega Araneda

40

Rails를 사용하는 경우을 사용하십시오 classify. 가장자리 케이스를 잘 처리합니다.

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

노트 :

이 답변은 질문에 주어진 설명에만 해당됩니다 (질문 제목에만 국한되지는 않음). 문자열을 낙타 케이스로 변환하려고하면 Sergio 의 대답 을 사용해야합니다 . 질문자는 그가로 변환 app_user하고 AppUser싶지 않다고 App_user말했기 때문에이 대답은 ..


4
Rails 환경에서는 완벽합니다.
ghayes

classify문자열 을 반환하므로 constantize나중에 실제 클래스로 변환 하려면 호출해야합니다 .
스테판

1
와 중요한주의가 classifypluralised 문자열이 단수가 될 것입니다 ... '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
휠이 ActiveSupport 라고하는 경우 @pguardiario , 다시 발명하십시오.
shime

lowerCase 변형이 잘못되었다고 생각합니다. 주입 블록은 버퍼를 직접 조작하지 말고 버퍼의 새 값을 반환해야합니다.self.split('_').inject([]){ |buffer,e| buffer + [buffer.empty? ? e : e.capitalize] }.join
Sven Koschnicke

19

순수한 루비 솔루션의 벤치 마크

순수한 루비 코드로 할 수있는 모든 가능성을 생각했습니다.

  • 대문자와 gsub

    'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
  • &속기를 사용하여 분할 및 매핑 (user3869936의 답변 덕분에)

    'app_user'.split('_').map(&:capitalize).join
  • 분할 및지도 (블랙 씨의 답변 덕분에)

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

그리고 여기에이 모든 것들에 대한 벤치 마크가 있습니다. 나는 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가 아닌 다른 곳에 정의 된 테이블 이름이면 실제 테이블 이름을 사용해야합니다.
율리시스 BN

3

여기에 더 많은 답변을 추가하는 것이 약간 불편하다고 느낍니다. @ ulysse-bn의 멋진 벤치 마크를 무시하고 가장 읽기 쉽고 최소한의 순수한 루비 접근법을 사용하기로 결정했습니다. :classmode는 @ 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 나는 단어의 역사에 있지 않습니다. Wikipedia claim은의 PascalCase일부입니다 CamelCase. 또한 이것은 내가 알고있는 것입니다-낙타 사건은 둘 다에 적용되었습니다. 그러나 나는 조사한 적이 없다. 그래도 PascalCase를 언급 해 주셔서 감사합니다. en.wikipedia.org/wiki/Camel_case
akostadinov

2
이것은 페이지 imo에서 가장 좋은 답변입니다. :method버전이 downcase처음으로 수행 되면 좋을 것이므로 lower_snake_case와 모두에 사용할 수 있습니다 UPPER_SNAKE_CASE.
skagedal

0

여기에 나열된 다른 방법은 대부분 Rails에 따라 다릅니다. 순수한 Ruby 로이 작업을 수행하려면 다음과 같은 가장 간결한 방법이 있습니다 (제안 된 개선을 위해 @ ulysse-bn에게 감사드립니다)

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

"낙타의 경우"에 대한 정의가 너무 제한적입니다. 예를 들어 Java의 클래스 이름과 Ruby 낙타의 경우 MyFavoriteClass입니다. 그러나 소문자 첫 글자도 없습니다. 때로는 낙타 케이스에 초기 캡이 있습니다. 때로는 그렇지 않습니다.
masukomi

하나만 사용할 수있는 2 정규식을 사용하면 과잉입니다. 비 캡처 그룹 만 사용할 수 있습니다.x.gsub(/(?:_|^)(\w)/){$1.upcase}
Ulysse BN

@UlysseBN, 우리는 귀하의 gsub솔루션 으로 돌아 왔으며 솔루션에 비해 느린 것 같습니다 map.
akostadinov

0

낙타를 추가하기 위해 문자열을 확장

순수 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.