From: Matthew Smillie Date: 2005-12-06T12:50:54+09:00 Subject: Re: Are my metaprogramming underpants showing? ---- Matthew Smillie Institute for Communicating and Collaborative Systems University of Edinburgh On Dec 6, 2005, at 2:37, Trans wrote: > The whole class as method thing seems very odd.n I suspect there's a > better way. But I'm not sure what you're trying to do exactly (the > link > to the Fliker API didn't work btw) > > T. Gah. Serves me right for doing this late at night. Here is the fixed link: http://flickr.com/services/api/ Do you mind if I ask how you find it odd? Or what you might do otherwise? Here is, hopefully, a fuller explanation: The reasoning was like this. I wanted the Ruby method calls to look just like they're defined in the api (modulus the parameters), so like this: flickr.test.echo({"api_key" => "..."}) The catch is that in Ruby, that's a calling 'echo' on 'flickr.test', and so the 'echo' there needs to somehow know what the name of the entire method (flickr.test.echo) is. The point of the exercise for me was to avoid defining each and every API method specifically, so I needed a way encode the entire API method name into that 'echo', and the class heirarchy seemed like a reasonable fit: - simpler than tracing callers So when a the above call is made, this happens: - flickr object create a Flickr::Test class, and an instance of it in @test - flickr.test creates a Flickr::Test::Echo class, and an instance of it in @echo, and then calls Flickr::Test::Echo#request - #request extracts the flickr API method name (flickr.test.echo) by downcasing the first letter of each element in the class name (the case-mangling was necessary since Ruby classnames are constants). The first and simplest thing I did was to use method_missing just to dynamically construct the API method name by concatenating the method_id's in #method_missing and returning self. This worked, but didn't leave open much flexibility for adding, well, much of anything. Another alternative I considered was instead of using instances of the classes, was just to instead create a class method with analogous behaviour (e.g. Flickr.test would create Flickr::Test, etc), but that meant treating the Flickr class differently from the other classes, since it would need to be instantiated to match the "flickr = Flickr.new" intuition as well as the 'flickr.x.y" requirement. Seemed better to do it all at once. thanks once again, matthew smillie.