107 votes

Comment convertir un nom de classe Ruby en un symbole délimité par un tiret bas?

Comment puis-je transformer par programme un nom de classe, FooBar , en un symbole, :foo_bar ? Par exemple, quelque chose comme cela, mais qui gère correctement le cas de chameau?

 FooBar.to_s.downcase.to_sym
 

156voto

kikito Points 23229

Rails est livré avec une méthode appelée underscore qui vous permettra de vous transformer en Camelcase les chaînes en underscore_separated cordes. Donc, vous pourriez être en mesure de le faire:

FooBar.name.underscore.to_sym

Mais vous devrez installer ActiveSupport viens de le faire, comme ipsum dit.

Si vous ne souhaitez pas installer ActiveSupport juste pour cela, vous pouvez monkey patch- underscore en String vous-même (le trait de soulignement fonction est définie dans ActiveSupport::Inflecteur):

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

85voto

Ciro Santilli Points 3341

En plus de la conversion manuellement comme d'autres l'ont suggéré, dans les Rails 4:

FooBar.model_name

retourne un ActiveModel::Name objet qui contient beaucoup d'informations utiles en plus "sémantique" des attributs tels que:

FooBar.model_name.param_key
#=> "foo_bar"

FooBar.model_name.route_key
#=> "foo_bars"

FooBar.model_name.human
#=> "Foo bar"

Donc, vous devez utiliser l'un de ces si elles correspondent à votre sens désiré, ce qui est probablement le cas. Avantages:

  • plus facile à comprendre votre code
  • votre application fonctionne même dans le cas (improbable) que les Rails décide de modifier une convention de nommage.

BTW, human a l'avantage d'être I18N conscient.

9voto

ipsum Points 540

premier: gem install actifsupport

 require 'rubygems'
require 'active_support'
"FooBar".underscore.to_sym
 

2voto

Louis Sayers Points 909

Voici ce que je suis allé pour:

 module MyModule
  module ClassMethods
    def class_to_sym  
      name_without_namespace = name.split("::").last
      name_without_namespace.gsub(/([^\^])([A-Z])/,'\1_\2').downcase.to_sym
    end
  end

  def self.included(base)
    base.extend(ClassMethods)
  end
end

class ThisIsMyClass
  include MyModule
end 

ThisIsMyClass.class_to_sym #:this_is_my_class
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X