【问题标题】:Where should JavaScript with embedded Ruby code go in a Rails 3.1 app?在 Rails 3.1 应用程序中嵌入 Ruby 代码的 JavaScript 应该放在哪里?
【发布时间】:2023-03-17 07:01:02
【问题描述】:

对于 Rails 3.1 应用程序,我的一些站点范围的 JavaScript 仅在满足某些实时、特定于实例的条件时才包含。这意味着我不能将它放在新资产管道的 application.js 中,因为 erb 没有为当前上下文中的嵌入式 Ruby 解析它。基本上,我根据登录的 current_user 包括键盘快捷键。

我的问题:这个带有嵌入代码的 JavaScript 应该去哪里,以便仍然使用正确的上下文(即当前登录用户)为每个页面访问解析嵌入的 Ruby?

答案似乎只是把它放在底部的 application.html.erb 布局视图中,但这就像我将 javascript 代码隐藏在一个不直观的位置一样。

我尝试创建一个 application2.js.erb 文件,但随后我收到有关未定义变量的错误,我认为这可能是因为资产引擎仅在缓存输出之前解析此文件一次并且范围不是对 current_user 之类的东西仍然正确。

所以,使用 application.html.erb 在这里工作得很好,这不是如何让它正常工作的问题。相反,我想知道是否有更优雅的方法可以将资产管道模型与我的需求结合起来,并且仍然将我的大部分 JavaScript 保留在 assets/javascripts 目录中。

【问题讨论】:

  • 你永远不需要用 JavaScript 来混淆 Ruby 代码
  • @fl00r:不知道你是什么意思。我的非常具体的例子说明了为什么有理由将 Ruby 混合到你的 JavaScript 中(即只有某些用户应该包含 JavaScript 块)。同样,我的 JavaScript 可以包含动态位,例如当前用户的名称,例如
  • 你总是可以用不显眼的 js 做同样的工作
  • fl00r:这里并不适用。根据用户的权限级别,我在服务器端排除某些事情。如果您有具体的代码示例,您想建议提供更多详细信息,我很乐意在此处的单独答案中看到这一点。

标签: javascript ruby-on-rails ruby-on-rails-3.1 erb asset-pipeline


【解决方案1】:

您应该尝试创建 app/assets/javascripts/application2.js.erb(或您想出的任何更好的名称)

然后在你的 app/assets/javascripts/application.js 中加入类似的内容:

//= require application2

然后你可以拥有

<%= javascript_include_tag 'application2' %>

您想要的任何地方 - 例如在您的 application.html.erb 中。

顺便说一句,如果您想根据每次观看自定义包含的内容,您可能会发现 content_for 很有用。看看这个screencast

【讨论】:

  • 已经有一个'require_tree'。默认情况下指令,因此新的 JS 文件将基于该指令被包含在内。但是,我认为资产管道只解析这个模板一次,然后缓存结果。这意味着没有像 current_user 对象这样的特定于页面的上下文,这将出错。注意顺便说一句,application.js 和 application.js.erb 不能很好地共存(后者被忽略),所以我不得不选择一个稍微不同的名称。
  • 关于 content_for 的好点子,我实际上已经在 3.1 之前的应用程序中将它用于 JS。但是,在这种情况下,它不是特定于控制器的 JS,因此最好只保留在全局应用程序布局中。这行得通,但我主要是问这个特定示例是否意味着我不能优雅地将所有 JS 都放在 assets 文件夹中。
  • 嗯。我知道了。我也使用这种技术:railscasts.com/episodes/205-unobtrusive-javascript。它通过在 .html.erb 中设置一些自定义属性而不是使用 jquery 读取它来工作。那时不需要 js.erb。但是对于您的情况,我可能会遗漏一些明显的东西:)我自己仍在学习:)
【解决方案2】:

好的,关于不显眼的 js。这只是一个概念(HAML):

在你看来某处

# hotkeys are "Ctrl+C", "Ctrl+A"
-current_user.hotkeys.each do |hotkey|
  %hotkey{ "data-key" => hotkey.key, "data-behavior" => hotkey.fn  }

然后在你的application.js

$(document).ready(function(){
  if($("hotkey").length > 0){
    $("hotkey").each{function(this){
      key = $(this).data("key");
      fn  = $(this).data("behavior");
      $(document).bind('keydown', key, fn);
    }}
  }
})

所以同样的 JS 会从 HTML 热键数据中提取然后绑定它。

【讨论】:

  • 老实说,这只是让事情变得过于复杂,例如,您在 current_user 上创建热键属性的方式。最后,您仍然将 JavaScript 添加到视图中(调用了 fn 代码 sn-p) .在我的具体示例中,我的问题也不太具体关于热键绑定。
【解决方案3】:

正如一些人所指出的,这两个选项是:

  • 将您的 javascript 放在视图中(正如您所说,这感觉不太正确)。
  • 将其放入一个 javascript 文件中。如果满足某些条件,请在包含此 javascript 文件的视图中创建条件。

如果您需要将更多实例变量从控制器传递到您的 javascript,这个名为 gon 的 gem 可以让您的生活更轻松。

这允许您使用以下 javascript 使用默认资产管道:

if(gon.conditional){
  //your embedded js code here
}

如果您想了解更多关于这颗宝石的信息,请查看此railcast,所有内容都会得到解释。

【讨论】:

    猜你喜欢
    • 2011-12-07
    • 2011-12-07
    • 1970-01-01
    • 2011-08-05
    • 2012-01-17
    • 1970-01-01
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多