Shrine gem - как предотвратить удаление загруженных файлов с S3

Я использую гем shrine для хранения изображений в S3 от Ruby on Rails.

Как я могу заставить храм вести себя следующим образом?

1. When uploading files from Frontend, they are stored in S3.
2. When deleting files from Frontend, they are deleted from Database, "but not deleted from S3"

То есть, когда я загружаю изображения в S3, они никогда не удаляются действиями пользователей.

Я нашел аналогичный вопрос, но что я хочу понимаете, это совершенно противоположное условие.


Нынешнее состояние таково.

Я загрузил святыню в ImageUploader в соответствии с docs.

При загрузке файла они сохраняются в S3. И когда я пытаюсь удалить файлы из базы данных, они также удаляются из S3.


Это блок кода, который загружает файлы в S3 и удаляет их из S3.

config/initializers/shrine.rb

require "shrine"
require "shrine/storage/file_system"
require "shrine/storage/s3"


s3_options = {
    access_key_id: ENV[ACCESS_KEY_ID],
    secret_access_key: ENV[SECRET_ACCESS_KEY],
    region: ENV[REGION],
    bucket: ENV[BUCKET],
}

Shrine.storages = {
    cache: Shrine::Storage::S3.new(prefix: ..., **s3_options),
    store: Shrine::Storage::S3.new(prefix: ..., **s3_options),
}


Shrine.plugin :activerecord           
Shrine.plugin :cached_attachment_data 
Shrine.plugin :restore_cached_data 

Shrine.plugin :url_options,
              cache: { public: true, host: ENV[CLOUDFRONT_URL] },
              store: { public: true, host: ENV[CLOUDFRONT_URL] }

На ImageUploader < Shrine установите логику изменения размера. А на модели Photo смонтировать загрузчик как include ImageUploader::Attachment(:image)

При удалении файлов из базы данных я использовал ActiveRecord вот так (на данный момент они также удаляются из S3)

class PhotoController < ApiController

def destroy
  photo = Photo.find(params[:id])
  photo.destroy!

  render json: photo, serializer: PhotoSerializer
end

person batch    schedule 25.08.2020    source источник
comment
Привет, @batch, и добро пожаловать. Не могли бы вы предоставить блоки кода, которые вы использовали для загрузки файла, они хранятся в S3 и для удаления файлов из базы данных. Таким образом, мы действительно могли бы указать вам правильное направление.   -  person ErvalhouS    schedule 25.08.2020
comment
@ErvalhouS Спасибо за ответ! Я только что предоставил блок кода, поэтому буду рад, если вы проверите код.   -  person batch    schedule 26.08.2020
comment
@ErvalhouS Спасибо. Первый способ1 работает отлично! Вы спасли мою жизнь!   -  person batch    schedule 26.08.2020
comment
@batch вы нашли решение, которое работает с обратными вызовами AR, но не удаляет файлы на S3? Я хочу добиться того же, что и ты.   -  person BvuRVKyUVlViVIc7    schedule 27.09.2020


Ответы (3)


Есть два способа добиться желаемого.

Способ 1: пропустите обратные вызовы ActiveRecord, которые запускают обратные вызовы Shrine, используя delete вместо destroy на вашем контроллере.

Способ 2: добавьте зеркалирование и резервное копирование в конфигурацию Shrine, например так

 Shrine.storages = { cache: ..., store: ..., backup: ... }

 Shrine.plugin :mirroring, mirror: { store: :backup }
person ErvalhouS    schedule 26.08.2020

Я нашел хороший и чистый способ...

В вашем инициализаторе shrine.rb просто создайте собственный класс:

class NoDeletionShrineS3Storage < Shrine::Storage::S3
  def delete(id)
    true
  end

  def delete_prefixed(delete_prefix)
    true
  end

  def clear!(&block)
    true
  end
end


Shrine.storages = {
  cache: Shrine::Storage::FileSystem.new..), # temporary
  store: NoDeletionShrineS3Storage.new(
      bucket: "mybucket", # required
      region: "eu-central-1", # required
      access_key_id: '123..',
      secret_access_key: '123..',
    )
}

person BvuRVKyUVlViVIc7    schedule 29.09.2020

Вы также можете использовать плагин keep_files Shrine: https://shrinerb.com/docs/plugins/keep_files

person Dom Eden    schedule 07.05.2021