为什么 Carrierwave 和 asset pipeline 似乎对 config.asset_host 的解释不同?

Why do Carrierwave and asset pipeline appear to interpret config.asset_host differently?

这个问题出现在我的 Rails 应用程序中的 Prawn PDF 生成器中,我有以下行:

image open(@user.avatar.url)

在测试中,此行开始失败并出现以下错误:

No such file or directory @ rb_sysopen - /images/fallback/default.png

Avatar 是 Carrierwave 上传器,带有默认图片 (see here)

def default_url(*args)
  ActionController::Base.helpers.asset_path("images/fallback/default.png" )
end

这似乎是一个简单的解决方案 — 在 test.rb

中定义资产主机
config.asset_host = Rails.root.join('app', 'assets').to_s

但随后我所有启用 JS 的功能测试开始失败

Capybara::Poltergeist::JavascriptError:
One or more errors were raised in the Javascript code on the page.
ReferenceError: Can't find variable: SomeVariable

因为路径是用两个 assets 构建的,例如

...app/assets/assets/jquery..

我显然正在做一些 "unconventional" 违背 Rails 做事方式的事情。所以我想知道这里的约定是什么。

一个解决方案是将我定义资产文件夹的位置从 test.rb 移动到上传器。

#config/environments/test.rb
config.asset_host = Rails.root.join('app').to_s
#app/uploaders/avatar.eb
def default_url(*args)
  ActionController::Base.helpers.asset_path("assets/images/fallback/default.png" )
end

但这意味着 helpers.asset_path 实际上调用的不是资产路径而是应用程序文件夹,这似乎又违反了 Rails 约定。

我原以为本地主机可以工作

config.asset_host = "http://localhost"

但 JS 文件再次失败

我确定我在这里忽略了一些明显的东西。感谢指向正确方向的指针。

我认为这归结为混淆了路径和 URL 的各种含义。

首先使用 asset_host 当您想要将您的资产文件从不同的服务器提供给您的应用程序时(即从 cdn)。如果您查看 asset_path 的来源,rails 首先计算资产的路径,然后在主机前添加。这会创建一个 URL 浏览器稍后将尝试获取该路径,因此在前面加上 /Users/andy/some_app 之类的路径没有意义

将其设置为 http://localhost 不起作用,因为它采用默认的 http 端口,而水豚在随机端口上运行您的应用程序。您永远不需要在测试环境中设置 asset_host

转到载波,avatar.url 还从浏览器的角度提供 URL(在您的情况下只是路径部分)- 它旨在嵌入 img 标签中例如。另一方面,open 方法对浏览器和服务器一无所知,只需要本地文件系统上文件的路径。

如果你想要本地文件系统路径,那么你需要 avatar.path 方法。据我所知,路径没有 default_url 的等效项,因此您需要准备好将其设为 return nil(并将其替换为后备路径)

#config/environments/test.rb
# do not set config.asset_host

#pdf_generator.rb
image open(@user.avatar.path)

#app/uploaders/avatar.rb
def path(*args)
  if model.avatar?
    super
  else
    "#{Rails.root}/app/assets/images/fallback/" + ["default_",version_name, ".png"].compact.join('')
  end
end