Ruby on rails 加载javascript并在rails中的特定控制器和特定操作上运行它

Ruby on rails 加载javascript并在rails中的特定控制器和特定操作上运行它,ruby-on-rails,ruby,Ruby On Rails,Ruby,我有标准的rails应用程序格式 我有这些控制器: class StaticPagesController < ApplicationController def help end def about end end 我假设第一个问题应该通过app/assets/javascripts/application.js文件通过添加以下规则来解决: //= require jquery //= require jquery_ujs //= require bootstra

我有标准的rails应用程序格式

我有这些控制器:

class StaticPagesController < ApplicationController

  def help
  end

  def about
  end

end
我假设第一个问题应该通过
app/assets/javascripts/application.js
文件通过添加以下规则来解决:

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .

//= (isItStaticController? render static_page.js.coffee)

但是我想知道如何才能做到这一点?

不幸的是,您不能向应用程序js文件添加条件,因为它是在部署应用程序时预编译的。 在这里,我可以看到两种可能的方法适用于您:

1) 如上所述,将所有javascript放在一个文件中,然后在代码中设置页面,如下所示:

<script> page = "Help" </script> or <script> page = "About" </script>
<% content_for :head %>
  <%= javascript_include_tag 'help' %>
<% end %>
2) 另一个选项是为每个页面创建单独的js文件,然后通过yield:head块将它们合并到布局中。在您的帮助文件中,它将如下所示:

<script> page = "Help" </script> or <script> page = "About" </script>
<% content_for :head %>
  <%= javascript_include_tag 'help' %>
<% end %>


我个人喜欢在我的应用程序中使用第二种方法

不幸的是,您无法向应用程序js文件添加条件,因为它是在部署应用程序时预编译的。 在这里,我可以看到两种可能的方法适用于您:

1) 如上所述,将所有javascript放在一个文件中,然后在代码中设置页面,如下所示:

<script> page = "Help" </script> or <script> page = "About" </script>
<% content_for :head %>
  <%= javascript_include_tag 'help' %>
<% end %>
2) 另一个选项是为每个页面创建单独的js文件,然后通过yield:head块将它们合并到布局中。在您的帮助文件中,它将如下所示:

<script> page = "Help" </script> or <script> page = "About" </script>
<% content_for :head %>
  <%= javascript_include_tag 'help' %>
<% end %>


我个人喜欢在我的应用程序中使用第二种方法

我会解释我是如何处理这件事的。在我的
ApplicationController
中,我有一个方法,在每次请求时从
前过滤器运行

def prepare_common_variables
  controller_name = self.class.name.gsub(/Controller$/, '')
  if !controller_name.index('::').nil?
    namespace, controller_name = controller_name.split('::')
  end

  @default_body_classes = ["#{controller_name.underscore}_#{action_name} ".downcase.strip]
  @default_body_classes = ["#{namespace.underscore}_#{@default_body_classes.join}".strip] if !namespace.nil?
end
在app/views/layouts/application.html.erb中,我有以下内容

<body class="<%= yield :body_classes %> <%= @default_body_classes.join(' ') %>">
接下来,在我的
app/assets/javascripts/application.js.erb

Array.prototype.diff = function(a) {
  return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};

var DEEFOUR = (function (deefour) {
  deefour.Utility = (function (utility) {
    utility.hasBodyClass = function() {
      var args = Array.prototype.slice.call(arguments);
      if (args.length === 0 || $('body').get(0).attr('class') == "") return false;

      return args.diff($('body').get(0).attr('class').split(/\s/)).length == 0;
    };

    return utility;
  }(deefour.Utility || {}));

  return deefour;
}(DEEFOUR || {}));
最后,在你的
app/assets/javascripts/static_page.js.coffee
中,我将有类似的内容

$(function(){
  if (!DEEFOUR.Utility.hasBodyClass('static_pages_help')) return;

  // code for your help page
});

$(function(){
  if (!DEEFOUR.Utility.hasBodyClass('static_pages_about')) return;

  // code for your about page
});
这很好,因为在你看来

<% content_for :body_classes, :some_custom_class %>
hasBodyClass(…)
接受任意的参数;把它们列出来。这对于
new
create
操作非常有用,您希望在表单提交失败时运行相同的Javascript

if (!DEEFOUR.Utility.hasBodyClass('some_controller_new', 'some_controller_create')) return;

需要注意的是,
prepare\u common\u variables
需要一些调整,因为它只允许一个名称空间,比如
SomeNamespace::the controller
,而不是更像
SomeNamespace::AnotherNamespace::the controller
,我将解释如何处理这个问题。在我的
ApplicationController
中,我有一个方法,在每次请求时从
前过滤器运行

def prepare_common_variables
  controller_name = self.class.name.gsub(/Controller$/, '')
  if !controller_name.index('::').nil?
    namespace, controller_name = controller_name.split('::')
  end

  @default_body_classes = ["#{controller_name.underscore}_#{action_name} ".downcase.strip]
  @default_body_classes = ["#{namespace.underscore}_#{@default_body_classes.join}".strip] if !namespace.nil?
end
在app/views/layouts/application.html.erb中,我有以下内容

<body class="<%= yield :body_classes %> <%= @default_body_classes.join(' ') %>">
接下来,在我的
app/assets/javascripts/application.js.erb

Array.prototype.diff = function(a) {
  return this.filter(function(i) {return !(a.indexOf(i) > -1);});
};

var DEEFOUR = (function (deefour) {
  deefour.Utility = (function (utility) {
    utility.hasBodyClass = function() {
      var args = Array.prototype.slice.call(arguments);
      if (args.length === 0 || $('body').get(0).attr('class') == "") return false;

      return args.diff($('body').get(0).attr('class').split(/\s/)).length == 0;
    };

    return utility;
  }(deefour.Utility || {}));

  return deefour;
}(DEEFOUR || {}));
最后,在你的
app/assets/javascripts/static_page.js.coffee
中,我将有类似的内容

$(function(){
  if (!DEEFOUR.Utility.hasBodyClass('static_pages_help')) return;

  // code for your help page
});

$(function(){
  if (!DEEFOUR.Utility.hasBodyClass('static_pages_about')) return;

  // code for your about page
});
这很好,因为在你看来

<% content_for :body_classes, :some_custom_class %>
hasBodyClass(…)
接受任意的参数;把它们列出来。这对于
new
create
操作非常有用,您希望在表单提交失败时运行相同的Javascript

if (!DEEFOUR.Utility.hasBodyClass('some_controller_new', 'some_controller_create')) return;

需要注意的是,
prepare\u common\u variables
需要一些调整,因为它只允许一个名称空间,比如
SomeNamespace::The controller
,而不是更像
SomeNamespace::AnotherNamespace::The controller
这里的最佳实践是使用content\u for helper方法。有点像@Adam所描述的,但是您可能希望在布局文件的底部放置一个
,然后调用

<% content_for :script_files do %>
  <%= javascript_include_tag 'your_js_file' %>
<% end %>

然后,您可以从操作视图调用
并包含该文件。

这里的最佳实践是使用content\u for helper方法。有点像@Adam所描述的,但是您可能希望在布局文件的底部放置一个
,然后调用

<% content_for :script_files do %>
  <%= javascript_include_tag 'your_js_file' %>
<% end %>
然后,您可以从操作视图中调用
,并将该文件包含在内

仅当我运行静态页面中的一个页面时才加载此javascript

首先,资产管道编译并创建静态资产文件
脱机
,这意味着您无法在服务用户请求期间(在生产中)根据控制器名称动态创建捆绑包

但是,您可以使用单独的
语句,而不是(包括StaticPages控制器的)相应布局文件中的
application.js
)来定义特定视图的特定Java脚本。例如,您可以有一个
app/assets/javascripts/static\u page\u manifest.js

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .

//= static_page
或者,如果希望包含动态javascript模块,可以使用
requirejs
requirejs-rails
)等

能够根据控制器内的特定操作进行不同的js调用

这可以通过检查body标签
id
来实现,该标签的值取决于控制器和动作名称!例如:

<body id="static_pages_<%= controller.action_name %>">
...

...
然后可以在javascript包中检查该id值以执行某些代码段

仅当我运行静态页面中的一个页面时才加载此javascript

首先,资产管道编译并创建静态资产文件
脱机
,这意味着您无法在服务用户请求期间(在生产中)根据控制器名称动态创建捆绑包

但是,您可以使用单独的
语句,而不是(包括StaticPages控制器的)相应布局文件中的
application.js
)来定义特定视图的特定Java脚本。例如,您可以有一个
app/assets/javascripts/static\u page\u manifest.js

//= require jquery
//= require jquery_ujs
//= require bootstrap
//= require_tree .

//= static_page
或者,如果您想要动态javascript模块inclusio