LoginSignup
7
3

More than 5 years have passed since last update.

ParperClipで画像投稿までの過程をまとめたよ(AWS cloud9 + Heroku + S3)

Last updated at Posted at 2018-10-23

はじめに

Ruby on Railsで画像を投稿する機能を作っている友人が、途中でハマっていたので、自分でも最小限の機能を実装してみました。
途中の過程で色々な記事を往復しましたので、条件が同じ人に活用して貰いたく、ここにまとめます。
実装は、以下の流れで試しました。

  1. local(cloud9)で画像の投稿
  2. cloud9から画像の保存を S3に行う
  3. Herokuにデプロイして、S3に画像の保存を行う

今回の記事では以下の内容は、詳しくは説明しません。
S3でのバケットの作成
Herokuアカウントの登録

対象となる読者

Rails初学者、半年以内で、自ら小さなプロダクトを作ってみようと考えている方。

操作を行った環境

ruby 2.3.1p112
rails 5.0.6

詳細

1.AWScloud9にImageMagickを導入する

公式にもあるように ImageMagickが動作させる環境に入っていないと、PaperClipは使えないとのこと。まずは ImageMagickを cloud9に導入します。

旧cloud9の記事から流れとしては、 apt-get update を行って sudo apt-get install imagemagick とのことで、この内容に従って進めます。

$ sudo apt-get update                                                                                              
sudo: apt-get: command not found

apt-get というコマンドが見つからないとお叱りを受ける。

親切なことに、cloud9でこのようにアラートメッセージが出力されました。

どうやら、Amazon Linuxを使用している場合は、RedHatベースのCentOSベースのため、 apt-get ではなく yum を使用するようです。

$ sudo yum update 
~(中略)  
Complete!

いけたようなので続いて sudo yum install imagemagick を実行します。

$ sudo yum install imagemagick
Loaded plugins: priorities, update-motd, upgrade-helper
1054 packages excluded due to repository priority protections
No package imagemagick available.
  * Maybe you meant: ImageMagick
Error: Nothing to do

有効な imagemagick というパッケージはないと怒られる。エラーのヒントの通り実行します。

$ sudo yum install ImageMagick
Loaded plugins: priorities, update-motd, upgrade-helper
amzn-main
~(中略)
Complete!                                     

成功したようなので、 convert --version で確認するImageMagickが入っているか確認します。

$ convert --version
Version: ImageMagick 6.7.8-9 2016-06-22 Q16 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2012 ImageMagick Studio LLC
Features: OpenMP  

無事に、ImageMagickの導入は完了しました。

2. アプリケーションにpaperclipを導入する

STEP1:ローカルで画像投稿が出来るか確認
※最小限のアプリケーションに今回は画像投稿、表示の機能を付け加えていく。 Message というモデルにカラムを追加し、画像を投稿できるように実装する。

Gemfile
gem "paperclip", "~> 6.0.0"

上記をGemfileに記述し bundle install を行います。

3. Migration, Model, Controller, Viewを準備する

Messageモデルに新しく投稿する画像を imageカラム を追加します。migrationファイルの作成を以下のコマンドで実行します。

rails g migration AddAttachmentImageToMessages

新しく追加されたmigrationファイルを以下のように変更します。

class AddAttachmentImageToMessages < ActiveRecord::Migration[5.0]
  def self.up
    change_table :messages do |t|
      t.attachment :image
    end
  end

  def self.down
    remove_attachment :messages, :image
  end
end

rails db:migrate で変更を schema.rb に反映させます。反映された schema.rb には以下の4つのカラムが追加されています。

  create_table "messages", force: :cascade, options: "ENGINE=InnoDB DEFAULT CHARSET=utf8" do |t|
    ~(中略)
    t.string   "image_file_name"
    t.string   "image_content_type"
    t.integer  "image_file_size"
    t.datetime "image_updated_at"
  end

続いてMessageモデルの中身に以下を追加します。

message.rb
class Message < ApplicationRecord
  ~(中略)
  has_attached_file :image,
                    :styles => { medium: "300x300>", thumb: "100x100>" }, 
                    :default_url => "/images/:style/missing.png"
  validates_attachment_content_type :image, content_type: /\Aimage\/.*\z/ 
end

Contollerを変更

messages_controller.rb
def create
  @message = Message.create(message_params)
end

def message_params
  params.require(:message).permit(:image)
end

必要な記述を対象のViewページに付け加えます。

rails s -b $IP -p $PORT でサーバーを起動して、画像を投稿してみると、、、

ローカルでの画像投稿完成!

投稿された画像はどこに保存されるかというと、 application名/public/system/ というディレクトリが新しく作成されており、その中に保存されています。

4. アプリケーションにaws-sdk-s3を導入する。

STEP2:ローカルからS3に画像を保存する

ParperClipの公式ページに以下のように記述があります。

You may also choose to store your files using Amazon's S3 service. To do so, include the aws-sdk-s3 gem in your Gemfile:

Gemfile
gem 'aws-sdk-s3'

bundle install を行います。

Gemfile
gem 'aws-sdk-s3'

bundle install 後にこのようなNoteが表示されました。

##################################################
#  NOTE FOR UPGRADING FROM 4.3.0 OR EARLIER      #
##################################################

Paperclip is now compatible with aws-sdk >= 2.0.0.

If you are using S3 storage, aws-sdk >= 2.0.0 requires you to make a few small
changes:

* You must set the `s3_region`
* If you are explicitly setting permissions anywhere, such as in an initializer,
  note that the format of the permissions changed from using an underscore to
  using a hyphen. For example, `:public_read` needs to be changed to
  `public-read`.

For a walkthrough of upgrading from 4 to 5 and aws-sdk >= 2.0 you can watch
http://rubythursday.com/episodes/ruby-snack-27-upgrade-paperclip-and-aws-sdk-in-prep-for-rails-5

Paperclipは aws-sdk >= 2.0.0. と互換性があり、 S3 storageを使うなら、 aws-sdk >= 2.0.0s3_region の設定が必要不可欠で、アクセス許可の形式で - を使っている箇所は _ に書き換えないといけないとのこと。

Paperclip with Amazon S3 によると
storage, s3_host_name, :bucket を設定するとのこと。加えて access_key_id, secret_access_key を追記します。

development.rb
  config.paperclip_defaults = {
  :storage        => :s3,
  :s3_host_name   => 's3-ap-southeast-1.amazonaws.com',
  :bucket         => ENV['S3_BUCKET_NAME'],
  :s3_credentials => {
      access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
    }
  }

大事な内容は .bash_profile に環境変数に設定してそこから参照するようにします。

echo export S3_BUCKET_NAME="S3のBucket Name" >> ~/.bash_profile
echo export AWS_ACCESS_KEY_ID="AWSのaccess_key_id" >> ~/.bash_profile
echo export AWS_SECRET_ACCESS_KEY="AWSのsecret_access_key" >> ~/.bash_profile

#書き込んだ .bash_profileの内容を読み込む
source ~/.bash_profile

サーバーを立ち上げ、画像を投稿するとエラーが発生しました。

undefined method match for nil:NilClass Did you mean? catch

調べると、これは S3のregionの設定がされていないことが原因。そういえば、 aws-sdk-s3 を導入したときに Noteで You must set the s3_region と書いてあったのを忘れていたので、記述します。

development.rb
  config.paperclip_defaults = {
  :storage        => :s3,
  :s3_host_name   => 's3-ap-southeast-1.amazonaws.com',
  :bucket         => ENV['S3_BUCKET_NAME'],
  :s3_region      => ENV['AWS_REGION'], #追記
  :s3_credentials => {
      access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
    }
  }

再度 .bash_profile に環境変数に設定してそこから参照するようにします。

echo export AWS_REGION="S3のRegion" >> ~/.bash_profile

#書き込んだ .bash_profileの内容を読み込みます。
source ~/.bash_profile

※Regionがよくわからない場合はこちらの公式ページを参照。

実際に投稿してみる。

無事に投稿完了!!

5. Herokuにアプリをupしてから画像をS3に保存

STEP3:HerokuからS3に画像を保存する

まずは、production環境に以下の記述を追記します。

production.rb
  config.paperclip_defaults = {
  :storage        => :s3,
  :s3_host_name   => 's3-ap-southeast-1.amazonaws.com',
  :bucket         => ENV['S3_BUCKET_NAME'],
  :s3_region      => ENV['AWS_REGION'],
  :s3_credentials => {
      access_key_id: ENV['AWS_ACCESS_KEY_ID'],
      secret_access_key: ENV['AWS_SECRET_ACCESS_KEY']
    }
  }

続いてCloud9に Heroku CLIが導入されていない場合は、CLIを導入していきます。

wget https://cli-assets.heroku.com/heroku-cli/channels/stable/heroku-cli-linux-x64.tar.gz -O heroku.tar.gz

sudo mkdir -p /usr/local/lib/heroku

sudo tar --strip-components 1 -zxvf heroku.tar.gz -C /usr/local/lib/heroku

sudo ln -s /usr/local/lib/heroku/bin/heroku /usr/local/bin/heroku

ターミナルから Heroku にログインしましょう。Herokuに登録してある mailとpasswordをターミナルから打ち込みます。

heroku login
Enter your Heroku credentials.
Email: Herokuに登録したメールアドレスを入力
Password: Herokuに登録したパスワードを入力

ログインに成功した場合は Logged in as 登録したmailアドレス が表示されます。
続いて、 Heroku にアプリケーションを作成しましょう。

heroku create 作成するHerokuアプリケーション名

※アプリケーション名は Heroku上で一意 である必要があるため、他の人と重複したアプリケーション名は命名出来ません。

念のためアプリケーションが作成されたかを確認します。

heroku apps

Herokuの DBPostgreSQL のため、 mysqlなど他の DBを使っている場合は以下の追加が必要です。

Gemfile
group :production do
  gem 'pg', '0.21.0'
end

Development環境でbundle installする必要はないので以下のコマンドで bundle install します。

bundle install --without production

今までの変更を、忘れずに commit しておきましょう。

ここまで出来たら、デプロイ作業に入ります。以下のコマンドでデプロイ。

git push heroku master

続いて heroku run コマンドでマイグレーションを実行していく。

heroku run rails db:migrate

それでは、 Herokuアプリ で画像を投稿してみます。

無事成功!? かと思いきや、S3を確認すると、対象の画像は保存されていません。

これは、HerokuにAWSの設定を追加してないからです。

公式に従って、必要な設定を登録していきます。

heroku config:set S3_BUCKET_NAME=your_bucket_name
heroku config:set AWS_ACCESS_KEY_ID=your_access_key_id
heroku config:set AWS_SECRET_ACCESS_KEY=your_secret_access_key
heroku config:set AWS_REGION=your_aws_region

再度 Herokuアプリを開き画像を投稿!

無事S3の中に対象の画像が保存されました!

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3