Rails Rails 6.1 ActiveStorage 支持多个存储服务了

hegwin · 2021年06月29日 · 最后由 gogo589 回复于 2021年07月04日 · 980 次阅读

Rails >= 6.1 开始,ActiveStorage 开始支持多个 storage service,可能不算新闻(这里有篇 blog 介绍),但是最近升上 6.1 来才用到它,分享一下。

背景

在存储的时候,可能会有不同的存储服务,比如我们的要把图片存在 Cloudinary,其他文件存在 Amazon S3。在 6.1 之前,我们是打了一个 monkey patch;在 6.1 之后,就可以直接配置啦。

6.1 之前的做法

# config/initializers/activestorage.rb
Rails.application.config.to_prepare do
  ActiveStorage::Blob.class_eval do
    alias_method :original_service, :service

    def service
      return original_service if self.image?
      @service ||= load_active_storage_service(:amazon)
    end

    private

    def load_active_storage_service(service)
      ActiveStorage::Service.configure service, Rails.configuration.active_storage.service_configurations
    rescue => e
      raise e, "Cannot load service #{service}`:\n#{e.message}", e.backtrace
    end
  end
 # ...
end

现在的做法

Monkey patch 就可以完全去掉了,因为 service 变得可以配置了;config/storage.yml 可以稍微修改下:

amazon:
  service: S3
  access_key_id: <%= ENV['s3_access_key_id'] %>
  secret_access_key: <%= ENV['s3_secret_access_key'] %>
  bucket: <%= ENV['s3_bucket'] %>
  region: <%= ENV['s3_region'] %>
cloudinary:
  service: Cloudinary
  fetch_format: auto
  quality: auto
  secure: true
  folder: <%= 'dev' if Rails.env.development? %>

然后在模型里,就可以这样:

class Posting < ApplicationRecord
  has_many_attached :images, service: :cloudinary
  has_one_attached :thumbnail, service: :cloudinary
end

class Project < ApplicationRecord
  has_one_attached :doc, service: :amazon
end
暂无回复。
需要 登录 后方可回复, 如果你还没有账号请 注册新账号