めも帖

「めも帖」代わりにダラダラと書いていったり、めもしたりしているだけです。

HerokuでAmazon S3に画像をアップロードする

Ruby on Rails 3.2 で、画像をアップしたい、というのがあります。
それと、Herokuを使いたい、というのもあります。
そいうときのために、Paperclipというgemがあるそうなので、試してみることにしました

Amazon S3

Paperclipのいいところは、Amazon S3が保存先として使えること。
Herokuの場合、静的なファイルは、保存できないので(一時保存として/tmpは使えるらしい)、Amazon S3を利用します。
Amazon S3については、他に詳しい説明がたくさんあるので、パス。

環境

  • Mac OS X 10.7
  • Ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-darwin11.3.0]
    • rbenvで、インストールしてあります
      • あと、最近、MacPortsから、Homebrewに変えました
  • Ruby on Rails 3.2

新しいアプリケーションを用意

rails new heroku_image_4 --skip-bundle

scaffold

rails g scaffold product name:string
rake db:migrate
カラム追加
rails g migration add_photo_columns_to_product
rake db:migrate

imagemagickの用意

brew install imagemagick
gem install rmagick

Gemfileの設定

いくつかポイントがあります

  • 本番環境は、Postgresqlを利用
  • インストール時は、bundle install --without production
Postgresqlを利用

Herokuは、Postgresqlが基本です。ローカルでは、sqliteでもいいです
環境によって使うDBを変えます。

budleのインストール

「--without」 オプションがあることを知りました。
これで、ローカルにPostgresqlがなくても…というよりも、HerokuでPostgresqlを使うときのみ、Postgresqlにしたほうが良さそうです。HerokuでのID/PASSがわからないです。あと、Postgresqlの設定も違うので。

Gemfile
gem 'rails', '3.2.3'

group :production do
  gem 'pg'
  gem 'therubyracer-heroku'
end

group :development do
  gem 'sqlite3'
end

group :assets do
  gem 'sass-rails',   '~> 3.2.3'
  gem 'coffee-rails', '~> 3.2.1'
  gem 'uglifier', '>= 1.0.3'
end

gem 'jquery-rails'
gem 'paperclip'
gem 'aws-s3'
gem 'aws-sdk'

modelと、s3.ymlの問題

scaffoldで作ったmodelにカラムを追加します。
ポイントは、Amazon S3の設定を書いたs3.ymlのパス指定。
config/s3.ymlとなるのですが、Railsのルート設定方法がポイント。

  attr_accessible :name, :photo

  has_attached_file :photo,
   :styles => {
   :thumb  => "100x100",
   :medium => "200x200",
   :large => "600x400"
 },
   :storage => :s3,
   :s3_credentials => File.join(Rails.root, 'config', 's3.yml'),
   :path => ":attachment/:id/:style.:extension"

config/s3.yml

development:
  bucket: bucketname
  access_key_id: xxxxxxx
  secret_access_key: xxxxxxx

test:
  bucket: bucketname
  access_key_id: xxxxxxx
  secret_access_key: xxxxxxx


production:
  bucket: bucketname
  access_key_id: xxxxxxx
  secret_access_key: xxxxxxx

assets

Rails 3.1からの機能?なのですけれど、Herokuでの対応を設定

    # Enable the asset pipeline
    #config.assets.enabled = true
     config.assets.compile = true

テンプレート

app/views/products/_form.html.erb
  • mulitpertを指定
  • 追加したphotoのfieldを用意
<%= form_for @product , :html => { :multipart => true } do |f| %>
  <%= f.file_field :photo %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
app/views/products/show.html.erb
<%= image_tag @product.photo.url %>
<%= image_tag @product.photo.url(:medium) %>
<%= image_tag @product.photo(:thumb) %>
<%= image_tag @product.photo(:large) %>

herokuへデプロイ

git
git init
git add .
git commit -m 'first commit'
Herokuでアプリを用意
heroku create
Herokuのデプロイ

というか、push

git push heroku master
Herokuでrake
heroku rake db:migrate

実際試してみた結果

  • Amazon S3パーミッションが、アクセス可能になって表示される
  • アップロードするときに、いくつかの画像が生成されてからアップされる
    • このあたりは、変えたい