Rails:Asset Pipeline在视图脚本中创建Javascript错误

时间:2012-09-21 18:25:17

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

我有一个resource的视图和一些特定于它的javascript。所以,我尽职尽责地将Javascript放在app/assets/javascripts/resource.js.coffee中。

问题是,当我在我的应用程序中转到其他视图时,我会收到各种类似的Javascript错误:

Type issue: 'null' is not an object...

page_url = page_image.getAttribute('src');

应用程序工作正常,但这些脚本实际上不应该尝试在其不适合的视图中运行。

显然我错过了一些东西......好吧......很明显!它是什么?

3 个答案:

答案 0 :(得分:2)

默认情况下,application.js包含app/assets/javascripts中的所有脚本,默认情况下,您的布局包含所有这些脚本。这样做的好处是,浏览器只能对Javascript文件发出一个请求,然后可以对其进行缓存 - 但缺点是所有Javascript都在每个页面上运行。

有两种基本解决方案:

  1. 编写Javascript,在需要时执行它应该执行的操作,并在不执行时执行任何操作。
  2. application.js更改为不包含所有内容,在需要时包含单个Javascript文件,并更改config.assets.precompile以包含所有新的顶级文件。

答案 1 :(得分:1)

由于只在某些页面上运行某些javascript,因此没有任何内容被刻录到rails中。我采取的方法是基于post

我的每个页面特定的coffeescript文件都是

window.App.controller_name = 
  init: ->
    #stuff that happens for all actions
  edit: ->
    #Stuff that happens only for the edit action

body元素使用数据控制器和数据操作属性进行修饰。然后,application.js中的一些javascript运行相应的javascript:

execute_hook = (controller, action='init') ->
  ns = window.App
  if controller?
    if ns[controller] && typeof(ns[controller][action]) == "function"
      ns[toplevel][controller][action]()

jQuery ->
  body = document.body
  controller = body.getAttribute("data-controller")
  action = body.getAttribute("data-action")
  execute_hook(controller)
  execute_hook(controller, action)

答案 2 :(得分:0)

两个建议,第一个是hacky,第二个是很棒。

1。清单+布局

为那些需要不同JS组合的视图创建一个新的JS清单文件,从新布局调用该清单文件,并从呈现这些视图的控制器操作中调用新布局。

在你的例子中:

应用程序/资产/ Javascript角/ resource.js.coffee

// Requires
//= require_whatever_js_files_your_resource_page_needs_here

// Custom JS below
...

应用程序/视图/布局/ resource.html.erb

...
<%# Within your <head> tag %>
<%= javascript_include_tag "resource" %>
...

应用程序/控制器/ resources_controller.rb

class ResourceController < ApplicationController
# filters, default layout, other actions, etc.
...

# Your action that needs only the resource JS,
# and therefore the resource layout
def action_that_only_uses_resource_js
  @some_objects = SomeObjects.all
  render layout: 'resource' # <- This is the important part
end

显然,这种方法不能很好地扩展,因为它不灵活,即你不能像你一样喜欢并且毫无疑问需要组合你的JS。这让我们把你的JS分解成......

2。 RequireJs Modules

使用RequireJsthis gem集成到Rails中。您将获得您正在寻找的模块化,并防止发生冲突。 RequireJs使用AMD pattern,我相信这是你正在寻找的。