Search code examples
ruby-on-railsamazon-web-servicesamazon-simpledbnon-relational-database

SimpleDB to ActiveResource. Rails


Im looking for a way to map an ActiveResource to SimpleDB

I want to avoid plugins/gems as all I have used are outdated/buggy/not mantained

It doesnt seem hard, I wonder if any of you have succesfully implemented a rails app with simpleDB as an Active Resource. How did you do it? Thanks.


Solution

  • I haven't worked with SimpleDB, but I have mapped ActiveResource to Amazon's Flexible Payments Service REST api and just skimming the docs they seem similar so here's basically what I did, maybe you can use this as a starting point.

    require 'base64'
    require 'openssl'
    
    class AmazonFlexiblePaymentResource < ActiveResource::Base
      self.site = AMZ_CONFIG['flexible_api_url']
    
      def self.rest_api(options = {})
        params = common_request_params.update(options)
    
        sig = compute_signature(AMZ_CONFIG['secret_access_key'], 'get', site, params)
    
        rest_req = {'Signature' => sig}.update(params)
    
        # make the http get call
        connection.get("/#{query_string(rest_req)}", headers)
      end
    
      protected
    
      # these are the params are common to all rest api calls
      def self.common_request_params
        { 'AWSAccessKeyId' => AMZ_CONFIG['access_key_id'],
          'SignatureVersion' => 2,
          'SignatureMethod' => 'HmacSHA256',
          'Timestamp' => Time.now.utc.iso8601,
          'Version' => '2008-09-17'}
      end
    
      def self.compute_signature(key, method, end_point_url, params)
        query_str = parameters.sort.collect {|k, v| v.to_query(k)}.join '&'
    
        # cannot use plus for space, and tilde needs to be reversed
        query_str.gsub!('+', '%20')
        query_str.gsub!('%7E', '~')
    
        to_sign = [method.upcase, end_point_uri.host.downcase,
            end_point_uri.request_uri, query_str].join "\n"
    
        digest = OpenSSL::Digest::Digest.new('sha256')
        hmac = OpenSSL::HMAC.digest(digest, key, to_sign)
        Base64.encode64(hmac).chomp
      end
    end
    

    Then I just make calls like this

    res = AmazonFlexiblePaymentResource.rest_api({ 'Action' => 'GetTransactionStatus', 'TransactionId' => '1234567890ABCDEFGHIJ' })
    

    And the response is a hash of the parsed xml. Again this works for Amazon Flexible Payments Service, so you may need to make adjustments to match the SimpleDB REST API.