[Ruby on Rails]paperclipでつくるS3への画像保存アプリ

2014.06.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

paperclipというGemを使い、Amazon S3に画像を保存するRailsアプリを作成してみました。ただ画像を保存するだけでは、aws-sdkを使うのと手間はそんなに変わらないですが、paperclipを使うと以下の機能が簡単に実装できます。

  • サムネイルとそれ以外など、アップロードされた画像から異なるサイズの画像ファイルを作成して保存する
  • S3へ保存する画像には権限をつけ、画像を全公開しないようにする

作成手順とソースコード

早速、アプリの作成手順とソースコードについて書いていきたいと思います。Railsのアプリケーションの雛形は出来ている前提です。

1.ImageMagicのインストール

paparclipはImageMagicを使用するため、ローカルにインストールされていない場合は以下のコマンドでインストールしてください。(Macの場合のコマンドです)

$ brew install imagemagick

2.Gemのインストール

Gemfileに以下を記述し、今回使うGemをインストールします。

gem 'paperclip'
gem 'aws-sdk'

以下のコマンドを実行します。

$ bundle install

3.スキャフォールドによる雛形の作成

スキャフォールドを使い、Modelとテーブル、CRUDの雛形を作成します。今回はModel名は「Article」、画像のタイトルを保持する「title」というカラム名で作成します。

$ rails g scaffold articles title:string

4.Modelの編集

Modelに、paperclipでの処理に必要なソースを記述します。

article.rb

class Article < ActiveRecord::Base
  has_attached_file :image,
                    :styles => {
                        :thumb  => "100x100",
                        :medium => "200x200",
                        :large => "600x400"
                    },
                    :storage => :s3,
                    :s3_permissions => :private,
                    :s3_credentials => "#{Rails.root}/config/s3.yml",
                    :path => ":attachment/:id/:style.:extension"

  validates_attachment_content_type :image, :content_type => ["image/jpg", "image/jpeg", "image/png", "image/gif"]

  def authenticated_image_url(style)
    image.s3_object(style).url_for(:read, :secure => true)
  end
end

まず2行目の「has_attached_file」について説明します。引数のhashで、以下のことについて定義しています。

  • 画像の情報を保持するプロパティ名の定義(2行目)
  • サムネイルなど、保存する複数の画像の大きさと、それぞれの名称を定義(3~7行目)
  • 画像の保存先をAmazon S3に定義(8行目)
  • S3へ保存する画像の権限をPrivateにして、アプリ以外からURL参照不可とする(9行目)
  • S3への接続定義ファイルのパスを設定(10行目)
  • S3のバケット内の画像パス(11行目)

続いて13行目の「validates_attachment_content_type」にて、画像の拡張子を限定するためのvalidatorを定義しています。

最後の15~17行目の「authenticated_image_url」メソッドですが、これは権限にて保護されているS3上の画像を参照するURLを作成するメソッドです。後で出てくる画面より、このメソッドを呼び出し、S3上の画像を参照します。

5.画像の情報を格納するDB上のカラムを定義

以下のコマンドにてMigrationファイルを作成します。

$ rails g migration AddAttachmentImageToArticles

作成されたMigrationファイルに、画像の情報を保存するためのカラムをarticleテーブルに追加する処理を記述します。

db/migrate/yyyymmdd_add_attachment_image_to_articles.rb

class AddAttachmentImageToArticles < ActiveRecord::Migration
  def self.up
    change_table :articles do |t|
      t.has_attached_file :image
    end
  end

  def self.down
    drop_attached_file :articles, :image
  end
end
[/ruby]
<p>
以下のコマンドで、migrationを実行し、カラムを追加します。
</p>

<h3>6.Controllerの修正</h3>
<p>
articles_controller.rbの「article_params」メソッド内に、以下を追加します。
</p>

params.require(:article).permit(:image)

7.画像の入力フィールドの作成

_form.html.erbに以下を追加し、登録する画像を登録するためのフィールドを表示させます。

<%= f.file_field :image %>

8.画像を参照して画面に表示

Model内に記述したメソッドを呼び出し、S3上に保存した画像を表示するための処理を、Viewに記述します。今回は一覧画面ではサムネイルとしてthumbサイズの画像を、詳細画面ではlargeサイズの画像を表示しました。

詳細画面(_article.html.erb)

 <%= image_tag(article.authenticated_image_url(:thumb)) if article.image.present? %>

一覧画面(show.html.erb)

 <%= image_tag(@article.authenticated_image_url(:large)) if @article.image.present? %>

それぞれ「authenticated_image_url」メソッドを呼び出し、引数に取得したい画像の名称を指定しています。取得したURLを使い、「image_tag」にて画像を表示します。

9.S3への接続定義ファイル

最後に、Amazon S3へ接続するための定義ファイルです。Model内で指定したファイルになります。

config/s3.yml

bucket: 'bucket name'
access_key_id: 'your access key id'
secret_access_key: 'your secret access key'
s3_host_name: host name

作成したアプリの画面とS3のバケット

以上のソースコードにて作成したアプリの画面は、以下のようになります。一覧画面、詳細画面で大きさの異なる画像が表示されていることが分かるかと思います。(尚、bootstrapを使っているため、見た目はRails標準のCSSとはかなり異なっています)

一覧画面

index

詳細画面

show

またアプリから登録した画像は、以下のようにS3上のバケットに保存されます。「Permissions」の欄を見ると「Grantee」に「Everyone」がいないため、登録されている接続ユーザからのみ参照できることが分かります。

permission

まとめ

RailsにてS3へ画像を保存するアプリを作る際の一助になれば、幸いです。

今回作成したソースはGithub上に上げてあります。参考にしたい方は、どうぞ。
s3_paperclip_jumbotron