Include Assets Only If They Exist

前端 未结 5 1727
情歌与酒
情歌与酒 2021-02-19 07:41

In our current rails app, we are following certain patterns for including assets such as scripts and stylesheets.

For instance, one such pattern is (code inside the layo

相关标签:
5条回答
  • 2021-02-19 07:59
    = stylesheet_link_tag controller.controller_name if File.exists?(File.join(Rails.public_path, 'assets', "#{controller.controller_name}.css"))
    
    0 讨论(0)
  • 2021-02-19 08:09

    I had found this answer before and we'd been happily using find_asset in our application (Rails 3.2.16), until one day it started bombing out.

    After some digging, it turns out that even in a production environment, with asset precompilation enabled, the first call to find_asset will attempt to actually compile the asset it's looking for, even if that asset has been precompiled already. As you can imagine, this is not good news -- in our specific case, we were pulling in a Compass library file into a stylesheet, which worked in dev and during precompile, but not in production, where Compass was not in the assets load path.

    Long story short, find_asset is not a bulletproof way to determine if an asset is available to include. You can read a bunch more about it in the issue someone tried to file about this, and which was subsequently closed as not a bug: https://github.com/sstephenson/sprockets/issues/411

    The real way to determine if an asset exists, and which works in both compile and precompile modes is demonstrated in the hoops that the filer of the above issues needed to jump through. Here's the diff for his fix: https://github.com/fphilipe/premailer-rails/pull/55/files

    I'm putting this here in hopes that other Googlers who find this don't fall into the same trap I did!

    0 讨论(0)
  • 2021-02-19 08:12

    Simple ViewHelpers

    This is what I use myself. Add this to your 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
    

    and use them like this in your application.html.haml:

    = controller_stylesheet
    = controller_javascript
    

    Note: This works with all .js, .coffee, .css, .scss even though it just says .css and .js

    0 讨论(0)
  • 2021-02-19 08:13

    To include an asset based on controller name

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

    To include an asset based on controller name and action name (was useful for me)

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

    And of course it'd be better not to leave this code as it is, but rather place it in a helper.

    0 讨论(0)
  • 2021-02-19 08:20

    Finally figured this one out. Asset existence can be checked as follows:

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

    The answer would then be:

    = stylesheet_link_tag controller.controller_name if YourApp::Application.assets.find_asset("#{controller.controller_name}.css")
    
    0 讨论(0)
提交回复
热议问题