If you’re looking to make use of the Amazon Web Services through your Rails app, here’s a tip: avoid trying to communicate with them using the Ruby on Rails ActiveWebServices classes. I spent a couple hours trying to patch together a solution, but nothing would work. I believe what currently exists is geared towards making your Rails app accessible through Soap or XMLRPC, rather than consuming exisiting web services.
Instead, use Ruby/Amazon, a “Ruby language library that allows programmatic access to the popular Amazon Web site via the REST (XML over HTTP) based Amazon Web Services.” Installation of the library on my development box was a breeze (just read the installation document to learn how) and, plus, it’s already preinstalled on the servers at TextDrive, so getting going using the Ruby/Amazon library is not a problem at all. For a quick tutorial on how to use the library, check out the documentation on the top-level Amazon module or read this entry on the GleepGlop blog. Both contain examples that show you how to make a basic connection to Amazon through the web services and how to query for products.
Once you get this far, though, you’ll realize that making calls to the Amazon Web Services with every page view is going to decrease the speed at which your website will render for your users. So what can you do instead? Cache the results in your database, that’s what. On my lyrics website, I want to have links back to Amazon for every artist that I have lyrics for. So, what I did was create an administrative function that will connect to Amazon and return a list of items for a given artist. This process is repeated over and over so that I have a huge archive of products for each of the artists. Then, instead of querying Amazon with each page view, I just need to call this administrative function every month or so, to update the products in my database.
Below, you’ll see a body of code that updates all products for all artists whose names begin with a particular letter (for example, “A”). For each artist, all existing products are deleted from the database. Then, a new list of products is retrieved and each product is added to the database.
amazon_controller.rb
require 'amazon/search'
class AmazonController < AdminController
   include Amazon::Search
   ASSOCIATES_ID = "amazonaffiliateid-20" # Your Amazon Affiliate ID
   DEV_TOKEN = "0222NLPJQD0A7633Q182" # Your Amazon Web Services Key
   def update
      artists = Artist.find_by_first_letter(@params["letter"])
      artists.each do |artist|
         # Delete all existing "out-dated" products
         existing_products = Product.find_all_by_artist_id(artist.id)
         existing_products.each do |existing_product|
            existing_product.destroy
         end
         # Query Amazon
         request = Request.new(DEV_TOKEN, ASSOCIATES_ID)
         response = request.artist_search(artist.artist_name)
         products = response.products
         # Loop over each product and add them to the database, one at a time
         products.each do |product|
            new_product = Product.new
            new_product.artist_id = artist.id
            new_product.product_name = product.product_name
            new_product.url = product.url
            new_product.image_url_small = product.image_url_small
            new_product.image_url_medium = product.image_url_medium
            new_product.image_url_large= product.image_url_large
            new_product.save
            new_product = nil
         end
      end
      redirect_to(:controller =< "admin", :action => "index") # Return to the list page if it suceeds
   end
end
What I’d like to do now is to have a Ruby script run nightly that updates a portion of the products in the database. For example, at midnight on the first day of each month, all artists whose names begin with A would have their products updated from Amazon. At midnight on day two, all B artists would have their products updated. I just have to figure out how to do this… but once I do, I’ll post it here.