Преобразование строки из snake_case в CamelCase в Ruby

120

Я пытаюсь преобразовать имя из случая змейки в случай верблюда. Существуют ли встроенные методы?

Например: "app_user" to "AppUser"

(У меня есть строка "app_user" Я хочу преобразовать ее в модель AppUser).

Теги:
string

7 ответов

186
Лучший ответ

Если вы используете Rails, String # camelize - это то, что вы ищете.

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

Если вы хотите получить фактический класс, вы должны использовать String # constantize.

"app_user".camelize.constantize
  • 38
    Вы должны добавить, что это дополнение Rails к String, оно не работает с чистым Ruby.
  • 2
    Он помечен как ruby-on-rails , так что, думаю, это не проблема. Но спасибо за упоминание.
Показать ещё 3 комментария
78

Как насчет этого?

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

Найдено в комментариях здесь: Классифицировать строку Ruby

Смотрите комментарий Уэйн Конрад

  • 9
    Вы великолепны, спасибо. Я не хотел включать библиотеки rails только для такой маленькой задачи. Это прекрасно. :)
  • 10
    Это один из немногих реальных ответов на вопрос. Не использовать библиотеки Rails.
40

Используйте classify. Он хорошо справляется с краевыми случаями.

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

Примечание:

Этот ответ относится к описанию, данному в вопросе (это не относится к заголовку вопроса). Если вы пытаетесь преобразовать строку в верблюд-футляр, они должны использовать ответ Sergio. Вопросник утверждает, что он хочет преобразовать app_user в AppUser (не app_user), следовательно, этот ответ..

  • 4
    Для сред Rails это идеально.
  • 0
    Обратите внимание, что classify возвращает строку, после чего вы должны вызвать constantize чтобы преобразовать ее в реальный класс.
Показать ещё 1 комментарий
19

Источник: 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"
  • 2
    Разве мы не должны учиться не изобретать велосипед?
  • 5
    @pguardiario, это после того, как мы узнали, как работает колесо.
Показать ещё 2 комментария
9

Я здесь искал обратный вопрос, идущий от случая верблюда к делу змеи. Используйте underscore для этого (не decamelize):

AppUser.name.underscore # => "app_user"

или, если у вас уже есть строка с верблюжьим футляром:

"AppUser".underscore # => "app_user"

или, если вы хотите получить имя таблицы, то, вероятно, вам нужен случай с змеей:

AppUser.name.tableize # => "app_users"

  • 0
    Почему бы не использовать AppUser.table_name ? Вы также убедитесь, что у вас есть истинное имя таблицы, если это не app_users, а что-то определенное в другом месте.
7

Тест для чистых решений Ruby

Я использовал все возможности, которые я имел в виду, чтобы сделать это с чистым кодом ruby, вот они:

  • capize и gsub

    "app_user".capitalize.gsub(/_(\w)/){$1.upcase}
    
  • расщепление и отображение с использованием сокращения & (спасибо пользователю3869936s)

    "app_user".split('_').map(&:capitalize).join
    
  • раскол и карта (спасибо ответу г-на Блэков)

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

И вот Benchmark для всех этих, мы можем видеть, что 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)
1

Большинство других методов, перечисленных здесь, являются специфичными для Rails. Если вы хотите сделать это с помощью чистого Ruby, то это самый сжатый способ, который я придумал (благодаря @ulysse-bn для предлагаемого улучшения)

x="this_should_be_camel_case"
x.gsub(/(?:_|^)(\w)/){$1.upcase}
    #=> "ThisShouldBeCamelCase"
  • 0
    Ваше определение «случая верблюда» слишком ограничено. Имена классов в Java и, например, Ruby, имеют верблюжий регистр MyFavoriteClass ... но они также не имеют строчной буквы. иногда у верблюжьего чехла есть начальные колпачки иногда это не так.
  • 0
    Использование 2-х регулярных выражений, где вы можете использовать только одно, является излишним. Вы можете использовать только группу без захвата: x.gsub(/(?:_|^)(\w)/){$1.upcase}
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню