不使用 S3 时,ActiveStorage service_url && rails_blob_path 无法生成完整的 url

ActiveStorage service_url && rails_blob_path cannot generate full url when not using S3

我有一个基本的 ActiveStorage 设置,其中一个型号 has_many_attached :file_attachments。在其他地方的服务中,我试图生成一个 link 以在主应用程序(电子邮件、工作等)之外使用。

在生产中使用 S3 我可以: item.file_attachments.first.service_url 并且我得到了一个合适的 link 到 S3 bucket+object。

我无法使用rails指南中规定的方法:Rails.application.routes.url_helpers.rails_blob_path(item.file_attachments.first)

它的错误是: ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true 我可以给它传递一个 host: 'http://....' 参数,它很高兴,尽管它仍然没有生成完整的 URL,只是路径。

开发中我正在使用磁盘支持的文件存储,但我不能使用任何一种方法:

> Rails.application.routes.url_helpers.rails_blob_path(item.file_attachments.first)
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true

在此处设置主机也不会生成完整的 URL。

在生产中 service_url 有效,但是在开发中我得到错误:

> item.file_attachments.first.service_url
ArgumentError: Missing host to link to! Please provide the :host parameter, set default_url_options[:host], or set :only_path to true

并且指定主机没有帮助:

item.file_attachments.first.service_url(host:'http://localhost.com')
ArgumentError: unknown keyword: host

我也试过添加

config.action_mailer.default_url_options = { :host => "localhost:3000" }
config.action_storage.default_url_options = { :host => "localhost:3000" }
Rails.application.routes.default_url_options[:host] = 'localhost:3000'

没有成功。

我的问题是 - 我怎样才能以一种既适用于开发又适用于生产的方式获得完整的 URL? 或者我应该在哪里设置主机?

Active Storage 的磁盘服务希望在 ActiveStorage::Current.host 中找到 URL 代的主机。

当您手动调用 ActiveStorage::Blob#service_url 时,请确保已设置 ActiveStorage::Current.host。如果你从控制器调用它,你可以继承 ActiveStorage::BaseController。如果这不是一个选项,请在 before_action 挂钩中设置 ActiveStorage::Current.host

class Items::FilesController < ApplicationController
  before_action do
    ActiveStorage::Current.host = request.base_url
  end
end

在控制器之外,使用ActiveStorage::Current.set提供主机:

ActiveStorage::Current.set(host: "https://www.example.com") do
  item.file_attachments.first.service_url
end

我遇到了类似的问题。由于容器设置,我不得不强制端口不同。在我的例子中,ActiveStorage 完成的重定向包括了错误的端口。对我来说,调整 default_url_options 有效:

before_action :configure_active_storage_for_docker, if: -> { Rails.env.development? }

def configure_active_storage_for_docker
  Rails.application.routes.default_url_options[:port] = 4000
end

我需要 url 存储在 ActiveStorage 中的图像。

图像是

Post.first.image

错误

Post.first.image.url
Post.first.image.service_url

url_for(Post.first.image)