views:

155

answers:

1

I am new to Ruby, and have a gem that I am making to interact with a JSONRPC API and basically all calls and responses are similar enough, that every API call can be handled with one function, like:

Module::api_command('APINamespace.NamespaceMethod')

but I would like to also (for convenience sake) be able to do:

Module::APINamespace.NamespaceMethod

Is there any reason not to do this by using Module.const_missing to return a dummy class that has a method_missing which will allow passing the call from Module::APINamespace.NamespaceMethod to Module::api_command('APINamespace.NamespaceMethod')

Is there a more elegant or civilized way to do this?

+1  A: 

Yes, I'm sorry, but to my mind that hack is ridiculous. :)

First of all, i'm assuming that your api_command method is actually invoking methods on the APINamespace module, as implied by this line: Module::api_command('APINamespace.NamespaceMethod')

Given the above, why not just set a constant equal to APINamespace in your module?

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

UPDATE:

I'm still not entirely understanding your situation, but perhaps this:

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

Now you can invoke any top-level constant as if it was defined on your module; say there was a module called StrangeAPI at top-level, if you use the hack above, you can now invoke its methods as follows:

MyModule::StrangeAPI.Blah()

Is this what you want?

banister
I figured it was a pretty goofy, way of doing it, which is why i posted the question :p. I am not sure i understand the = ::APINamespace assignment, whats going on there?
re5et
@re5et, if i understood what you're doing correctly -- there actually exists a module called `APINamespace` that holds the methods you want to invoke...but you are currently invoking them through `MyModule.api_command()`. My solution just binds a constant called `MyModule::APINamespace` to the global `APINamespace` constant...enabling you to directly invoke the `ApiNamespace` methods from within your module by going `MyModule::APINamespace.NameSpaceMethod()`
banister
the problem is there are a bunch of namespaces, which all have their own methods. I was wondering if there was something I could do other than defining them each as a constant in the module.
re5et
@re5et, i updated my answer to reflect your recent comment
banister