Jak utworzyć instancję klasy na podstawie nazwy ciągu w języku Ruby?


121

Mam nazwę klasy i chcę utworzyć wystąpienie tej klasy, aby móc przechodzić przez każdy atrybut rails obecny w schemacie tej klasy.

Jak bym to zrobił?

  1. Mam nazwę jako ciąg klasy, którą chcę sprawdzić
  2. Wydaje mi się, że muszę utworzyć instancję klasy, aby móc
  3. Przejrzyj jego atrybuty i wydrukuj je.

1
To świetne pytanie. Dzięki za pytanie i uratowanie mnie przed używaniemeval
David West,

Odpowiedzi:


219

W szynach możesz po prostu zrobić:

clazz = 'ExampleClass'.constantize

W czystym rubinie:

clazz = Object.const_get('ExampleClass')

z modułami:

module Foo
  class Bar
  end
end

użyłbyś

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

4
Zauważ, że Object.const_get('Foo::Bar')to nie zadziała, a constantizebędzie.
Marc-André Lafortune

Dzięki, obudziłem się, żeby o to zapytać z powodu problemu z Admin :: User :) Pobij mnie.
mhenrixon

Hej @Wes, to było pomocne, dzięki! Szybkie pytanie - czy to zadziała również w przypadku modułów zagnieżdżonych? Na przykładclazz = 'Foo::Bar::Uber'
iaacp

@iaacp Tak, będzie działać na tylu zagnieżdżonych poziomach, ile masz.
Wes


6

Spróbuj tego:

Kernel.const_get("MyClass").new

Następnie, aby przejść przez zmienne instancji obiektu:

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

Dziękuję, ponieważ naprawdę muszę przeglądać kolumny modelu aktywnego rekordu, to nie zadziała dla mnie, ale przyda się w moich „czystych” aplikacjach rubinowych :)
mhenrixon

1
Sprawdź ActiveRecord # attribute () i / lub ActiveRecord # attribute_names ().
żerowanie


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"

W Ruby 2.0 i prawdopodobnie we wcześniejszych wersjach Object.const_getbędzie rekurencyjnie wyszukiwać przestrzenie nazw, takie jak Foo::Bar. Powyższy przykład dotyczy sytuacji, w których przestrzeń nazw jest znana z wyprzedzeniem i podkreśla fakt, że const_getmożna ją wywoływać bezpośrednio w modułach, a nie wyłącznie na Object.


Powinieneś dodać do tego wyjaśnienie. Na razie jest to tylko blok kodu.
Josh Crozier,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.