【问题标题】:Include Assets Only If They Exist仅包含存在的资产
【发布时间】:2012-01-02 15:32:59
【问题描述】:

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

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

= stylesheet_link_tag controller.controller_name

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

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 asset-pipeline


    【解决方案1】:
    = stylesheet_link_tag controller.controller_name if File.exists?(File.join(Rails.public_path, 'assets', "#{controller.controller_name}.css"))
    

    【讨论】:

    • 我没有测试过这段代码,但乍一看似乎没有考虑缓存破坏后缀。例如。控制器-181432da64a0609a7571e391af2c4d6c.css.
    • Rails 会复制原始文件和带有摘要后缀的文件。也许你可以把Rails.public_path改成Rails.root, 'app/assets'
    • 我没有看到带有摘要后缀的原始文件,但这是在开发环境中。
    • 我也对使用 Rails.root 'app/assets' 犹豫不决,因为我必须考虑所有不同类型的资产(sass、scss、css 等)。必须有类似asset_exists的东西吗?
    【解决方案2】:

    终于想通了。资产是否存在可以检查如下:

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

    答案是:

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

    【讨论】:

    • 只有在预编译设置为 true 的情况下才有效?它在大多数生产环境中都会失败。
    • 也应该小心,因为这只会包含 *.css 文件,而忽略 *.scss 和 *.sass。
    • 我强烈敦促问题作者阅读下面@randy 的答案(link),因为这意味着这个(当前接受的)答案将在生产环境中引起真正的问题,即,总是重新编译资产。
    【解决方案3】:

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

    经过一番挖掘,事实证明,即使在启用资产预编译的生产环境中,对find_asset 的第一次调用也会尝试实际编译它正在寻找的资产,即使该资产已经被预编译。你可以想象,这不是一个好消息——在我们的具体案例中,我们将 Compass 库文件拉入到样式表中,该样式表在开发和预编译期间工作,但在生产环境中不起作用,因为 Compass 不在资产加载中路径。

    长话短说,find_asset 不是确定资产是否可包含的万无一失的方法。您可以在有人尝试提交的关于此问题的问题中阅读更多相关信息,该问题随后因不是错误而被关闭:https://github.com/sstephenson/sprockets/issues/411

    确定资产是否存在以及在编译和预编译模式下工作的真正方法在上述问题的提交者需要跳过的箍中得到证明。这是他修复的差异:https://github.com/fphilipe/premailer-rails/pull/55/files

    我将其放在这里是希望其他发现此问题的 Google 员工不会落入与我相同的陷阱!

    【讨论】:

      【解决方案4】:

      根据控制器名称

      包含资产
      <% 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) %>
      

      当然,最好不要让这段代码保持原样,而是将它放在帮助程序中。

      【讨论】:

        【解决方案5】:

        简单的 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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-13
          • 2018-12-06
          • 1970-01-01
          • 1970-01-01
          • 2021-05-14
          • 1970-01-01
          相关资源
          最近更新 更多