仅在资产存在的情况下包括资产

在我们当前的rails应用程序中,我们遵循某些模式来包含脚本和样式表等资产。

例如,一个这样的模式是(布局内的代码):

= stylesheet_link_tag controller.controller_name 

这里的问题是并非所有控制器都有相关的样式表。 检查资产是否存在的最佳方法是什么? 具体来说,我知道由于缓存破坏资产名称,这里有一些技巧。

最后想出了这一个。 资产存在可以检查如下:

 YourApp::Application.assets.find_asset("#{asset}.css").nil? 

答案是:

 = stylesheet_link_tag controller.controller_name if YourApp::Application.assets.find_asset("#{controller.controller_name}.css") 

之前我找到了这个答案,我们很乐意在我们的应用程序中使用find_asset (Rails 3.2.16),直到有一天它开始轰炸。

经过一番挖掘后,事实certificate,即使在生产环境中,启用资产预编译,第一次调用find_asset也会尝试实际编译它正在寻找的资产,即使该资产已经预编译。 您可以想象,这不是一个好消息 – 在我们的具体情况下,我们将Compass库文件放入样式表中,该样式表在dev和预编译期间工作,但不在生产中,Compass不在资产负载中路径。

长话短说, find_asset不是一种确定资产是否可以包含的防弹方式。 你可以在有人试图提交的关于此问题的问题中阅读更多关于它的内容,随后关闭它并不是一个错误: https : //github.com/sstephenson/sprockets/issues/411

确定资产是否存在以及在编译和预编译模式下工作的真正方法在上述问题的文件管理器需要跳过的环节中得到了certificate。 这是他修复的差异: https : //github.com/fphilipe/premailer-rails/pull/55/files

我把它放在这里,希望发现这个的其他Google员工不会陷入我所做的同一个陷阱!

包含基于控制器名称的资产

 <% controller_asset = controller.controller_name %> <%= stylesheet_link_tag controller_asset if YourApp::Application.assets.find_asset(controller_asset) %> 

包含基于控制器名称和操作名称的资产(对我有用)

 <% action_asset = "#{controller.controller_name}/#{controller.action_name}" %> <%= stylesheet_link_tag action_asset if YourApp::Application.assets.find_asset(action_asset) %> 

当然最好不要保留这些代码,而是将其放在帮助器中。

 = stylesheet_link_tag controller.controller_name if File.exists?(File.join(Rails.public_path, 'assets', "#{controller.controller_name}.css")) 

简单的ViewHelpers

这是我自己使用的。 将其添加到您的ApplicationHelper

 module ApplicationHelper def controller_stylesheet(opts = { media: :all }) if Rails.application.assets.find_asset("#{params[:controller]}.css") stylesheet_link_tag(params[:controller], opts) end end def controller_javascript(opts = {}) if Rails.application.assets.find_asset("#{params[:controller]}.js") javascript_include_tag(params[:controller], opts) end end end 

并在application.html.haml使用它们:

 = controller_stylesheet = controller_javascript 

注意:这适用于所有.js,.coffee,.css,.scss,即使它只是说.css和.js