概要
ファイルアップロード機能を実装する際に、Rails5.2で導入されたActive Storageを使ってみました。
実際に使ってみて困ったことがいくつかあったので、誰かのために役立てばと思いまとめておきます。
環境
- Rails 6.0.2.1
- Ruby 2.6.5
結論: 困った点と解決方法
困った点
Active Storage のサービスとして、Amazon S3を利用して、以下の点で困りました。
- アップロード時にアクセス権限(S3のACL)を
public-read
に設定できない - ファイルを保存するディレクトリが設定できない
(正確には、S3にはフォルダという概念は存在しないので、ファイルのキー名につけるprefixがつけられない)
解決方法
以下のパッチで対応しました。
この書き方だと、ファイルごとにアクセス権限を変更したり、ディレクトリを変更したりといった細かい設定はできません。
# lib/active_storage/service/better_s3_service.rb
require 'aws-sdk-s3'
require 'active_storage/service/s3_service'
require 'active_support/core_ext/numeric/bytes'
module ActiveStorage
class Service::BetterS3Service < Service::S3Service
attr_reader :root
def initialize(bucket:, upload: {}, root:, **options)
@root = root
super(bucket: bucket, upload: upload, **options)
end
def upload(key, io, checksum: nil, content_type: nil, **)
instrument :upload, key: key, checksum: checksum do
object_for(key).put(upload_options.merge(body: io, content_md5: checksum, content_type: content_type, acl: 'public-read'))
rescue Aws::S3::Errors::BadDigest
raise ActiveStorage::IntegrityError
end
end
private
def object_for(key)
path = root.present? ? File.join(root, key) : key
bucket.object(path)
end
end
end
以下のようにroot
を設定する。
# config/storage.yml
amazon:
service: BetterS3
root: root-directory
1. アップロード時にアクセス権限(S3のACL)
アップロードしたファイルにパブリック読み取りアクセス許可をつけようとしましたが、v6.0.2.1
ではアップロード時に権限を設定することはできません。
ただ2019年7月のPR1で、public
というオプションをstorage.yml
で設定できる変更がマージされたので、将来的にはサポートされそうです。
いくつかの記事2やissueへのコメント3を参考にしてパッチをあてる形で対応しました。
2. ファイルを保存するディレクトリが設定できない
S3にアップロードするファイルにprefixをつけて、フォルダを作成したいことは多々あると思いますが、現時点(v6.0.2.1)のActive Storageではサポートされていません。
「Active Storageでフォルダーを使う」といった旨のissue4 で議論されていますが、あまり議論が進んでいないので、まだまだサポートされなそうですね…。
こちらも先述のissue4にあったパッチ5を利用して、config/storage.yml
から特定のディレクトリ名を設定できるようにしました。
まとめ
Active Storageを使ってみましたが、意外とサポートされていない機能が多く、少し驚きました。
Delyさんの記事にもありましたが、Rails本体に入っていても過信せず、使う前にユースケースを満たしているか利用すべきだと勉強になりました。
読んでいただきありがとうございました!
-
Permanent URLs for Active Storage blobs by peterzhu2118 · Pull Request #36729 · rails/rails · GitHub ↩
-
ActiveStorage: Allow access to backing file from Service API · Issue #31419 · rails/rails · GitHub ↩
-
Folder with active storage · Issue #32790 · rails/rails · GitHub ↩ ↩2
-
(Folder with active storage · Issue #32790 · rails/rails · GitHub) ↩