読者です 読者をやめる 読者になる 読者になる

黒魔法使いの弟子

Ruby & Javascript & Hack

Amazon S3@Tokyo RegionでPaperclipを使う

f:id:kattton:20110719111354j:image


[追記: 2012/1/19] aws-s3ではなくaws-sdkを使用する仕様に変更されたようなので、ご注意ください。


以前も書きましたが、Ruby on Rails で画像などをアップロードするときにお世話になるGemが「Paperclip」といいます。


結論から先に言うと、Paperclipを修正してAmazon S3@tokyoを使いやすくしたので紹介します。
よって、Paperclipの基本的な使用方法などは説明していませんので、後述のリンクを辿っていただければと思います。

AmazonS3@tokyoを使おうと思ったらエラーがでます


最近、Amazon S3 を使い始めて、東京にもあるということで、「近いほうがいいだろう」という安直な理由で使うことにしたのですが、普通にやろうとするとエラーが続出なんですね。

The bucket you are attempting to access must be addressed using the specified endpoint. Please send all future requests to this endpoint.


それで、いろいろ調べてみたのですが、Amazon S3 の東京リージョンに限らず、デフォルト(US)以外のS3を使うのはちょっと面倒らしいのですね。


AmazonS3(Tokyo region) + Paperclip + Rails3を使ってみた


本体に修正が無いあたり、あまり需要がないのかなぁと思っていたけど、そのままだと自分が困るので、私の都合の良いように修正して、pull request 送ったら、紆余曲折ありつつ、無事にマージされたので使い方をさくっと紹介します。


(Photo via konishiroku_)

なぜエラーがでるの?

(答え)リージョンによってホスト名が異なるから。


詳細は、こちらで解説されてます。


Amazon S3 の標準はUSなのですが、それ以外を使う場合はホスト名がそれぞれ異なります。

  • US Standard * s3.amazonaws.com
  • US-West (Northern California) Region s3-us-west-1.amazonaws.com
  • EU (Ireland) Region s3-eu-west-1.amazonaws.com
  • Asia Pacific (Singapore) Region s3-ap-southeast-1.amazonaws.com
  • Asia Pacific (Tokyo) Region s3-ap-northeast-1.amazonaws.com

(via Github comment)


なので、 :s3_host_name でそれぞれのホスト名を設定します。

:s3_host_name オプションの使い方


:s3_host_name の設定方法は以下の2通り。

  1. モデルで直接指定する
  2. config/s3.yml などに設定する


私は後者をオススメします。


なぜなら、開発環境と本番環境でのバケットの変更がスマートに書けます
直接モデルにも書くことは出来るのですが、ソースが汚くなるので、私は嫌いですね。

config/s3.yml のサンプル


例えば、開発データは東京リージョンに、本番データは別(s3-us-west-1.amazonaws.com)に、という場合、以下のようにする。

# config/s3.yml
development:
  bucket: sample-dev
  access_key_id: アクセスキー
  secret_access_key: シークレットキー
  s3_host_name: s3-ap-northeast-1.amazonaws.com
production:
  bucket: sample-production
  access_key_id: アクセスキー
  secret_access_key: シークレットキー
  s3_host_name: s3-us-west-1.amazonaws.com


参考:AWS セキュリティセンター (AWS Security Center) | アマゾン ウェブ サービス(AWS 日本語)

その場合のモデルはこうなる
# app/models/figure.rb
class Figure < ActiveRecord::Base
  has_attached_file :image, 
    :styles => { :medium => "300x300>", :thumb => "100x100>" }, 
    :storage => :s3,
    :s3_credentials => "#{Rails.root}/config/s3.yml",
    :path => ":attachment/:id/:style/:filename" 
end

すっきりしましたね。

config/initializers/aws.rb を追加する


[追記:2012/1/19] 現時点において下記のコードは不要です。


残念ながら現状、次のプログラムを追加する必要があります。面倒ですね。今度なんとかしましょう。

#config/initializers/aws.rb
AWS::S3::DEFAULT_HOST.replace "s3-ap-northeast-1.amazonaws.com"


参考:PaperclipからAmazon S3のTokyo Regionを使うには。 - このブログは証明できない。


ともあれ、これで以前よりも簡単にS3@tokyoを使えるようになるはずです。

新しいバージョンじゃないと使えません


(追記)既に本体に取り込まれているので、下記の作業は不要です。


2011/7/19の時点で、paperclipは2.3.15ですが、:s3_host_nameオプションは、それには含まれていないので、Gemfileを以下のようにするか、次のバージョンがでるまで待つとよいでしょう。

#Gemfile
gem 'paperclip', :git => "git://github.com/thoughtbot/paperclip.git"
gem 'aws-s3'

コミュニティに参加しよう


今回、初めてPull Request送ったのですが、これからは、ドンドンやるべきだなぁと思いました。


私だって始めたばかりのひよっこですが、もっといろいろ出来ることがあるなぁと感じましたし、実際できましたし。
Railsだって、もはやDHHが作っているわけではないし(3.1は南米産という噂だし)、こういったオープンソースのコミュニティに積極的に関わるというのは、とても良い経験になると思います。