LoginSignup
9
7

More than 3 years have passed since last update.

Active Storageでキー名を指定するには

Last updated at Posted at 2020-08-16

環境: Rails 5.2 / 6.0

RailsのActive Storageを使ってAWS S3にファイルを保存すると、自動的に whZ3Y8VP3XV8WGqjyK2dyZ5j のようなキー名になります。これを images/developmenet/whZ3Y8VP3XV8WGqjyK2dyZ5j のようにフォルダ分けする方法です。Rails Guildesには載っていませんが、Active Storageのソースコードを見てて気付きました。

次のモデルがあるとします。

class User < ApplicationRecord
  has_one_attached :image
end

ふつうの使い方では、user.image.attachActionDispatch::Http::UploadedFile を渡します。

user.image.attach(file)

user.image.attach には ActionDispatch::Http::UploadedFile だけでなく、ActiveStorage::Blob オブジェクトも渡せます。ActiveStorage::Blob を直接使ってアップロードし、その後にUserモデルにくっ付ける、ということができます。

次の例では、ActiveStorage::Blob にキーを指定して new したあと、upload メソッドにIO オブジェクトを指定してアップロードし、それから attach メソッドに渡しています。key に指定した文字列がS3のキー名なります。

def save_image(user, file)
  if Rails.configuration.active_storage.service == :amazon
    key = "images/#{Rails.env}/#{SecureRandom.hex}"
    blob = ActiveStorage::Blob.new(key: key,
      filename: file.original_filename, content_type: file.content_type)
    blob.upload file.to_io

    user.image.attach(blob)
  else
    user.image.attach(file)
  end
end

ActiveStorage::Blob のソースでは、キーは次のように作られています。

activestorage-6.0.3.2/app/models/active_storage/blob.rb
class ActiveStorage::Blob < ActiveRecord::Base
# 略
  has_secure_token :key
# 略
  def key
    # We can't wait until the record is first saved to have a key for it
    self[:key] ||= self.class.generate_unique_secure_token
  end

generate_unique_secure_token メソッドは ActiveRecord::SecureToken のソース中にあります。

activerecord-6.0.3.2/lib/active_record/secure_token.rb
      def generate_unique_secure_token
        SecureRandom.base58(24)
      end

上記のサンプルは次のようにも書けます。ActiveStorage::Blob にキーを作らせておいてから、プレフィックスを付ける方法です。

blob = ActiveStorage::Blob.new(filename: file.original_filename,
  content_type: file.content_type)
blob.key = "images/#{Rails.env}/#{blob.key}"
blob.upload file.to_io

Active Storage関連のテーブル

以下、ご参考までにメモ。

Active Storage関連のテーブルには、active_storage_blobsactive_storage_attachments があり、それぞれモデルクラス ActiveStorage::BlobActiveStorage::Attachment が対応しています。どちらも ActiveRecord::Base のサブクラスなので、ふつうのモデルのように使えます。

  • ActiveStorage::Blob : アップロードしたファイルを表すモデル
  • ActiveStorage::Attachment : モデルへのファイルの添付を表すモデル

activestorage.png

9
7
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
7