2011-07-17 2 views
2

Cela peut sembler déroutant, mais je travaille avec une petite équipe de nouveaux arrivants, et j'essaie de faire abstraction de certaines choses dans ruby ​​pour que tout se passe bien. La partie avec laquelle j'ai des problèmes est celle des espaces de noms.Comment faire pour exécuter un Proc dans un module généré dynamiquement?

Fondamentalement, avec des espaces de noms rubis peuvent être créés:

module EIF 
    module Core 
    module Entities 
    #stuff 
    end 
    end 
end 

ou

module EIF 
end 

module EIF::Core 
end 

module EIF::Core::Entities 
#some stuff 
end 

La chose est, c'est honnêtement encombrant. Je voulais quelque chose qui s'apparente à C# où vous définissez simplement l'espace de noms comme:

namespace EIF.Core.Entities 
{ 
    #Some stuff 
} 

Et être fait avec elle. J'ai réussi à obtenir quelque chose de similaire en utilisant eval pour créer les modules (après avoir fait correspondre le nom à une expression régulière)

def namespace(path) 
    if path.match(/^([A-Z][a-zA-Z0-9]*)(::[A-Z][a-zA-Z0-9_]*)*$/) 
    spaces = path.split("::") 
    code = "" 
    spaces.each { |m| code << "module #{m}\n" } 
    spaces.each { code << "end\n" } 
    eval(code) 
    else 
    raise ArgumentError, "'#{path}' is not a valid namespace" 
    end 
end 

Le résultat est que je peux maintenant faire ce qui suit:

namespace "EIF::Core::Entities" 
class EIF::Core::Entities::Attirbute 
    #class code 
end 

vient maintenant l'étape suivante. Je veux utiliser un bloc rubis pour rendre les choses plus faciles à lire, de sorte qu'il ressemblera:

namespace "EIF::Core::Entities" do 
    class Attribute 
    #class code 
    end 
end 

myAttribute = EIF::Core::Entities::Attribute.new 

Le problème est que jusqu'à présent, la seule méthode que j'ai trouvé pour créer les modules sur l'exécution est avec eval et lorsque j'essaie de glisser le bloc de code dans eval, la classe résultante reste dans l'espace de noms racine. J'ai essayé instance_eval, module_eval, et class_eval, et aucun ne crée la classe dans les modules pour une raison quelconque.

De toute façon je peux le faire? Je détesterais abandonner maintenant.

+2

Pourquoi sur __earth__ voudriez-vous faire quelque chose comme ça? Il est préférable pour vos coéquipiers inexpérimentés d'apprendre les constructions __ruby__ réelles et non quelques obscènes additions syntaxiques que vous voulez créer. –

+0

Parce que c'est amusant: D Oh, et d'ailleurs, c'est un projet de passe-temps. Le code n'est pas destiné à être réutilisable, et ces gens ne sont pas des programmeurs pour commencer (encore). Je voulais simplifier certaines choses en utilisant DSL – elite5472

+2

Non, alourdir vos nouveaux arrivants en leur faisant apprendre pas-assez-Ruby n'est pas amusant et celui qui reste bloqué en maintenant votre code vous détestera. Est-ce que votre code C a '#define BEGIN {' et '#define END}' aussi? –

Répondre

2

Terminé.

Il semble que lorsque vous ajoutez une classe à l'aide module_eval, comme dans:

My::Namespace.module_eval do 
    class MyClass 
    end 
end 

L'espace de noms pour MyClass est résolu à :: quel que soit le contexte. Cependant, en écrivant:

class self::MyClass 

L'espace de noms est résolu à l'objet de l'espace de noms en cours, ainsi la définition de la classe résultante sera dans mon :: Espace de noms

Je ne sais pas pourquoi cela se produit, mais au moins J'ai quelque chose qui marche. Maintenant, le problème est que, bien que cela soit plus court, le mot self est contre-intuitif.

Questions connexes