【问题标题】:In Rails how to check if javascript file exists before using javascript_include_tag在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是否存在
【发布时间】:2012-10-01 11:32:00
【问题描述】:

在 rails 3.2 应用程序中,我想在文件中包含 javascript_include_tag 之前检查资产管道中是否存在 javascript 文件。比如:

<% if javascript_file_exists? %>
  <%= javascript_include_tag "#{controller_name}_controller" %>
<% end %>

我想这样做,以便没有 javascript 文件不会导致错误。有没有办法做到这一点?

【问题讨论】:

  • 类似..什么?为什么需要它?
  • 修复了这个问题,并添加了动机。谢谢!

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


【解决方案1】:

更多的 Rails 方法是使用助手。这允许您检查文件的咖啡脚本或 javascript 版本:

def javascript_exists?(script)
  script = "#{Rails.root}/app/assets/javascripts/#{params[:controller]}.js"
  File.exists?(script) || File.exists?("#{script}.coffee") 
end

然后你可以在你的布局中使用它:

<%= javascript_include_tag params[:controller], :media => "all"  if javascript_exists?(params[:controller]) %>

你可以对你的 CSS 做同样的事情:

 -- helper --
 def stylesheet_exists?(stylesheet)
   stylesheet = "#{Rails.root}/app/assets/stylesheets/#{params[:controller]}.css"
   File.exists?(stylesheet) || File.exists?("#{stylesheet}.scss") 
 end

 -- layout --
 <%= stylesheet_link_tag params[:controller], :media => "all"  if stylesheet_exists?(params[:controller]) %>


编辑:更新了#javascript_exists?

我最近对我的javascript_exists? 助手进行了一些更改:

def javascript_exists?(script)
  script = "#{Rails.root}/app/assets/javascripts/#{script}.js"
  extensions = %w(.coffee .erb .coffee.erb) + [""]
  extensions.inject(false) do |truth, extension|
    truth || File.exists?("#{script}#{extension}")
  end
end

在应用布局中调用它:

<%= javascript_include_tag params[:controller]  if javascript_exists?(params[:controller]) %>

现在这将处理更多扩展名并使用注入来确定文件是否存在。然后,您可以根据应用的需要向 extensions 数组添加更多扩展。


EDIT DEUX:更新了#stylesheet_exists?

相同,但对于样式表:

def stylesheet_exists?(stylesheet)
  stylesheet = "#{Rails.root}/app/assets/stylesheets/#{stylesheet}.css"
  extensions = %w(.scss .erb .scss.erb) + [""]
  extensions.inject(false) do |truth, extension|
    truth || File.exists?("#{stylesheet}#{extension}")
  end
end


最后编辑(可能):擦干

def asset_exists?(subdirectory, filename)
  File.exists?(File.join(Rails.root, 'app', 'assets', subdirectory, filename))
end

def image_exists?(image)
  asset_exists?('images', image)
end

def javascript_exists?(script)
  extensions = %w(.coffee .erb .coffee.erb) + [""]
  extensions.inject(false) do |truth, extension|
    truth || asset_exists?('javascripts', "#{script}.js#{extension}")
  end
end

def stylesheet_exists?(stylesheet)
  extensions = %w(.scss .erb .scss.erb) + [""]
  extensions.inject(false) do |truth, extension|
    truth || asset_exists?('stylesheets', "#{stylesheet}.css#{extension}")
  end
end

【讨论】:

  • 这在 Rails 6 中仍然有效/实用吗?
  • @Jake 你告诉我。我已经很多年没有做过 Rails 了。我现在是一名数据工程师。
【解决方案2】:

虽然我知道 application.js 中的资产管道和清单,但我的方法是在 application.js 中保留应用程序的“基本”javascript,并使用

仅加载每个控制器的特定 javascript
<%= javascript_include_tag "application" %> 
<%= javascript_include_tag controller_name if File.exists?("#{Rails.root}/app/assets/javascripts/#{controller_name}.js") %>

在我的 application.html.erb 的末尾,在

【解决方案3】:

我知道这是一个很老的问题,但我建议使用 find_asset 函数。对于 Rails 4,您可以执行以下操作:

<%= javascript_include_tag params[:controller] if ::Rails.application.assets.find_asset("#{params[:controller]}.js") %>

【讨论】:

  • 好主意。这可能取决于 Rails 的版本或我们的偏好,但对于 4 及更高版本,我会使用 controller_name 而不是 params[:controller](以及 action_name,因为特定于页面的 js 文件之间的联系要紧密得多到动作而不是控制器)。
  • 适用于最新的 Ruby 2.2.1 和 Rails 4.2.3。如果需要,您甚至可以省略 .js 扩展名。默认模板不再添加 .js(我的 JS 文件现在只有 .coffee 扩展名),但如果添加,Rails 仍会识别它。
【解决方案4】:

自定义 ViewHelpers 救援!

将此添加到您的ApplicationHelper

module ApplicationHelper
  def controller_stylesheet(opts = { media: :all })
    if Rails.application.assets.find_asset("#{controller_name}.css")
      stylesheet_link_tag(controller_name, opts)
    end
  end

  def controller_javascript(opts = {})
    if Rails.application.assets.find_asset("#{controller_name}.js")
      javascript_include_tag(controller_name, opts)
    end
  end
end

您可以在application.html.erb 中像这样使用它们:

<%= controller_stylesheet %>
<%= controller_javascript %>

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

【讨论】:

  • 不应使用params[:controller]。而是controller.controller_name 描述的here
  • 仅供参考,这适用于 Rails 6 / Ruby 3
【解决方案5】:

在 Rails3.2 中,您只需在 application.js 文件的顶部写入 js 文件列表。例如,

//=require jquery.min
//=require jquery_ujs
//=require general

如果其中一个文件确实不存在(顺便说一句,将它们放在 app/assets/javascripts 中)- 没问题,不会显示任何错误。

【讨论】:

  • 那么通过asset pipeline,每个控制器是否会自动加载manifest文件中指定的与控制器同名的js文件。 IE。 users_controller.rb 会加载 users_controller.js 吗?
  • 此外,您不需要在视图中指定 javascript_include_tag 吗?
  • 不,您必须将//=require users.js 写入application.js。只有这样才能访问 users.js 中的所有逻辑。
  • 在您的布局中输入&lt;%= javascript_include_tag "application" %&gt;。见railscasts.com/episodes/279-understanding-the-asset-pipeline
  • @alex 的方法会用这个users.js 重载EVERY 视图。最好只做你上面做的事情,然后询问Rails.application.assets文件是否存在如果要渲染它。
【解决方案6】:

捕捉错误:

    #/app/helpers/application_helpers.rb

    def javascript_include_tag_if_assets(*args)
      javascript_include_tag(*args)
    rescue Sprockets::Rails::Helper::AssetNotFound
      ''
    end

另外,由于这要求在使用该方法之前进行检查,javascript_include_tag 使用javascript_path,因此您不妨使用它来检查然后捕获该错误。这适用于所有类似 javascript 的资产。对于类似 css 的资产,请使用 stylesheet_path

    #/app/helpers/application_helpers.rb

    def javascript_include_tag_if_assets(*files, **opts)
      files.each { |file| javascript_path(file) }
      javascript_include_tag(*files, **opts)
    rescue Sprockets::Rails::Helper::AssetNotFound
      ''
    end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-21
    • 1970-01-01
    • 1970-01-01
    • 2012-02-10
    • 2021-05-31
    • 2010-09-25
    • 2013-12-21
    相关资源
    最近更新 更多