Come creo un'istanza di classe da un nome di stringa in ruby?


121

Ho il nome di una classe e desidero creare un'istanza di quella classe in modo da poter scorrere ogni attributo rails presente nello schema di quella classe.

Come potrei farlo?

  1. Ho il nome come stringa della classe che voglio controllare
  2. Immagino di dover creare un'istanza di una classe in modo da poterlo fare
  3. Scorri i suoi attributi e stampali.

1
Questa è un'ottima domanda. Grazie per averlo chiesto e per avermi salvato dall'utilizzoeval
David West,

Risposte:


219

In rails puoi semplicemente fare:

clazz = 'ExampleClass'.constantize

In rubino puro:

clazz = Object.const_get('ExampleClass')

con moduli:

module Foo
  class Bar
  end
end

useresti

> clazz = 'Foo::Bar'.split('::').inject(Object) {|o,c| o.const_get c}
  => Foo::Bar 
> clazz.new
  => #<Foo::Bar:0x0000010110a4f8> 

4
Nota che Object.const_get('Foo::Bar')non funzionerà, mentre lo constantizefarà.
Marc-André Lafortune

Grazie, mi sono svegliato per chiedere informazioni a causa di un problema di Admin :: User :) Battimi.
mhenrixon

Hey @Wes, è stato utile, grazie! Domanda veloce: funzionerebbe anche per i moduli nidificati? Ad esempio,clazz = 'Foo::Bar::Uber'
iaacp

@iaacp Sì, funzionerà per tutti i livelli nidificati che hai.
Mercoledì


6

Prova questo:

Kernel.const_get("MyClass").new

Quindi per scorrere le variabili di istanza di un oggetto:

obj.instance_variables.each do |v|
  # do something
end

Grazie, poiché devo davvero scorrere le colonne del modello di record attivo, questo non funzionerà per me ma sarà utile nelle mie app ruby ​​"pure" :)
mhenrixon

1
Controlla ActiveRecord # attributes () e / o ActiveRecord # attribute_names ().
mbreining


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"

In ruby 2.0 e, possibilmente release precedenti, Object.const_getsarà ricorsivamente eseguire una ricerca su un namespace come Foo::Bar. L'esempio sopra è quando lo spazio dei nomi è noto in anticipo ed evidenzia il fatto che const_getpuò essere chiamato direttamente sui moduli anziché esclusivamente su Object.


Dovresti aggiungere una spiegazione a questo. A partire da ora, è solo un blocco di codice.
Josh Crozier
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.