在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在
Posted
技术标签:
【中文标题】在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在【英文标题】: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 文件不会导致错误。有没有办法做到这一点?
【问题讨论】:
类似..什么?为什么需要它? 修复了这个问题,并添加了动机。谢谢! 【参考方案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 中的所有逻辑。
在您的布局中输入<%= javascript_include_tag "application" %>
。见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
【讨论】:
以上是关于在 Rails 中如何在使用 javascript_include_tag 之前检查 javascript 文件是不是存在的主要内容,如果未能解决你的问题,请参考以下文章
Rails如何检测是不是使用javascript / jQuery插入了部分
如何使用 AJAX 请求将用户在类变量中的 HTML5 位置从 JavaScript 传递到 Rails 控制器?
如何在 ruby on rails 和 javascript 中使用 data-post 接收数据
如何在 ruby on rails 中访问 rails 助手和嵌入资产 javascript 文件中的 ruby?