【Rails】ActionTextでアップロードした画像の保存先がローカルから変更できない😥

2022年6月15日 22:19

はじめに

Rails6の新機能「ActionText」はお手軽にリッチテキストエディターが利用できます。
ActionTextでアップロードした画像の保存先は、デフォルトではローカル(本番環境ならサーバー上)になっています。Railsアプリのデプロイ先としてHerokuを使うことが多いと思いますが、Herokuは定周期でデプロイ時の状態に戻していまいますので、デプロイ後にActionTextでアップロードした画像は時間が経つと消えてしまいます。
そこで、ActionTextでアップロードした画像の保存先をローカルから外部のクラウドストレージ(今回はAmazon S3)に変更したいのですが、うまくいきませんでした😥
現時点までに試した手順を備忘として残しておきます。もし、解決方法を知っている方がいましたら教えていただけると助かります…

ActiveStorageについて

ActionTextは画像のアップロードにActiveStorageを使用していますので、ActiveStorageの設定を変更していきます。

画像の保存先を変更

config/environments/配下にあるファイルを変更します。
開発環境なら「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を使って設定します。

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を作成し、以下のように設定します。
{
  "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設定

それでもうまくいかない…

Umm...
実際にリッチテキストエディターで画像を投稿すると、画像だけ無視されて投稿されてしまいます。
画像だけで投稿しようとするとバリデーションエラーが発生します。
ログでは正常に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

関連記事

【Rails】Railsアップグレードまとめ
# はじめに Ruby on Railsに限らず、何らかのフレームワークを使ってWebシステムを構築している場合、フレームワークのアップグレード作業は避けて通れません。 一般的にフレームワークはバージョン毎にEOL (End of Life [...]
2022年10月1日 14:32
【Rails】ユーザー登録時に行うメールアドレス認証機能の実装方法
# はじめに ユーザー登録/解除やログイン/ログアウトといった認証機能の導入に「devise」というGemを使っている人は多いと思います。「devise」では以下のように記述するだけで、ユーザー登録時に確認メールを送付しメールアドレス認証を行う機 [...]
2022年9月24日 14:24
【Rails】モデルに列挙型(enum)を定義し、使いこなす方法
# はじめに Railsはモデルでカラム名と同名の列挙型(enum)を定義することで、カラムと列挙型の変数を紐付けることができます。カラムと列挙型の変数を紐付けると、カラムに対して様々な便利な使い方ができるようになります。 本記事では、モデ [...]
2022年9月3日 10:29
【Rails】RailsでCORSとPreflight requestの設定を行う方法
# はじめに RailsアプリをAPIサーバーとして構築するには、CORS (Cross-Origin Resource Sharing)と Preflight requestの設定を行う必要があります。APIサーバーは外部からの要求に対して処理 [...]
2022年8月27日 10:44
【Ruby】Bundlerを使ってRubyGemsを作成/公開する方法
# はじめに Bundlerを使ってRubyGemsを作成および公開する方法について説明します。Bundlerを使わずにRubyGemsを作成/公開する方法については以下の記事を参照してください。 <iframe class="hatena [...]
2022年7月12日 23:18
【Ruby】RubyGemsを作成/公開する方法
# はじめに RubyGemsを作成および公開する方法について説明します。Bundlerを使ってRubyGemsを作成する方法については以下の記事を参照してください。 <iframe class="hatenablogcard" style [...]
2022年7月11日 21:52
【Rails】M1チップ搭載MacでRuby on Railsの開発環境構築
# はじめに M1チップ搭載MacにRuby on Railsの開発環境を構築する手順を記載します。 - MacBook Air (M1, 2020) - macOS Monterey 12.3.1 # Homebrew ## [...]
2022年5月5日 11:56
【Rails】Rakeタスクの基本情報と作成・実行方法
# はじめに Railsには標準でRakeというGemが同梱されています。RakeはRubyで実装されたMake(UNIX系のOSで使用できるコマンド)のようなビルド作業を自動化するツールです。Ruby Make、略してRakeというわけですね。 [...]
2022年3月7日 22:12