Wave Robot Ruby Client
Wanting to learn more about Google Wave, I ported the Wave Robot Python Client library to Ruby, mainly because I wanted to understand the protocol. The current protocol is tightly coupled to the Java server implementation.
>>> import waveapi.document
>>> import waveapi.util
>>> waveapi.util.Serialize([waveapi.document.Image('http://example.com/foo.jpg', width=100, height=100)])
{'javaClass': 'java.util.ArrayList', 'list': [{'type': 'IMAGE', 'properties': {'javaClass': 'java.util.HashMap', 'map': {'url': 'http://example.com/foo.jpg', 'width': 100, 'height': 100}}, 'java_class': 'com.google.wave.api.Image'}]}
In addition to being littered with javaClass names and requiring 5 levels of nesting to represent an array of a single Image, this serialization is not strictly JSON as it uses single quotes, something that the builtin library for Ruby chokes on:
$ irb
irb(main):001:0> require 'rubygems'
=> true
irb(main):002:0> require 'json'
=> true
irb(main):003:0> JSON.parse('["foo"]')
=> ["foo"]
irb(main):004:0> JSON.parse("['foo']")
JSON::ParserError: 349: unexpected token at ''foo']'
But, in any case, the Ruby implementation can now match the function:
$ irb
irb(main):001:0> require 'document'
=> true
irb(main):002:0> Util.Serialize([Image.new('http://example.com/foo.jpg', :width=>100, :height=>100)])
=> {"list"=>[{"java_class"=>"com.google.wave.api.Image", "type"=>"IMAGE", "properties"=>{"javaClass"=>"java.util.HashMap", "map"=>{"url"=>"http://example.com/foo.jpg", "height"=>100, "width"=>100}} }], "javaClass"=>"java.util.ArrayList"}
Other than the use of double quotes and the ordering of Hash keys, these results match.
Additional notes, in no particular order:
- instead of creating a new Range class, I used the one built in to Ruby. I believe that a similar approach should have been used for Python.
- source code contains a typo “last_modifed_time”.
- the API feels distinctly un-Ruby-like. Method names like
GetIDshould be simplyid. - I couldn’t tell if the module structure was Python imposed or intended. I changed my mind a few times during this quick port, and this needs to be cleaned up.
- there is an attempt to assign to
wave_idinside ofWaveData. I believe that this should simply beid - there is a class by the name of
_ContextImpl. I moved the underscore to the end because Ruby doesn’t allow classes to be named this way. - many classes have an property named
type. This is a PITA in Ruby as there is an existing (and deprecated) attribute by this name. - for now,
_,__, andInitialCapsfor functions implemented as defacto naming conventions
Overall, I feel that this Google Wave could benefit from earlier and wider reviews. In particular, the whole approach to JSON generation should be rethought. I look forward to testing interop with a live server, in particular one that I can self host.