9

在 rails 3 中,要将管道中的资产用作default_urlcarrierwave上传器,您执行了以下操作:

class MyUploader
  # Include the Sprockets helpers for Rails 3.1+ asset pipeline compatibility:
  include Sprockets::Helpers::RailsHelper
  include Sprockets::Helpers::IsolatedHelper

  def default_url
    # For Rails 3.1+ asset pipeline compatibility:
    asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
  end
end

在 rails 4 中,管道已被抽象到sprockets-rails gem/railtie 中,因此上面将为您提供:

未初始化的常量 Sprockets::Helpers

查看sprockets-rails gem,替换助手似乎是Sprockets::Rails::Helper. 但是包含这个模块,asset_path("fallback/default.png")返回,简单:

# wrong:
"/fallback/default.png"

不是我期望的资产和摘要感知 URL:

"/assets/fallback/default-b3beee1588afe2ae582c64888cd007db.png"

如何asset_path在视图之外获得正确的行为?

4

1 回答 1

19

TL;博士:

什么都不要include。请改用辅助代理,如下所示:

def default_url
  ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
end

血腥细节:

Sprockets::Rails::Helper使用 sprockets manifest 来正确定位和消化资产。一旦它被抽象为 rails 4 的 gem,这个清单就开始由 railtie 设置。因此,简单地include将模块的方法添加到我们的类中并不足以将清单拉入,并且asset_path(错误)表现得相应。

值得庆幸的是,有一个经常被忽视的 ActionController::Base.helpers类方法:

提供代理以从视图外部访问辅助方法。

就像文档说的那样,它充当辅助代理,可能从一开始就应该用于此目的(在命名空间中包含辅助模块会冒着使用未使用的方法污染类并可能覆盖内容的风险,因此使用代理是更好的选择)。

可能还有一些相当于Sprockets::Helpers::IsolatedHelper这些黑客的东西,足以提供Sprockets::Rails::Helper完成工作所需的东西。但代理是,恕我直言,一个更优雅的解决方案。所以我停止了搜索。

于 2013-05-17T13:04:35.837 回答