I’ve been playing with Google Wave recently and enjoying the challenge of making a robot for the platform.  My challenge is to create a robot that looks for “Q:” and “A:” markup and submits questions and answers to a flash card service such as FlashCardDB.com so that my Inuversity study group can use spaced repetition to optimize our study sessions.

Because the Google Wave team first released a Python version of their robot api, I started work on the project from that direction.  Unfortunately, Python’s “mechanize” library is not as well developed as I would like to see it.  For example, among other difficulties, the ClientForm library that it depends on was unable to parse the login form at flashcarddb.com.  In addition, due to the limitation that Python’s mechanize library does not easily allow me to simulate an XmlHTTPRequest, I finally gave up on that approach.  Since Ruby’s Mechanize library is in much better shape, I thought it might be an option.

Since I am familiar with Ruby, I searched for possible Ruby/Wave solutions and discovered the 3 main contenders (Rave, Robot Sinatra Template and Wave Robot Ruby Client).  I chose Rave because of its “package” feel: The author, Jason Rush, has worked to make each step easy from configuration, to development, to deployment.  For example, building the Java WAR file is a simple “jruby -S rave war” command, and configuration is as simple as filling out a yaml file.

I followed the directions at Jason’s introductory post about Rave and quickly deployed my first “bot” using jruby and the Rack+Rave framework.  Unfortunately, I soon realized that version 0.1.1 of Rave which has been released to the world does not support robot versioning!  That meant that I could not increment the version number of my software to indicate that I had made changes.  The robot was stuck at version 1.0.

This problem was solved by Jason and other contributors in the latest source code.  As of this writing, it’s not packaged as a gem yet–so I went to his git repository to get the latest.

One gotcha: since upgrading from 0.1.1 to 0.1.2, the rackup file (config.ru) has changed.  I received this cryptic error which indicates I needed to change the line in config.ru from “run Remembry::Robot.new(:name => ‘remembry’)” to ”run Remembry::Robot.instance”.

javax.servlet.ServletContext log: unable to create shared application instance
org.jruby.rack.RackInitializationException: private method `new’ called for RemembryRave::Robot:Class
from /base/data/home/apps/remembry/1.339256739153417236/WEB-INF/gems/gems/rack-1.1.0/lib/rack/builder.rb:46:in `initialize’

Also, I tried using an integer number to version my robot, but integers don’t work (use a string, such as ‘12′ instead of 12):

sun.reflect.NativeMethodAccessorImpl invoke0: TypeError: can’t dup Fixnum
/base/data/home/apps/remembry/1.339257167247162572/WEB-INF/gems/gems/rave-0.1.2-java/lib/models/robot.rb:16:in `version’

In addition, it used to be that the packaged gems were configured in the Warbler::Config block in config/warbler.rb, like this:

Warbler::Config.new do |config|
  config.gems = %w( rave json-jruby rack builder hpricot )
  config.includes = %w( robot.rb appengine-web.xml )
end

But it appears that the new config.yaml file is the place to put gems and other configuration:

robot:
  name: Remembry Bot
  image_url:
  version: ‘9′
appcfg:
  version: 1
gems:
  - hpricot

And finally, in order to accomplish my task, I needed to use Ruby’s Mechanize library but because the latest version of Mechanize depends on Nokogiri which in turn depends on Ruby’s Foreign Function Interface (FFI), I had to downgrade from Mechanize 0.9.3 to 0.8.5.  According to this google forum, FFI will never be supported in App Engine.

More details on this project to come later!

Posted via email from Duane’s Quick Posts