在Ruby中将字符串从snake_case转换为CamelCase


171

我正在尝试将名称从蛇案转换为骆驼案。有内置的方法吗?

例如:"app_user""AppUser"

(我有一个"app_user"想要将其转换为model 的字符串AppUser)。

Answers:


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,所以我想这不是问题。但是感谢您的提及。
Sergio Tulentsev

6
在稳定之前,您不需要骆驼化。使用#classify代替。"some_namespace/module/class_name".classify => "SomeNamespace::Module::ClassName"
克里斯·希尔德

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

为了从纯Ruby使用Rails的这些方法require "active_support/core_ext/string",只要已安装Rails就足够了。
Masa Sakano


40

如果您使用Rails,请使用classify。它可以很好地处理边缘情况。

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

注意:

该答案特定于问题中给出的描述(并非特定于问题标题)。如果试图将字符串转换为驼峰式大小写,则应使用Sergio的答案。发问者说他想要转换app_userAppUser(not App_user),因此此答案。


4
对于Rails环境,这是完美的。
ghayes

请注意,classify返回一个字符串,constantize之后必须调用将其转换为实际的类。
斯特凡

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

我认为lowerCase变体是错误的。注入块不应直接操作缓冲区,而应返回缓冲区的新值:self.split('_').inject([]){ |buffer,e| buffer + [buffer.empty? ? e : e.capitalize] }.join
Sven Koschnicke

19

纯Ruby解决方案的基准

我考虑了使用纯红宝石代码实现的所有可能性,它们是:

  • 大写和gsub

    'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
  • 使用&简写方式进行拆分和映射(感谢user3869936的回答)

    'app_user'.split('_').map(&:capitalize).join
  • 拆分并映射(感谢布莱克先生的回答)

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

这是所有这些的基准,我们可以看到gsub对此非常不利。我用了126080个单词。

                              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的不错基准。虽然: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我不喜欢这些单词的历史。维基百科声称PascalCase是的子集CamelCase。这也是我所知道的-骆驼案适用于两者。但是我从来没有调查过。感谢您提及PascalCase。en.wikipedia.org/wiki/Camel_case
akostadinov

2
这是imo页面上的最佳答案。如果该:method版本downcase首先进行了很好,那么它可以在lower_snake_case和上使用UPPER_SNAKE_CASE
skagedal '18

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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.