Rails Ambassador

Heroku + Cloudinary環境でCarrierwaveで画像アップロード

こちらのTipsでは最小限の記述でHeroku環境で画像アップロードを実装します。
HerokuサーバはGit管理下にないファイルはキャッシュされませんので別途画像を保存しておくストレージが必要となります。
今回はHerokuの兄弟サイトであるCloudinaryを使って画像をアップロードすることにします。

それぞれの役割を確認しておいてください。

  • Heroku … アプリの本番環境
  • Carrierwave … 画像アップロードをサポートしてくれるGem
  • Cloudinary … 画像を保存しておく場所(ストレージ)
参考サイト

動作環境

以下環境で動作確認しています。

ruby: 2.6.6
Rails: 6.0.3.1
  • Herokuのアカウント登録は済んでいるものとします。
  • Cloudinaryのアドオンの追加をするためにはHerokuでクレジットカードの登録が必要です。
  • HerokuにデプロイするためにGitを使用します。

動作確認日: 2020/05/28

Railsアプリの作成

任意の名前でプロジェクトを作成しディレクトリの移動をおこなってください。
※このTipsではプロジェクト名をImageUploadとしています。
こちらでは開発環境のデータベースはMySQLを使うものとしていますが、任意のお好きなもので構いません。

$ rails new ImageUpload -d=mysql
$ cd ImageUpload

Gitリポジトリも登録しておきましょう。

$ git init
$ git add .
$ git status
$ git commit -m "app init"

Gemfileの設定

今回使うGemを全てインストールしておきます。

Gemfileの一番下に追加(※任意の場所でも良いです)
Herokuの推奨データベースはPostgreSQLなのでこちらを使います。
gem pgをHeroku(prodution)でインストールされるようにしておきます。

gem 'cloudinary' , '1.11.1'
gem 'carrierwave', '~> 1.3.1'
gem 'pg', group: :production

Gem cloudinaryはHerokuとストレージであるCloudiinaryを連携するためのGemです。
Gem carriewaveが画像アップロードを行うライブラリになります。
Herokuで推奨されているPostgreSQLというデータベースサーバを使うためのライブラリ「pg」を本番環境でインストールされるようにしておきます。

追記しましたらインストールを実行してください。

$ bundle install

Herokuのアプリ作成とアドオンの追加

Herokuアプリを作成しましょう。heroku infoコマンドで表示URLも確認しておいてください。
※Herokuにログインしていない方はemailとpasswordを聞かれますのでHerokuアカウントのメールとログインパスワードを入力してください。

$ heroku create アプリ名
$ heroku info

次にHerokuとCloudinaryを連携するためのアドオンを追加します。(Herokuサイトのダッシュボードからも追加できますがコマンドで実施します。)
※アドオンとはHerokuの追加機能のことです。

$ heroku addons:add cloudinary:starter

アップローダーの作成

UserUploaderの作成

アップローダーを作成します。このアップローダーファイルはCarrieawaveを使って画像をアップロードするための設定ファイルです。
複数モデルがありそれぞれ別の設定を行いたい場合は複数アップローダーを作成してください。今回のアップローダー名はUserとします。

$ rails g uploader User
     create  app/uploaders/user_uploader.rb

app/uploaders/user_uploader.rbファイルが作成されました。

UserUploaderの編集

作成したアップローダー「app/uploaders/user_uploader.rb」を編集します。

class UserUploader < CarrierWave::Uploader::Base
  include Cloudinary::CarrierWave
end

モデルの作成

Userモデルの作成

画像をアップロードし、名前と一緒に画像を表示するようにします。
Userモデルにnameカラムとアップロードした画像のURLを入れるimageカラムを持たせましょう。
DB作成とマイグレーションも行ってください。

$ rails g model User name image
$ rails db:create
$ rails db:migrate

Userモデルの編集

作成したuserモデルに作成したアップローダーを設置します。app/models/user.rbファイルを以下のように編集してください。

class User < ApplicationRecord
  mount_uploader :image, UserUploader
end

画像ファイルのURLを格納するカラム名はimage、作成したアップローダーはUserUploaderなので上記のように設置します。

mount_uploader :対象カラム名, アップローダ―クラス名

コントローラの作成

UsersControllerの作成

usersコントローラを作成します。
TOPページはusers#indexで表示し、こちらに入力フォームを設置しますので以下のように設定しています。

$ rails g controller users index

usersコントローラの編集

usersコントローラを編集します。app/controllers/users_controller.rbを以下のように編集してください。

class UsersController < ApplicationController
  def index
    @user = User.new  #form用インスタンス
    @users = User.all #ユーザー一覧表示用
  end

  def create
    @user = User.new(user_params)
    @user.save
    redirect_to root_url
  end
  
  private 
  def user_params
    params.require(:user).permit(:name, :image)
  end
end

動作確認

Messagesアプリケーションのディレクトリでサーバを起動してブラウザでlocalhost:3000にアクセスして動作確認を行ってください。
rails s

ルーティングとViewの作成

ルーティング

画像をアップロードするViewを作成していきましょう。
今回はTOPページで画像をアップし、users#createアクションでDBに保存を行い、User一覧としてTOPページで表示させます。

config/routes.rbを以下のように編集してください。

Rails.application.routes.draw do
  root 'users#index'
  resources :users, only: [:create]
end

TopぺージとUser作成のルートになります。

Viewの編集

app/views/users/index.html.erbファイルを以下のように編集してください。

<%= form_with model: @user, local: :true do |f| %>
  <%= f.label :name %>
  <%= f.text_field :name %>
  <%= f.file_field :image %>
  <%= f.submit '登録' %>
<% end %>

<h2>User一覧</h2>
<% @users.each do |user| %>
  <%= user.name %>
  <%= image_tag(user.image.to_s) %> <%# カラム名がimageの場合はto_sが必要 %>
<% end %>

※今回のようにカラム名が「image」の場合は表示時にto_sメソッドで文字列にする必要があります。
image以外のカラム名の場合は「to_sメソッド」は不要になります。

Cloudinary用の設定ファイルの追加

※こちらの設定は開発・テスト環境から画像をアップするテスト用に必要です。

Heokuの公式サイトに行き、アプリケーションのDashboardのOverviewタブにある Cloudinaryをクリックするとこのアプリに紐づいたCloudinaryのサイトに遷移します。

※ここでCloudinaryのアイコンやリンクが表示されていない方はアドオンの追加ができていません。また、アドオンの追加にはクレジットカードの登録が必要になります。
※Cloudinaryのサイトではアンケート(質問)が表示されますが詳細は割愛します。スキップしても大丈夫です。

cloudinary.ymlファイルのダウンロード

CloudinaryのDashboardのAccountDetailsの右側にダウンロードリンクがありますのでYMLをクリックしてダウンロードしてください。

ダウンロードしたファイルをconfigディレクトリに配置します。config/cloudinary.yml

※このままGithubなどでソースコードを公開しないでください。 cloudinary.ymlにはapi_keyが記載されていますのでこのまま公開しますと悪用されてしまいます。
公開する際はgitignoreに追加するなど各自対応してください。

Heroku用の設定を行う。

HerokuのPostgreSQLの設定

Herokuで使うPostgreSQL用の設定を記述します。database.ymlファイルのProductionの部分を変更します。

config/database.yml
※YAMLファイルのインデントは半角スペース2つです。注意してください。

production:
  adapter: postgresql
  pool: 5
  encoding: unicode
  database: ImageUpload_production
  username: ImageUpload
  password: <%= ENV['IMAGEUPLOAD_DATABASE_PASSWORD'] %>>

開発・テスト環境からアップロードをするための設定を追加

Cloudinaryの各種APIキーを使用できるように環境変数に設定

前述しましたがこのまま公開すると非常に危険です。API_keyは環境変数に登録しましょう。ファイルに記載してあるcloud_name、api_key、api_secretの値は後で使いますので控えておいてください。
config/cloudinary.ymlファイルを以下のように編集してください。

---
development:
  cloud_name: <%= ENV['CLOUDINARY_CLOUD_NAME'] %>
  api_key: <%= ENV["CLOUDINARY_API_KEY"] %>
  api_secret: <%= ENV["CLOUDINARY_API_SECRET"] %>
  enhance_image_tag: true
  static_image_support: false
test:
  cloud_name: <%= ENV['CLOUDINARY_CLOUD_NAME'] %>
  api_key: <%= ENV["CLOUDINARY_API_KEY"] %>
  api_secret: <%= ENV["CLOUDINARY_API_SECRET"] %>
  enhance_image_tag: true
  static_image_support: false

ローカルで動作確認

以下コマンドでサーバを立ち上げ動作確認してください。
※Dotenv-Railsなど任意の方法で環境変数に登録している方はrails sで起動して大丈夫です。

$ CLOUDINARY_CLOUD_NAME=取得したcloud_name CLOUDINARY_API_KEY=取得したAPI__key CLOUDINARY_API_SECRET=取得したapi_secret rails s 

名前とファイルを選択し、登録後画像が表示されればOKです。

Cloudinaryのサイトに行きますと画像がアップロードされているのがわかると思います。

Tips!ciphersが見つからないエラーが出る場合

KeyError in UsersController#create
key not found: :ciphers

以下画像のようにエラーとなる場合はrest-client というgemのバージョンを2.0.2に指定する必要があります。

Gemfileの一番下に以下行を追加してください。

gem 'rest-client', '2.0.2'

その後bundle updateを行います。

$ bundle update

サーバを再起動して動作確認を行ってください。

Herokuへデプロイ・動作確認

ローカルで動作確認ができましたらデプロイしましょう。
※エラーが出るものをデプロイするのは危険です。 必ずローカルでしっかりと動作確認を行ってください。

$ git add .
$ git status
$ git commit -m "Deploy to Heroku"
$ git push heroku master
$ heroku run rails db:migrate

herokuで動作確認をし、画像がCloudinaryにアップロードされていれば完成です!