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
GetID
should 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_id
inside 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,
_
,__
, andInitialCaps
for 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.