Como posso transformar programaticamente um nome de classe,, FooBar
em um símbolo :foo_bar
,? por exemplo, algo assim, mas que lida com a caixa de camelo corretamente?
FooBar.to_s.downcase.to_sym
Como posso transformar programaticamente um nome de classe,, FooBar
em um símbolo :foo_bar
,? por exemplo, algo assim, mas que lida com a caixa de camelo corretamente?
FooBar.to_s.downcase.to_sym
Respostas:
Rails vem com um método chamado underscore
que permitirá a você transformar strings CamelCased em strings underscore_separated. Então, você pode fazer isso:
FooBar.name.underscore.to_sym
Mas você terá que instalar o ActiveSupport apenas para fazer isso, como diz o ipsum.
Se você não deseja instalar o ActiveSupport apenas para isso, pode fazer um monkey-patch underscore
em String
você mesmo (a função de sublinhado é definida em 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
Rails 4 .model_name
No Rails 4, ele retorna um ActiveModel::Name
objeto que contém muitos atributos mais "semânticos" úteis, como:
FooBar.model_name.param_key
#=> "foo_bar"
FooBar.model_name.route_key
#=> "foo_bars"
FooBar.model_name.human
#=> "Foo bar"
Portanto, você deve usar um deles se corresponderem ao significado desejado, o que provavelmente é o caso. Vantagens:
BTW, human
tem a vantagem de estar ciente do I18N.
model_name
também funciona para objetos de instância. Ex: foo_bar.model_name
. Se você quiser a lista completa, escreva foo_bar.model_name.inspect
no console do Rails ou no seu depurador
classify
, modelize
não parecem funcionar.
primeiro: gem install activesupport
require 'rubygems'
require 'active_support'
"FooBar".underscore.to_sym
FooBar.to_s.underscore.to_sym
, já que estou tentando converter uma classe (que é uma constante) em um símbolo, que posso alimentar a Factory Girl . :)
Aqui está o que eu busquei:
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
String#demodulize
que removerá a parte anterior ::
.