はじめに
この記事はRuby on RailsのActiveStorageとCloudinaryを使って画像を管理するアプリを作るためのメモです。PaaSとしてHerokuを使います。
ActiveStorageはRails 5.2以上で動作するクラウドストレージサービスへのファイルのアップロードやActiveRecordオブジェクトへのファイルのアタッチをやってくれる便利なモデルです。
Cloudinaryは画像や動画のCDNや編集の機能を有するSaaSです。Herokuのadd-onsとしても存在しています。
この記事のゴール
この記事では、Heroku上でユーザー名とプロフィール写真を管理するRuby on Railsアプリケーション(on Docker)をHeroku上で動作させることをゴールにします。DB/StorageはHerokuのadd-onsからPostgres/Cloudinaryを使います。
前提
- Rails on Dockerの準備ができていること --> Quickstart: Compose and Rails | Docker Documentation
- Herokuのアカウントが準備できていること
メモ
1. ActiveStorageのアプリを作る
こちらの記事が参考になりました。
【Rails 5.2】 Active Storageの使い方 - Qiita
まずファイルをアタッチするモデルとしてUserモデルをscaffoldで作っておきます。
$ docker-compose run --rm web rails g scaffold user name:string
$ docker-compose run --rm web rails db:migrate
続いて、ActiveStorageをインストール。
$ docker-compose run --rm web rails active_storage:install
$ docker-compose run --rm web rails db:migrate
ActiveStorageはモデルにhas_one_attached
を定義するだけでファイルを扱えるようになる優れものです。
class User < ApplicationRecord
has_one_attached :photo
end
これでphoto
という名前のファイルをActiveStorageが勝手に管理してくれます。
ファイルのアップロードと参照ができるようにview/controllerも手直ししておきます。
def user_params
# photoの登録を許可
params.require(:user).permit(:name, :photo)
end
<!-- 以下をいい感じのところに追加 -->
<div class="field">
<%= form.label :photo %>
<%= form.file_field :photo %>
</div>
<!-- 以下をいい感じのところに追加 -->
<div>
<% if @user.photo.attached? %>
<%= image_tag @user.photo %>
<% end %>
</div>
これでUser
モデルでphoto
としてファイルを管理できるようになりました。
この段階ではphoto
として登録されるファイルはstorage/
に保存されていきます。これは
config.active_storage.service = :local
local:
service: Disk
root: <%= Rails.root.join("storage") %>
で定義されています。
2. Herokuの準備
HerokuはHeroku CLIで操作していきます。まずはadd-onsでpostgresとcloudinaryの準備が必要です。まずHerokuにログインしてアプリを作成します。
$ heroku login
$ heroku create app-name
このアプリに対してpostgresとcloudinaryのadd-onsを追加してきます。postgresは無料のhobby-dev、cloudinaryも無料のstarterというプランを使っていきます。cloudinary:starterはクレカ登録してないと使えないみたいですね。
$ heroku addons:create heroku-postgresql:hobby-dev
$ heroku addons:create cloudinary:starter
3. ActiveStorageとCloudinaryを連携させる
ActiveStorageとCloudinaryを連携させるためにGitHub - 0sc/activestorage-cloudinary-serviceを利用します。
READMEの通りにやっていけばOKです!
gem 'cloudinary', require: false
gem 'activestorage-cloudinary-service'
$ docker-compose build
Cloudinaryと連携するためのcloud_name
、api_key
、api_secret
の情報をRailsアプリに登録してきます。これらの情報はHerokuサイトでOverviewのところから各アドオンのサイトにリンクされているんですが、リンク先のCloudinaryのDashboardに情報が載ってます。
Rails5.2以降であればcredentials
を利用しているかと思いますので、そちらの方法で。
$ docker-compose run --rm -e EDITOR="vim" web rails credentials:edit
cloudinary:
cloud_name: xxxxxxxxxx
api_key: xxxxxxxxxx
api_secret: xxxxxxxxxx
※vimがないとか言われる場合は【Rails 5.2.2】Rails on Dockerでcredentialsをeditしたい - Qiitaあたりを参考にしていただけますと!
この設定をconfig/storage.yml
から呼び出します。
# 以下を追加
cloudinary:
service: Cloudinary
cloud_name: <%= Rails.application.credentials.dig(:cloudinary, :cloud_name) %>
api_key: <%= Rails.application.credentials.dig(:cloudinary, :api_key) %>
api_secret: <%= Rails.application.credentials.dig(:cloudinary, :api_secret) %>
そして、config/environments/development.rb
で指定されているconfig.active_storage.service
も書き換えます。
# config.active_storage.service = :local
config.active_storage.service = :cloudinary
本当はproduction.rb
を書き換えて、heroku側のconfigもRAILS_ENV=production
とするべきなのですが、今回のメモはお試しなのでdevelopmentで進めますね。
ここまででRailsアプリ、Herokuのadd-onsの準備は完了になりますので、あとはこのアプリをdeployしていくだけです。
4. Rails on DockerをHerokuにDeployする
Rails on DockerのHerokuへのDeploy方法は以下の記事でもまとめています。
Rails on DockerをHerokuでDeployするまで - Qiita
この記事ではpostgresのadd-ons追加などが完了しているので必要なところだけ書いていきます。
$ heroku container:login
$ heroku container:push web
$ heroku container:release web
$ heroku run rails db:migrate
これでアプリのデプロイが完了するはずなので、あとはサイトを開いてみます。
$ heroku open
ローカルでテストしてみた時と同じようにファイルをアップロードできるはずです。
また、Cloudinaryのサイトの「Media Library」にその画像ファイルが登録されているのみ見れるはずです。
ちなみにActiveStorageはそのモデルが削除されるときに画像ファイルも一緒にdeleteしてくれるのもすごい便利ですね。
あとがき
ということで、Rails on Docker on HerokuでActiveStorage + Cloudinaryの画像管理ができました。
Carrier Waveとかなしで画像扱えるのは便利でした〜。herokuも1コマンドでアドオンが追加できて便利!