Amazon WebサービスのレスポンスをActiveRecordでキャッシュ
前回RailsでAmazonのWebサービスを使ってみたけれども、何かあるたびに毎回リクエストを送るのはいろいろ無駄があって忍びないのでレスポンスをキャッシュしなければならない。
ということで今回はActiveRecordを使ってざっくりキャッシュしてみる。
キャッシュテーブルにたくさんカラムを定義するのは面倒なので検索キーにしたいものだけカラムとして定義して、あとは結果をシリアライズして突っ込む方針で。
キャッシュ用のテーブルとモデルを作る
まずはキャッシュするためのテーブルとモデルを準備。
テーブル
とりあえずマイグレーションでテーブルを作る。
class CreateAmazonCaches < ActiveRecord::Migration
def self.up
create_table :amazon_caches do |t|
t.string :asin
t.string :title
t.text :response_dump
t.timestamps
end
end
def self.down
drop_table :amazon_caches
end
end
モデル
キャッシュを参照するためのモデル。
データを参照するときにレスポンスの内容をデシリアライズする。
class AmazonCache < ActiveRecord::Base
@reponse_hash = nil
@search_limit = 10
def get(name)
@response_hash = Marshal.restore(response_dump) if @response_hash.nil?
@response_hash[name.to_sym]
end
def self.search(title, order = 'id', limit = nil)
@search_limit = limit if limit
self.find(:all, :conditions => ["title like ?", "%#{title}%"], :order => order, :limit => @search_limit)
end
end
ハッシュのデシリアライズのタイミングはafter_findでもいいかもしれないなぁ。
キャッシュの保存と参照
テーブルとモデルができたので次はそれを使って実際にキャッシュする。
レスポンスをキャッシュする
以下がレスポンスをキャッシュするためのコード。
get_hashで取得したデータのハッシュだけシリアライズして突っ込む。
(itemのままだとなにやらうまいことMarshalでシリアライズできなかった)
res = Amazon::Ecs.item_search("Rails", :response_group => 'Large')
res.items.each do |item|
AmazonCache.create(:asin => item.get('asin'), :title => item.get('title'), :response_dump => Marshal.dump(item.get_hash))
end
キャッシュを参照する
参照は以下のように。
items = AmazonCache.search("Rails")
items.first.get(:title) # => Railsの何かの本とかそんなタイトル
smallimageのように子要素を持つ要素はXMLの断片が保存されている。
items.first.get(:smallimage) # => "<url>http://ecx.images-amazon.com/images/I/hogehogehoge-.jpg</url><height units=\"pixels\">75</height><width units=\"pixels\">58</width>"
これは正規表現とかで値を取り出すのが楽かね。
モデルにそれ用のメソッドを追加してしまってもいいかもしれない。
まあひとまず今回はこんなところで。