web-dev-qa-db-fra.com

Comment convertir un nom de classe Ruby en un symbole délimité par des traits de soulignement?

Comment puis-je transformer par programme un nom de classe, FooBar, en un symbole, :foo_bar? par exemple. quelque chose comme ça, mais qui gère correctement l'étui à chameau?

FooBar.to_s.downcase.to_sym
88
Josh Glover

Rails est livré avec une méthode appelée underscore qui vous permettra de transformer des chaînes CamelCased en chaînes de soulignement séparées. Vous pourriez donc être en mesure de le faire:

FooBar.name.underscore.to_sym

Mais vous devrez installer ActiveSupport juste pour le faire, comme le dit ipsum.

Si vous ne voulez pas installer ActiveSupport juste pour cela, vous pouvez monkey-patch underscore dans String vous-même (la fonction de soulignement est définie dans ActiveSupport :: Inflector ):

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
134
kikito

Rails 4 .model_name

Dans Rails 4, il renvoie un ActiveModel::Name objet qui contient de nombreux autres attributs "sémantiques" utiles tels que:

FooBar.model_name.param_key
#=> "foo_bar"

FooBar.model_name.route_key
#=> "foo_bars"

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

Vous devez donc en utiliser un s'ils correspondent à la signification souhaitée, ce qui est probablement le cas. Avantages:

  • plus facile à comprendre votre code
  • votre application fonctionnera toujours même dans le cas (peu probable) où Rails décide de modifier une convention de dénomination).

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

premier: gem install activeupport

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

Voici ce que j'ai recherché:

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
2
Louis Sayers