Ruby GData API, Google Calendar, and redirects

6
May/10
0

The Ruby GData API provides for accessing a number of Google data sources: Google Apps, Analytics, YouTube, you name it (http://code.google.com/apis/gdata/docs/directory.html).

When you access a Google Calendar that is managed through a Google Apps username (e.g., you@example.com, as opposed to you@gmail.com), the standard lookup feed (example: http://www.google.com/calendar/feeds/default/owncalendars/full) redirects after you access it. (Not the case for calendars owned by gmail.com addresses, it would seem.)

Well, bizarrely, in the Ruby implementation (which you can find here: http://code.google.com/p/gdata-ruby-util/ Ruby 1.9 version here: http://code.google.com/u/hoanga/), redirects are not handled properly.

Handling a redirect is a “must have” to get into the Calendar data for a Google Apps user.

The master code repository is hosted on code.google.com, so since it doesn’t provide for submitting patches as easily as Github, I’ll just lob a monkeypatch fix here . . .


# Fix for GData::Client::Calendar failure to follow redirects
module GData
  module Client
    class Calendar
      def make_request(method, url, body = '', retries = 4)
        response = super(method, url, body)
        if response.status_code == 302 and retries > 0
          @session_cookie = response.headers['set-cookie']
          # original wasn't capturing the redirect location
          redirect_url = response.headers['location']
          return self.make_request(method, redirect_url, body, retries - 1)
        else
          return response
        end
      end
    end
  end
end

For Rails, you can put this into a file in config/initializers

Filed under: Code

Default params for POST in HTTParty

5
May/10
1

So I was looking at the API for ping.fm (http://groups.google.com/group/pingfm-developers/web/api-documentation?_done=%2Fgroup%2Fpingfm-developers%3F), and thought: Ah, this would be easy to wrap with HTTParty (http://github.com/jnunemaker/httparty).

For ping.fm, all requests must be POSTs, and each request much include a couple of keys. But in HTTParty, you can’t specify default params that should be used every time for POST.

So I fixed that. See below. I’m too lazy to fork, add my code, write tests, and create a pull request, so I’ll just have it here for posterity.

Then I realized that there is probably a gem for ping.fm — and there is! So I won’t be using HTTParty after all!

But here’s the code. For a Rails app, just put this in a file in config/initializers.


# Provide means for HTTParty to allow for default body parameters
module HTTParty
  module ClassMethods
    def default_body_params(h={})
      raise ArgumentError, 'Default body params must be a hash' unless h.is_a?(Hash)
      default_options[:default_body_params] ||= {}
      default_options[:default_body_params].merge!(h)
    end
  end
  class Request
    def body
      if options[:default_body_params]
        if options[:body]
          if options[:body].is_a?(Hash)
            options[:body] = options[:default_body_params].merge(options[:body])
          end
        else
          options[:body] = options[:default_body_params]
        end
      end
      # original:
      options[:body].is_a?(Hash) ? options[:body].to_params : options[:body]
    end
  end
end
Filed under: Code

If you must rescue Exception . . .

29
Oct/09
0

Sometimes you see Ruby code that rescue an exception at the top of the hierarchy:


rescue Exception => e

If you must do that, how about providing a means to control-C, by putting this in the method with the rescue:


trap("INT") do
  puts "Terminating . . . "
 return # or maybe exit
end
Filed under: Code, Ruby

How to embed JRuby 1.9 into a Java class

20
Aug/09
0

It took awhile longer to figure this out than I would have liked, due to no on-line JavaDocs for JRuby (what’s up with that!?).

But here’s how to embed JRuby 1.9 into a Java class:


import org.jruby.Ruby;
import org.jruby.RubyRuntimeAdapter;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.RubyInstanceConfig;
import org.jruby.CompatVersion;

import java.util.ArrayList;

public class JRubyEmbedded {
  public static void main(String[] args) {
    RubyInstanceConfig ric = new RubyInstanceConfig();
    ric.setCompatVersion(CompatVersion.RUBY1_9);
    Ruby ruby = JavaEmbedUtils.initialize(new ArrayList(), ric);
    RubyRuntimeAdapter rra = JavaEmbedUtils.newRuntimeAdapter();

    System.out.println(rra.eval(ruby, "\"Ruby #{RUBY_VERSION}\""));

    JavaEmbedUtils.terminate(ruby);
  }
}
Filed under: Code

Teaching Ruby and Ruby on Rails again at Harvard

7
Aug/08
0

Once again, I’m pleased to be offering a course on Ruby and Ruby on Rails at Harvard: course; course site.

We’ll try to avoid this anti-pattern:

Ruby: eval, rescue, and Exception

7
Jun/08
0

Recently I needed to store bits of Ruby code in the database, and then evaluate them in the context of a particular instance. But one thing I flubbed up was the handling of exceptions. You see, in this situation, if you have bad Ruby code, you will likely raise an exception. My first attempt was, roughly, this code (wrong!):


begin
  eval s
rescue
  # log the fact that s couldn't be eval'ed
end

The catch is that when you use rescue without specify an exception, you are only catching StandardError or one of its subclasses. But eval will raise a SyntaxError (or worse), which is a subclass of ScriptError, which is not a subclass of StandardError. Therefore, you want to rescue an Exception that is further up the hierarchy. In short, better:


begin
  eval s
rescue Exception => e
  # log the fact that s couldn't be eval'ed
end

Nick Sieger provides a post with the Ruby Exception hierarchy, along with some code to generate it dynamically. Too bad this info isn’t in the on-line Pickaxe (http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_exceptions.html).

Filed under: Code, Ruby