[Ruby] Définition de classe dynamique AVEC un nom de classe



Answers

J'ai aussi joué avec ça. Dans mon cas, j'essayais de tester les extensions à ActiveRecord :: Base. J'avais besoin de pouvoir créer dynamiquement une classe, et parce que l'enregistrement actif recherche une table basée sur un nom de classe, cette classe ne peut pas être anonyme.

Je ne suis pas sûr que cela aide votre cas, mais voici ce que j'ai trouvé:

test_model_class = Class.new(ActiveRecord::Base) do
  def self.name
    'TestModel'
  end

  attr_accessible :foo, :bar
end

En ce qui concerne ActiveRecord, définir self.name était suffisant. Je suppose que cela fonctionnera dans tous les cas où une classe ne peut pas être anonyme.

(Je viens juste de lire la réponse de sepp2k et je pense que c'est mieux, je vais laisser ça de toute façon.)

Question

Comment définir dynamiquement une classe dans Ruby avec un nom?

Je sais créer une classe dynamiquement sans nom en utilisant quelque chose comme:

dynamic_class = Class.new do
  def method1
  end
end

Mais vous ne pouvez pas spécifier un nom de classe. Je veux créer une classe dynamiquement avec un nom.

Voici un exemple de ce que je veux faire, mais bien sûr, cela ne fonctionne pas vraiment.
(Notez que je ne crée pas une instance d'une classe mais une définition de classe)

class TestEval
  def method1
    puts "name: #{self.name}"
  end
end

class_name = "TestEval"
dummy = eval("#{class_name}")

puts "dummy: #{dummy}"

dynamic_name = "TestEval2"
class_string = """
class #{dynamic_name}
  def method1
  end
end
"""
dummy2 = eval(class_string)
puts "dummy2: #{dummy2}" # doesn't work

Sortie réelle:

dummy: TestEval
dummy2: 

Sortie désirée:

dummy: TestEval
dummy2: TestEval2

============================================= ====

Réponse: Une solution totalement dynamique utilisant la méthode de sepp2k

dynamic_name = "TestEval2"

Object.const_set(dynamic_name, Class.new)
dummy2 = eval("#{dynamic_name}")
puts "dummy2: #{dummy2}"



Que diriez-vous du code suivant:

dynamic_name = "TestEval2"
class_string = """
class #{dynamic_name}
  def method1
  end
end
"""
eval(class_string)
dummy2 = Object.const_get(dynamic_name)
puts "dummy2: #{dummy2}"

Eval ne renvoie pas l'objet Class d'exécution, du moins sur mon PC. Utilisez Object.const_get pour obtenir l'objet Class.






Links