2010-09-27 24 views
5

Soy nuevo en Ruby, y tienen una joya que estoy haciendo para interactuar con un API JSONRPC y, básicamente, todas las llamadas y las respuestas son tan similares, que cada llamada a la API se puede manejar con una sola función, como:¿Este abuso de la metaprogramación de ruby?

Module::api_command('APINamespace.NamespaceMethod')

pero me gustaría también (por conveniencia) ser capaz de hacer:

Module::APINamespace.NamespaceMethod

¿hay alguna razón para no hacer esto mediante el uso de Module.const_missing para devolver una clase ficticia que tiene una method_missing que permitirá passin g la llamada de Module::APINamespace.NamespaceMethod a Module::api_command('APINamespace.NamespaceMethod')

¿Hay alguna manera más elegante o civilizada de hacer esto?

+0

¿bien? ¿mi respuesta hizo lo que querías? Todavía no he tenido noticias tuyas. – horseyguy

Respuesta

2

Sí, lo siento, pero en mi opinión ese hackeo es ridículo. :)

En primer lugar, estoy asumiendo que su método es en realidad api_command invocando métodos en el módulo APINamespace, como se deduce de esta línea: Module::api_command('APINamespace.NamespaceMethod')

Teniendo en cuenta lo anterior, ¿por qué no acaba de establecer una constante igual a APINamespace en su módulo?

MyModule::APINamespace = ::APINamespace 
MyModule::APINamespace.NamespaceMethod() 

ACTUALIZACIÓN:

Todavía no estoy del todo la comprensión de su situación, pero tal vez esto:

module MyModule 
    def self.const_missing(c) 
     Object.const_get(c) 
    end 
end 

Ahora se puede invocar ninguna de alto nivel constante como si se definió en tu módulo; decir que no hubo un módulo llamado StrangeAPI al más alto nivel, si se utiliza el truco anterior, ahora se puede invocar sus métodos de la siguiente manera:

MyModule::StrangeAPI.Blah() 

¿Es esto lo que quieres?

+0

Pensé que era una forma bastante tonta de hacerlo, por eso publiqué la pregunta: p. No estoy seguro de entender la asignación = :: APINamespace, ¿qué está pasando allí? – re5et

+0

@ re5et, si entendí lo que está haciendo correctamente, en realidad existe un módulo llamado 'APINamespace' que contiene los métodos que desea invocar ... pero actualmente los está invocando a través de' MyModule.api_command() '. Mi solución solo une una constante llamada 'MyModule :: APINamespace' a la constante global' APINamespace' ... que le permite invocar directamente los métodos 'ApiNamespace' desde su módulo yendo' MyModule :: APINamespace.NameSpaceMethod() ' – horseyguy

+0

el problema es que hay un montón de espacios de nombres, que tienen sus propios métodos. Me preguntaba si había algo que pudiera hacer aparte de definirlos como una constante en el módulo. – re5et

Cuestiones relacionadas