为什么 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
这个问题出现在我的 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