2010/04/12

Ruby on Rails と PostgreSQL

RoR と PostgreSQL の話題はいっぱいありますが、ラージオブジェクトを扱ったものが少ないなぁと。
特に PostgreSQL8.4.x は全然見つかりません。で、仕方なく8.3でやっつけています。

以下、覚書。

>ruby -v
ruby 1.8.6 (2007-09-24 patchlevel 111) [i386-mswin32]

>rails -v
Rails 2.3.5

>gem list --local
:
ruby-postgres (0.7.1.2006.04.06)
:

>psql --version
psql (PostgreSQL) 8.3.10

この組み合わせだと、以下のような感じでラージオブジェクトを扱うことができます。

モデルの中で

def uploaded_picture_01=(picture_field)
@tmp_picture = picture_field
if @tmp_picture.original_filename != ""
@tmp_filename_01 = "#{RAILS_ROOT}/public/tmp/#{@tmp_picture.original_filename}"
File.open(@tmp_filename_01, "wb") do |f|
f.write(@tmp_picture.read)
end
@skip_upload_01 = false
else
@skip_upload_01 = true
end
end

def before_save
if @skip_upload_01 == false
conn = connection.raw_connection

# 古いイメージの削除
if self.image_field?
conn.exec("BEGIN")
conn.lounlink(self.image_field.to_i)
conn.exec("END")
end

# 新しいイメージの登録
conn.exec("BEGIN")
@tmp_lo = conn.loimport(@tmp_filename_01)
conn.exec("END")
self.image_field = @tmp_lo.oid
end
end

コントローラで

def show_image
base_x = 640.0
base_y = 480.0
ii = params[:id].to_i
if ii > 0
begin
conn = ActiveRecord::Base.connection.raw_connection

conn.exec("BEGIN")
@tmp_lo = conn.loopen(ii)

img = Magick::Image.from_blob(@tmp_lo.read).shift
new_img = img.resize_to_fit(params[:w], params[:h])
send_data(new_img.to_blob, :disposition => "inline", :type => "image/jpeg")

conn.exec("END")
rescue
end
else
end
end

引数には表示させたいイメージの oid を渡します。

PostgreSQL8.3.x ではこれでうまく動いているのですが、8.4.x にしたとたんに動かなくなります。
まず、gem の ruby-postgres が 8.4.x には対応していないようで WEBrick の起動時点でこけてしまいます。これを回避するために別の gem を入れたのですが、ラージオブジェクトの表示の部分で引っかかってしまいました。登録はできるんですが、表示の部分のロジックがうまいこと走りません。

一日かけてあれこれいじってみたのですが諦めて 8.3.x に戻してしまいました。

でも、いずれは 8.4.x に対応しないといけないので、調査継続ということでお茶を濁します。