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

95

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

FooBar.to_s.downcase.to_sym
Josh Glover
la source

Réponses:

141

Rails est livré avec une méthode appelée underscorequi vous permettra de transformer des chaînes CamelCased en chaînes underscore_separated. Vous pourrez donc peut-être faire ceci:

FooBar.name.underscore.to_sym

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

Si vous ne souhaitez pas installer ActiveSupport juste pour cela, vous pouvez singe-patch underscoreen Stringvous - même (la fonction underscore 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
kikito
la source
1
Merci. J'avais peur que ce soit une extension Rails. :) Pas de soucis, car j'utilise actuellement Rails.
Josh Glover
2
Ensuite, vous devriez avoir étiqueté votre question en conséquence. Ici, laissez-moi le faire pour vous ...
kikito
5
Non, pas ActiveRecord. ActiveSupport.
Rein Henrichs
En effet, laissez-moi le changer
kikito
2
comment faire l'inverse?
user1406062
72

Rails 4 .model_name

Dans Rails 4, il renvoie un ActiveModel::Nameobjet qui contient de nombreux attributs plus "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 devriez donc en utiliser un s'il correspond à 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, humana l'avantage d'être conscient I18N.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
la source
model_namefonctionne également pour les objets par exemple. Ex: foo_bar.model_name. Si vous voulez que la liste complète soit écrite foo_bar.model_name.inspectdans la console des rails ou votre débogueur
ivanxuu
et je cherchais le contraire / inverse, classify, modelizene semble pas fonctionner.
Pysis le
7

first: gem install activesupport

require 'rubygems'
require 'active_support'
"FooBar".underscore.to_sym
ipsum
la source
FooBar.to_s.underscore.to_symCela devrait être , puisque j'essaie de convertir une classe (qui est une constante) en un symbole, que je peux ensuite transmettre à Factory Girl . :)
Josh Glover
2

Voici ce que j'ai fait:

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
Louis Sayers
la source
3
ActiveSupport a String#demodulizequi supprimera la pièce avant ::.
amoebe le
@amoebe - merci pour l'info. Cela dépend de ce sur quoi vous travaillez - vous ne travaillez peut-être pas sur une application de rails (ou même une application Web).
Louis Sayers