经过一番挖掘,我发现了问题所在。问题出在 Rails 中,特别是 Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path。Sprockets::Helpers::RailsHelper::AssetPaths 继承自 ActionView::AssetPaths 并覆盖了许多方法。当通过 Sass::Rails::Resolver#public_path 方法调用 sass-rails 的 compute_public_path 时,rails sprocket helper 将承担解析资产的任务。Sprockets::Helpers::RailsHelper::AssetPaths#compute_public_path 遵循超级,即 ActionView::AssetPaths#compute_public_path。在这个方法中有一个has_request的条件吗?在 rewrite_relative_url_root 上,如下所示:
def compute_public_path(source, dir, ext = nil, include_host = true, protocol = nil)
...
source = rewrite_relative_url_root(source, relative_url_root) if has_request?
...
end
def relative_url_root
config = controller.config if controller.respond_to?(:config)
config ||= config.action_controller if config.action_controller.present?
config ||= config
config.relative_url_root
end
如果您查看 rewrite_relative_url_root 的内部结构,它依赖于存在的请求以及从控制器变量派生它以解析相对 url 根的能力。问题是当 sprockets 为 sass 解析这些资产时,它没有控制器存在,因此没有请求。
上面的解决方案对我来说在开发模式下不起作用。这是我现在用来使其工作的解决方案:
module Sass
module Rails
module Helpers
protected
def public_path(asset, kind)
resolver = options[:custom][:resolver]
asset_paths = resolver.context.asset_paths
path = resolver.public_path(asset, kind.pluralize)
if !asset_paths.send(:has_request?) && ENV['RAILS_RELATIVE_URL_ROOT']
path = ENV['RAILS_RELATIVE_URL_ROOT'] + path
end
path
end
end
end
end