はじめに
Rails6の新機能「ActionText」はお手軽にリッチテキストエディターが利用できます。
ActionTextでアップロードした画像の保存先は、デフォルトではローカル(本番環境ならサーバー上)になっています。Railsアプリのデプロイ先としてHerokuを使うことが多いと思いますが、Herokuは定周期でデプロイ時の状態に戻していまいますので、デプロイ後にActionTextでアップロードした画像は時間が経つと消えてしまいます。
そこで、ActionTextでアップロードした画像の保存先をローカルから外部のクラウドストレージ(今回はAmazon S3)に変更したいのですが、うまくいきませんでした😥
現時点までに試した手順を備忘として残しておきます。もし、解決方法を知っている方がいましたら教えていただけると助かります…
ActionTextでアップロードした画像の保存先は、デフォルトではローカル(本番環境ならサーバー上)になっています。Railsアプリのデプロイ先としてHerokuを使うことが多いと思いますが、Herokuは定周期でデプロイ時の状態に戻していまいますので、デプロイ後にActionTextでアップロードした画像は時間が経つと消えてしまいます。
そこで、ActionTextでアップロードした画像の保存先をローカルから外部のクラウドストレージ(今回はAmazon S3)に変更したいのですが、うまくいきませんでした😥
現時点までに試した手順を備忘として残しておきます。もし、解決方法を知っている方がいましたら教えていただけると助かります…
ActiveStorageについて
ActionTextは画像のアップロードにActiveStorageを使用していますので、ActiveStorageの設定を変更していきます。
画像の保存先を変更
config/environments/配下にあるファイルを変更します。
開発環境なら「development.rb」、本番環境なら「production.rb」を開きます。
開発環境なら「development.rb」、本番環境なら「production.rb」を開きます。
# Store uploaded files on the local file system (see config/storage.yml for options) config.active_storage.service = :local
となっている行を以下のように変更します。
# Store uploaded files on the local file system (see config/storage.yml for options) config.active_storage.service = :amazon
保存先の設定を追加
上記で変更した「:amazon」という保存先の設定を追加します。config/storage.ymlを変更します。
# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) # amazon: # service: S3 # access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> # secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> # region: us-east-1 # bucket: your_own_bucket
となっている行のコメントアウトを外し、各値を設定します。
access_key_idとsecret_access_keyはCredentialsを使って設定します。
access_key_idとsecret_access_keyはCredentialsを使って設定します。
Credentialsの設定
ターミナルで以下のコマンドを実行します。
$ EDITOR=vi rails credentials:edit
すると、Credentialsの設定がviで編集できるようになります。
# aws: # access_key_id: 123 # secret_access_key: 345
となっている行のコメントアウトを外し、access_key_idとsecret_access_keyを設定します。
CORSの設定を変更
Amazon S3のCORSの設定はGUIからは変更できないので、コマンドラインツールのawscliを使います。
awscliのインストールとセットアップは省略します。
適当なディレクトリにCORS.jsonを作成し、以下のように設定します。
awscliのインストールとセットアップは省略します。
適当なディレクトリにCORS.jsonを作成し、以下のように設定します。
{ "CORSRules": [ { "AllowedOrigins": ["http://localhost:3000"], "AllowedMethods": ["GET", "POST", "PUT"], "MaxAgeSeconds": 3000, "AllowedHeaders": ["*"] } ] }
続いて、以下のコマンドを実行します。
$ aws s3api put-bucket-cors --profile s3_config --bucket バケット名 --cors-configuration file://CORS.json
CORS.jsonの内容に不備があるとエラーが帰ってきます。正常にいけば何も帰ってきません。
Amazon S3のコンソール画面でCORSの設定画面を見ると、先ほど作成したCORSの設定が反映されていることがわかります。
Amazon S3 CORS設定
Amazon S3のコンソール画面でCORSの設定画面を見ると、先ほど作成したCORSの設定が反映されていることがわかります。

それでもうまくいかない…
Umm...
実際にリッチテキストエディターで画像を投稿すると、画像だけ無視されて投稿されてしまいます。
画像だけで投稿しようとするとバリデーションエラーが発生します。
ログでは正常にS3にアップロードされているように見えるんですが…
実際にリッチテキストエディターで画像を投稿すると、画像だけ無視されて投稿されてしまいます。
画像だけで投稿しようとするとバリデーションエラーが発生します。
ログでは正常にS3にアップロードされているように見えるんですが…
Started POST "/rails/active_storage/direct_uploads" for ::1 at 2019-09-07 00:07:12 +0900 Processing by ActiveStorage::DirectUploadsController#create as JSON Parameters: {"blob"=>{"filename"=>"759647.jpg", "content_type"=>"image/jpeg", "byte_size"=>1124951, "checksum"=>"aNJX53d715bfIlPCp+kxng=="}, "direct_upload"=>{"blob"=>{"filename"=>"759647.jpg", "content_type"=>"image/jpeg", "byte_size"=>1124951, "checksum"=>"aNJX53d715bfIlPCp+kxng=="}}} (0.1ms) begin transaction ActiveStorage::Blob Create (2.8ms) INSERT INTO "active_storage_blobs" ("key", "filename", "content_type", "byte_size", "checksum", "created_at") VALUES (?, ?, ?, ?, ?, ?) [["key", "xtyzr6n5dqtkrtktaw4eyff6cqx7"], ["filename", "759647.jpg"], ["content_type", "image/jpeg"], ["byte_size", 1124951], ["checksum", "aNJX53d715bfIlPCp+kxng=="], ["created_at", "2019-09-07 00:07:13.831165"]] (1.9ms) commit transaction S3 Storage (1.9ms) Generated URL for file at key: xtyzr6n5dqtkrtktaw4eyff6cqx7 (https://バケット名.s3.ap-northeast-1.amazonaws.com/xtyzr6n5dqtkrtktaw4eyff6cqx7?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIASDZCAGFGPBO5QBPX%2F20190906%2Fap-northeast-1%2Fs3%2Faws4_request&X-Amz-Date=20190906T150713Z&X-Amz-Expires=300&X-Amz-SignedHeaders=content-md5%3Bcontent-type%3Bhost&X-Amz-Signature=759db267c76e158c753e0ccff9a9f488251f83a36d880395005a45b1a8a05613) Completed 200 OK in 993ms (Views: 0.5ms | ActiveRecord: 6.1ms | Allocations: 140789)
追記
config/application.rb
require 'rails/all' require 'active_storage'
Gemfile
gem 'aws-sdk-s3', require: false