String'i snake_case'den Ruby'deki CamelCase'e dönüştürme


171

Yılan kasasından deve kasasına bir isim dönüştürmeye çalışıyorum. Yerleşik yöntemler var mı?

Ör: "app_user"hiç"AppUser"

(Bu "app_user"modele dönüştürmek istiyorum bir dize var AppUser).

Yanıtlar:


252

Rails kullanıyorsanız, String # camelize aradığınız şeydir.

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

Gerçek bir sınıf almak istiyorsanız , bunun üstünde String # constantize kullanmalısınız .

"app_user".camelize.constantize

44
Bunun String'e bir Rails eklentisi olduğunu, saf Ruby ile çalışmadığını eklemelisiniz.
2013'te

2
Etiketlendi ruby-on-rails, bu yüzden sanırım sorun değil. Ama bahsettiğiniz için teşekkürler.
Sergio Tulentsev

6
Sabitlemeden önce deveye ihtiyacınız yok. #classifyBunun yerine kullanın . "some_namespace/module/class_name".classify => "SomeNamespace::Module::ClassName"
Chris Heald

5
@chris #classify: Aynı değil. #classify bir dize döndürür, oysa #constantize bağlamda sabit görünür (ve deveye ihtiyaç duyar). 'active_record'.constantize hata verir,' active_record'.camelize.constantize sabit ActiveRecord'u, 'active_record'.classify' ActiveRecord 'dizesini döndürür. Eğer 'no_class'.camelize.constantize yaparsanız hata alırsınız (böyle bir sabit NoClass yok), ancak' no_class'.classify mutlu bir şekilde 'NoClass' dizesini döndürür.
Kanat Bolazar

Saf Ruby'den bu Ray yöntemlerini kullanmak için, Rayların require "active_support/core_ext/string"önceden kurulmuş olması koşuluyla yeterlidir.
Masa Sakano


40

Rails kullanıyorsanız, kullanın classify. Kenar kasalarını iyi idare eder.

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

Not:

Bu cevap soruda verilen açıklamaya özgüdür (soru başlığına özgü değildir). Eğer bir ipi deveye çevirmeye çalışıyorsa Sergio'nun cevabını kullanmalıdırlar. O dönüştürmek istediği sorgulayıcı devletler app_useriçin AppUser(değil App_user), dolayısıyla bu cevabı ..


4
Rails ortamları için mükemmeldir.
ghayes

classifyBir dize döndürdüğünü unutmayın, constantizedaha sonra gerçek bir sınıfa dönüştürmek için çağırmanız gerekir.
Stefan

1
Önemli bir uyarı classify, çoğullaştırılmış dizelerin tekil 'age_in_years'.classifyhale AgeInYear
gelmesidir

@ br3nt activerecord beri çoğullamaz4.2.11
Ulysse BN

23

Kaynak: http://rubydoc.info/gems/extlib/0.9.15/String#camel_case-instance_method

Öğrenme amacıyla:

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"

Ve lowerCase varyantı için:

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 direksiyona ActiveSupport adı verilirse , lütfen yeniden icat edin.
shime

LowerCase değişkeninin yanlış olduğunu düşünüyorum. self.split('_').inject([]){ |buffer,e| buffer + [buffer.empty? ? e : e.capitalize] }.join
Enjekte

19

Saf Ruby çözümleri için karşılaştırma ölçütü

Saf yakut koduyla bunu yapmak için aklımdaki tüm olasılıkları aldım, işte bunlar:

  • büyük harf ve büyük harf

    'app_user'.capitalize.gsub(/_(\w)/){$1.upcase}
  • &steno kullanarak böl ve eşleştir (user3869936'un cevabı sayesinde)

    'app_user'.split('_').map(&:capitalize).join
  • bölün ve haritalayın (Bay Black'in cevabı sayesinde)

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

İşte tüm bunlar için Benchmark, gsub'ın bunun için oldukça kötü olduğunu görebiliyoruz. 126 080 kelime kullandım.

                              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

Buraya, sorunuzun tersini aramaya başladım, deve kasasından yılan kasasına. Bunun için alt çizgi kullanın (decamelize değil):

AppUser.name.underscore # => "app_user"

veya zaten bir deve kılıfı dizeniz varsa:

"AppUser".underscore # => "app_user"

veya tablo adını almak istiyorsanız, büyük olasılıkla yılan kasasını istersiniz:

AppUser.name.tableize # => "app_users"


Neden kullanmıyorsunuz AppUser.table_name? Ayrıca, app_users değil, başka bir yerde tanımlanmış bir şeyse gerçek tablo adına sahip olmanız gerekir.
Ulysse BN

3

Buraya daha fazla cevap eklemek biraz huzursuz hissediyorum. @ Ulysse-bn'den güzel ölçütü göz ardı ederek en okunabilir ve minimal saf yakut yaklaşımına karar verdi. İken :classmod @ user3869936 bir kopyasıdır, :methodmod burada başka yanıtında görmüyorum.

  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

Sonuç:

[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
Deve kasası aslında ilk düşük. Aksi takdirde PascalCase (veya bazen üst deve kılıfı) olarak adlandırılır. Bu soruda olmasına rağmen belirsiz!
Ulysse BN

2
@UlysseBN, tbh Kelimelerin tarihine girmiyorum. Wikipedia iddiaları PascalCasebir alt kümesidir CamelCase. Ayrıca bildiğim de buydu - deve davası her ikisine de uygulandı. Ama hiç araştırmadım. Yine de PascalCase'den bahsettiğiniz için teşekkürler. en.wikipedia.org/wiki/Camel_case
akostadinov

2
Bu sayfa imo en iyi cevaptır. Eğer iyi olurdu :methodsürümü yaptılar downcasehem kullanılabilir, böylece ilk lower_snake_caseve UPPER_SNAKE_CASE.
skagedal

0

Burada listelenen diğer yöntemlerin çoğu Raylara özgüdür. Bunu saf Ruby ile yapmak istiyorsanız, aşağıda ortaya koyduğum en özlü yol (önerilen iyileştirme için @ ulysse-bn sayesinde)

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

"Camel case" tanımınız çok sınırlı. Java ve Ruby Sınıf isimleri, örneğin, şunlardır deve vaka MyFavoriteClass ... ama aynı zamanda daha düşük kasalı ilk harfi yok. bazen deve kasasının ilk kapakları vardır. bazen değil.
masukomi

Yalnızca bir tanesini kullanabileceğiniz 2 Regex kullanmak aşırıdır. Sadece yakalamayan grubu kullanabilirsiniz:x.gsub(/(?:_|^)(\w)/){$1.upcase}
Ulysse BN

@UlysseBN ve gsubçözümünüze geri dönüyoruz, ki bu mapçözümle karşılaştırıldığında daha yavaş görünüyor .
akostadinov

0

Camelize Eklemek için Dizeyi Uzat

Pure Ruby'de, dize sınıfını Rails ile aynı kodu kullanarak genişletebilirsiniz .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
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.