在我的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..
我显然正在做一些违反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
实际上并没有调用资产路径而是app文件夹,这似乎也违背了Rails惯例。
我以为localhost会工作
config.asset_host = "http://localhost"
但JS文件再次失败
我确定我忽略了一些显而易见的事情。感谢正确方向的指针。
答案 0 :(得分:2)
我认为这归结为混合了路径和URL的各种含义。
如果要将资产文件从不同的服务器提供给应用程序(即从cdn),则首先使用asset_host
。如果查看asset_path
rails的源,首先计算资产的路径,然后预先设置主机。这会创建一个浏览器稍后会尝试获取的网址,因此在/Users/andy/some_app
之类的路径前添加不会有意义
将其设置为http://localhost
不起作用,因为它采用默认的http端口,而capybara在随机端口上运行您的应用。您不应该在测试环境中设置asset_host
。
转到carrierwave,avatar.url
还从浏览器的角度提供了URL(在您的情况下只是路径部分) - 它被设计为嵌入在img标记中,例如。另一方面,open
方法对浏览器和服务器一无所知,只想获得本地文件系统上文件的路径。
如果您需要本地文件系统路径,则需要avatar.path
方法。据我所知,路径上没有default_url
的等价物,所以你需要做好准备让它返回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