Como crio uma instância de classe a partir de um nome de string em ruby?

121

Eu tenho o nome de uma classe e quero criar uma instância dessa classe para que eu possa percorrer cada atributo do rails que está presente no esquema dessa classe.

Como eu faria isso?

  1. Eu tenho o nome como uma sequência da classe que quero verificar
  2. Eu acho que preciso instanciar uma instância de classe para que eu possa
  3. Passe pelos atributos e imprima-os.
mhenrixon
fonte
1
Esta é uma grande pergunta. Obrigado por perguntar isso e me salvar de usareval
David West

Respostas:

219

Nos trilhos, você pode apenas fazer:

clazz = 'ExampleClass'.constantize

Em rubi puro:

clazz = Object.const_get('ExampleClass')

com módulos:

module Foo
  class Bar
  end
end

você usaria

> clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
  => Foo::Bar 
> clazz.new
  => #<Foo::Bar:0x0000010110a4f8> 
Wes
fonte
4
Note que Object.const_get('Foo::Bar')não vai funcionar, enquanto constantizevai.
Marc-André Lafortune
Obrigado, acordei para perguntar sobre isso por causa de um problema do Admin :: User :) Entre em contato comigo.
Mhenrixon
Hey @Wes, isso foi útil, obrigado! Pergunta rápida - isso funcionaria também para módulos aninhados? Por exemplo,clazz = 'Foo::Bar::Uber'
iaacp 16/03/2015
@iaacp Sim, funcionará para tantos níveis aninhados quanto você.
Wes
15

Muito simples no Rails: use String#constantize

class_name = "MyClass"
instance = class_name.constantize.new
edgerunner
fonte
6
Para Rails não Ruby :(
ethichack3r 17/09/2013
Copiar descaradamente a implementação ActiveSupport se você não está usando Rails já
edgerunner
6

Tente o seguinte:

Kernel.const_get("MyClass").new

Em seguida, faça um loop pelas variáveis ​​de instância de um objeto:

obj.instance_variables.each do |v|
  # do something
end
mbreining
fonte
Obrigado, desde que eu realmente tem que percorrer as colunas do modelo de registro ativo isto não vai funcionar para mim, mas será útil nas minhas "puros" apps rubi :)
mhenrixon
1
Confira ActiveRecord # attribute () e / ou ActiveRecord # attribute_names ().
mbreining
Impressionante! api.rubyonrails.org/classes/ActiveRecord/…
mhenrixon 8/11
5
module One
  module Two
    class Three
      def say_hi
        puts "say hi"
      end
    end
  end
end

one = Object.const_get "One"

puts one.class # => Module

three = One::Two.const_get "Three"

puts three.class # => Class

three.new.say_hi # => "say hi"

Em Ruby 2.0 e, lançamentos possivelmente mais cedo, Object.const_getvai recursiva executar uma pesquisa em um namespaces como Foo::Bar. O exemplo acima é quando o espaço para nome é conhecido antecipadamente e destaca o fato de que const_getpode ser chamado diretamente nos módulos, e não exclusivamente Object.

A-Dubb
fonte
Você deve adicionar uma explicação para isso. A partir de agora, é apenas um bloco de código.
precisa