2009-10-02 13 views
178

Czy jest jakaś gotowa funkcja, która przekształca łańcuchy wielbłądów w ciąg podkreślony?Konwersja wielbłąda do podkreślenia w rubinie

chcę coś takiego:

"CamelCaseString".to_underscore  

powrotu "camel_case_string".

...

+35

FYI: małe i podkreślona jest „oficjalnie” nazywa wąż case – Andrew

+3

To dziwne, widzieć "oficjalnie" w cudzysłowie, a jednak jest to najlepszy sposób, aby to opisać. –

Odpowiedz

299

Rails' ActiveSupport dodaje podkreślenia do łańcucha stosując następujący:

class String 
    def underscore 
    self.gsub(/::/, '/'). 
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
    gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
    tr("-", "_"). 
    downcase 
    end 
end 

Następnie można zrobić rzeczy Fun:

"CamelCase".underscore 
=> "camel_case" 
+5

Jeśli zmienisz 'tr (" - "," _ ")' na 'tr (" - "," _ ")' (spacja dodana do pierwszego paramu), to również zamieni spacje na podkreślenia. Ponadto, nie sądzę, abyś musiał dołączyć "self", a przynajmniej działa dla mnie w Ruby 1.9.3. –

+3

'require 'active_support/core_ext/string'' – konsolebox

16

Oto jak Rails does it:

def underscore(camel_cased_word) 
    camel_cased_word.to_s.gsub(/::/, '/'). 
     gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
     gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
     tr("-", "_"). 
     downcase 
    end 
realizacja
+0

Lepiej mieć argument operacji jako argument metody niż inwazji na rdzeń klasy String. – Pistos

+1

Nie zgadzam się - lepiej, aby działało na zajęciach tak, jak powinno, lub w inny sposób będziesz musiał włożyć go do modułu i pamiętać o włączeniu go tam, gdzie będzie potrzebny. – Ghoti

+1

Ta metoda jest również częścią łańcuchów Rails 3 i tak :) – Ghoti

45

One-liner Ruby:

class String 
    # ruby mutation methods have the expectation to return self if a mutation occurred, nil otherwise. (see http://www.ruby-doc.org/core-1.9.3/String.html#method-i-gsub-21) 
    def to_underscore! 
    gsub!(/(.)([A-Z])/,'\1_\2') 
    downcase! 
    end 

    def to_underscore 
    dup.tap { |s| s.to_underscore! } 
    end 
end 

Więc "SomeCamelCase".to_underscore # =>"some_camel_case"

+2

jak inne rozwiązania nie są czystymi rubinami? – jrhicks

+0

Och, sh ... Dzięki - bardziej interesowało mnie pisanie niż czytanie. W rezultacie - linki w Rails sprawiły, że myślałem, że te inne fragmenty są specyficzne dla Railsów. Zmieniona odpowiedź ... – kirushik

+1

Wystąpił kolejny błąd w mojej edycji i wydaje się, że nie mogę go naprawić. Oto poprawiony kod: https://gist.github.com/4027440 –

61

Można użyć

"CamelCasedName".tableize.singularize 

lub po prostu

"CamelCasedName".underscore 

obie opcje sposoby przyniesie "camel_cased_name". Możesz sprawdzić więcej szczegółów to here.

+8

Jest to część implementacji ActiveSupport :: Inflector, bez której nie możesz używać tych rozszerzeń String (spróbuj w konsoli czystej irb: "ThisCamelCaseString" .underscore, następnie wymagaj "active_support/inflector" i spróbuj ponownie) –

+5

Donovan ponieważ nie jest to zwykły rubin. – Papipo

25

Jest Szyny wbudowana metoda zwana „podkreślenia”, którego można użyć do tego celu

"CamelCaseString".underscore #=> "camel_case_string" 

do „podkreślenia” metoda może być zwykle uznawane za odwrotności „camelize”

+0

niezdefiniowana metoda "podkreślenie" dla "...": String – Dorian

+2

Jest to metoda ActiveSupport – Dorian

6

Wyjazd snakecase z Ruby Facets

następujących przypadkach są traktowane, jak widać poniżej:

"SnakeCase".snakecase   #=> "snake_case" 
"Snake-Case".snakecase  #=> "snake_case" 
"Snake Case".snakecase  #=> "snake_case" 
"Snake - Case".snakecase #=> "snake_case" 

Od: https://github.com/rubyworks/facets/blob/master/lib/core/facets/string/snakecase.rb

class String 

    # Underscore a string such that camelcase, dashes and spaces are 
    # replaced by underscores. This is the reverse of {#camelcase}, 
    # albeit not an exact inverse. 
    # 
    # "SnakeCase".snakecase   #=> "snake_case" 
    # "Snake-Case".snakecase  #=> "snake_case" 
    # "Snake Case".snakecase  #=> "snake_case" 
    # "Snake - Case".snakecase #=> "snake_case" 
    # 
    # Note, this method no longer converts `::` to `/`, in that case 
    # use the {#pathize} method instead. 

    def snakecase 
    #gsub(/::/, '/'). 
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). 
    gsub(/([a-z\d])([A-Z])/,'\1_\2'). 
    tr('-', '_'). 
    gsub(/\s/, '_'). 
    gsub(/__+/, '_'). 
    downcase 
    end 

    # 
    alias_method :underscore, :snakecase 

    # TODO: Add *separators to #snakecase, like camelcase. 

end 
1

Chciałbym to:

class String 

    # \n returns the capture group of "n" index 
    def snikize 
    self.gsub(/::/, '/') 
    .gsub(/([a-z\d])([A-Z])/, "\1_\2") 
    .downcase 
    end 

    # or 

    def snikize 
    self.gsub(/::/, '/') 
    .gsub(/([a-z\d])([A-Z])/) do 
     "#{$1}_#{$2}" 
    end 
    .downcase 
    end 

end 

Monkey skrawek String klasie. Istnieją klasy, które zaczynają się od dwóch lub więcej wielkich liter.

3

Krótki oneliner dla CamelCases gdy masz obowiązuje również (nie działa prawidłowo, jeśli masz słowo pomiędzy nimi z małym wyjścia listu):

a = "Test String" 
a.gsub(' ', '').underscore 

    => "test_string"