2012-03-01 12 views

Odpowiedz

189

Jeśli używasz Railsów, String#camelize jest tym, czego szukasz.

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

Jeśli chcesz uzyskać aktualną klasę, powinieneś dodatkowo użyć String#constantize.

"app_user".camelize.constantize 
+30

Należy dodać, że jest to dodatek do szyn String, to nie działa z czystym Ruby. – iGEL

+1

Jest oznaczony 'ruby-on-rails', więc, jak sądzę, to nie problem. Ale dzięki za wzmiankę. –

+6

Nie musisz wielbłądów przed ustawieniem. Zamiast tego użyj '# classify'. '" some_namespace/module/class_name ".classify =>" SomeNamespace :: Module :: ClassName "' –

40

Użyj classify. Dobrze radzi sobie z przypadkami na krawędziach.

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

Uwaga:

Ta odpowiedź jest specyficzne z opisem podanym w pytaniu (to nie jest specyficzne dla tytule zapytania). Jeśli próbujesz przekonwertować ciąg na wielbłądzie, powinni użyć odpowiedzi: Sergio. Pytający stwierdza, że ​​chce przekształcić app_user do AppUser (nie App_user), stąd ta odpowiedź ..

+4

Dla środowisk Railsowych jest to idealne rozwiązanie. – ghayes

+0

Zauważ, że 'classify' zwraca ciąg znaków, musisz później wywołać' constantize', aby przekonwertować go na aktualną klasę. – Stefan

+1

Ważnym zastrzeżeniem z "klasyfikacją" jest to, że ciągi o różnych rozmiarach staną się pojedyncze ... "age_in_years'.classify" stanie się "AgeInYear" – br3nt

21

Źródło: http://rubydoc.info/gems/extlib/0.9.15/String#camel_case-instance_method

do nauki celu:

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" 

A dla wariantu małymi literami:

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

Czy nie powinniśmy uczyć się, aby nie odkrywać koła na nowo? – pguardiario

+5

@pguardiario, po tym, jak dowiedzieliśmy się, jak działa koło. – caesarsol

+5

@pguardiario, jeśli koło nazywa się * ActiveSupport *, wymyśl je ponownie. – shime

9

Poszukałem odwrotności twojego pytania, przechodząc od przypadku wielbłąda do s sprawa nake. Użyj underscore na to (nie decamelize):

AppUser.name.underscore # => "app_user"

lub, jeśli masz już camel sprawa ciąg:

"AppUser".underscore # => "app_user"

lub, jeśli chcesz uzyskać nazwę tabeli, która prawdopodobnie dlatego, że chcesz sprawę snake:

AppUser.name.tableize # => "app_users"

1

Większość innych wymienionych tutaj metod jest specyficznych dla Rails. Jeśli chcesz rób tego z czystej Ruby, następujące jest najbardziej zwięzły sposób mam wymyślić (dzięki @ Ulysse-bn dla sugerowanej poprawy)

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

Twoja definicja "przypadku wielbłąda" jest zbyt ograniczona. Nazwy klas w Javie i na przykład Ruby * to * wielka litera MyFavoriteClass ... ale nie mają też pierwszej litery pisanej małymi literami.czasami skrzynia wielbłąda ma początkowe czapki. czasami tak nie jest. – masukomi

+0

Używanie 2 Regeksa, w którym można użyć tylko jednego, jest przesadą. Możesz użyć tylko niezapisującej grupy: 'x.gsub (/ (?: _ | ^) (\ W) /) {$ 1.upcase}' –

85

Jak o tym?

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

Znaleziono tu komentarze: Classify a Ruby string

Zobacz komentarz Wayne Conrad

+8

Jesteś niesamowity, dziękuję. Nie chciałem włączać bibliotek szyn do zadania tak małego. To jest piękne. :) – Gerry

+8

Jest to jedna z niewielu odpowiedzi na to pytanie. Nie używając bibliotek Rails. –

8

Benchmark dla czystych rozwiązań Ruby

wziąłem co możliwości miałem na myśli to zrobić z czystego kodu Ruby , tutaj są to:

  • wykorzystać i gsub

    "app_user".capitalize.gsub(/_(\w)/){$1.upcase} 
    
  • Split i mapę przy użyciu & skrótów (dzięki odpowiedzi user3869936'S)

    "app_user".split('_').map(&:capitalize).join 
    
  • dzielenie i map (dzięki pana Blacka odpowiedź)

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

I tutaj jest Benchmark dla wszystkich z nich, my widać, że gsub jest na to zły. Użyłem 126 080 słów.

       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) 
0

Czuję się trochę nieswojo, aby dodać więcej odpowiedzi tutaj. Postanowili przejść do najbardziej czytelnego i minimalnego podejścia z czystym rubinem, pomijając ładny benchmark z @ ulysse-bn. Podczas gdy tryb :class jest kopią trybu @ user3869936, :method, nie widzę tutaj żadnej innej odpowiedzi.

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 

Wynik jest:

[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" 
Powiązane problemy