Como faço para converter um nome de classe Ruby em um símbolo delimitado por sublinhado?

95

Como posso transformar programaticamente um nome de classe,, FooBarem um símbolo :foo_bar,? por exemplo, algo assim, mas que lida com a caixa de camelo corretamente?

FooBar.to_s.downcase.to_sym
Josh Glover
fonte

Respostas:

141

Rails vem com um método chamado underscoreque 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 underscoreem Stringvocê 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
kikito
fonte
1
Obrigado. Eu estava com medo de que fosse uma extensão do Rails. :) Não se preocupe, já que estou usando Rails.
Josh Glover,
2
Então você deveria ter marcado sua pergunta de acordo. Aqui, deixe-me fazer isso por você ...
kikito
5
Não, não ActiveRecord. ActiveSupport.
Rein Henrichs,
Na verdade, deixe-me mudar isso
kikito
2
como fazer o inverso?
user1406062
72

Rails 4 .model_name

No Rails 4, ele retorna um ActiveModel::Nameobjeto 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:

  • mais fácil de entender seu código
  • seu aplicativo ainda funcionará mesmo no caso (improvável) de o Rails decidir mudar uma convenção de nomenclatura.

BTW, humantem a vantagem de estar ciente do I18N.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
fonte
model_nametambém funciona para objetos de instância. Ex: foo_bar.model_name. Se você quiser a lista completa, escreva foo_bar.model_name.inspectno console do Rails ou no seu depurador
ivanxuu
e eu estava olhando para a frente / reversa, classify, modelizenão parecem funcionar.
Pysis
7

primeiro: gem install activesupport

require 'rubygems'
require 'active_support'
"FooBar".underscore.to_sym
ipsum
fonte
Deveria ser 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 . :)
Josh Glover
2

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
Louis Sayers
fonte
3
ActiveSupport tem String#demodulizeque removerá a parte anterior ::.
amebe
@amoebe - obrigado pela informação. Porém, depende em que você está trabalhando - você pode não estar trabalhando em um aplicativo Rails (ou mesmo em um aplicativo web).
Louis Sayers