Techioz Blog

Rails 5.2 Shrine および Tus サーバー: ファイルを保存するためのカスタム フォルダー構造を作成できない

概要

再開可能なファイルのアップロードに Rails 5.2、Shrine 2.19、tus サーバー 2.3 を使用しています。

ルート.rb

  mount Tus::Server => '/files'

モデル、file_resource.rb

class FileResource < ApplicationRecord
  # adds an `file` virtual attribute
  include ResumableFileUploader::Attachment.new(:file)

コントローラー/files_controller.rb

def create
      file = FileResource.new(permitted_params)
      ...
      file.save

config/initializers/shrine.rb


s3_options = {
  bucket: ENV['S3_MEDIA_BUCKET_NAME'],
  access_key_id: ENV['S3_ACCESS_KEY'],
  secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
  region: ENV['S3_REGION']
}

Shrine.storages = {
  cache: Shrine::Storage::S3.new(prefix: 'file_library/shrine_cache', **s3_options),
  store: Shrine::Storage::S3.new(**s3_options), # public: true,
  tus: Shrine::Storage::Tus.new
}

Shrine.plugin :activerecord
Shrine.plugin :cached_attachment_data

config/initializers/tus.rb

Tus::Server.opts[:storage] = Tus::Storage::S3.new(
  prefix: 'file_library',
  bucket: ENV['S3_MEDIA_BUCKET_NAME'],
  access_key_id: ENV['S3_ACCESS_KEY'],
  secret_access_key: ENV['S3_SECRET_ACCESS_KEY'],
  region: ENV['S3_REGION'],
  retry_limit: 3
)
Tus::Server.opts[:redirect_download] = true

私の問題は、AWS s3 の別のフォルダー構造にファイルを保存するために、Shrine クラスのgenerate_location メソッドをオーバーライドできないことです。

すべてのファイルは s3://bucket/file_library/ (tus.rb で提供されるプレフィックス) 内に作成されます。 s3://bucket/file_library/:user_id/:parent_id/ フォルダー構造のようなものが必要です。

Tus 設定はすべての resumable_file_uploader クラスのカスタム オプションをオーバーライドし、アップロードには影響を及ぼさないことがわかりました。

再開可能ファイル_アップローダー.rb

class ResumableFileUploader < Shrine
  plugin :validation_helpers  # NOT WORKS
  plugin :pretty_location     # NOT WORKS

  def generate_location(io, context = {})  # NOT WORKS
    f = context[:record]
    name = super # the default unique identifier

    ['users', f.author_id, f.parent_id, name].compact.join('/')
  end

  Attacher.validate do                    # NOT WORKS
    validate_max_size 15 * 1024 * 1024, message: 'is too large (max is 15 MB)'
  end

end

それでは、tus オプションを使用して (神社オプションが機能しないため) S3 でカスタム フォルダー構造を作成するにはどうすればよいでしょうか?

解決策

tus サーバーのアップロードは、Shrine にはまったく触れないため、#generate_location は呼び出されませんが、代わりに tus-ruby-server が場所を決定します。

tus サーバーは一時ストレージとしてのみ機能する必要があることに注意してください。通常の直接アップロードと同様に、Shrine を使用してファイルを永続ストレージにコピーする (別名「プロモート」) 必要があります。プロモーション時に #generate_location メソッドが呼び出され、ファイルが目的の場所にコピーされます。これはすべて、デフォルトの神社セットアップで自動的に行われます。