76

如果我在 Rails 3.1 中生成一个新控制器,也会自动添加一个带有控制器名称的 javascript 文件。首先,我认为只有在调用相关控制器时才会使用这个 javascript 文件。

默认情况下,-file 中有指令//= require_tree .application.js包括树上的每个 javascript 文件。

我怎么能只加载控制器特定的脚本?

4

6 回答 6

122

仅加载必要的 name_of_the_js_file.js 文件:

  1. //=require_tree从_application.js

  2. 将您的 js 文件(在加载特定页面时要加载的文件)保留在资产管道中

  3. 添加一个助手application_helper.rb

    def javascript(*files)
      content_for(:head) { javascript_include_tag(*files) }
    end
    
  4. 屈服于您的布局:

    <%= yield(:head) %>
    
  5. 在你的视图文件中添加这个:

    <% javascript 'name_of_the_js_file' %>
    

那么应该没问题

于 2011-07-22T20:08:26.810 回答
83

一个优雅的解决方案是在你的 javascript_include_tag 中要求 controller_name

http://apidock.com/rails/ActionController/Metal/controller_name/class

<%= javascript_include_tag "application", controller_name %>

controller_name.js 将被加载并且也在资产中,所以你可以从这里请求其他文件。

例如,渲染汽车#index 将给出

<%= javascript_include_tag "application", "cars" %>

car.js 可以包含的地方

//= require wheel
//= require tyre

享受 !

于 2011-10-20T03:56:10.513 回答
28

我总是将它包含在我的布局文件中。它可以将你的 js 限定为行动

<%= javascript_include_tag params[:controller] if AppName::Application.assets.find_asset("#{params[:controller]}.js") %>
<%= javascript_include_tag "#{params[:controller]}_#{params[:action]}"  if AppName::Application.assets.find_asset("#{params[:controller]}_#{params[:action]}.js") %>
于 2012-10-22T09:57:54.583 回答
6

您的问题可以通过不同的方式解决。

动态添加资产

请考虑这对于生产模式不是一个好的解决方案,因为您的控制器细节不会被预编译!

  1. 将以下方法添加到我们的应用程序助手中:

    module ApplicationHelper
        def include_related_asset(asset)
        #          v-----{Change this}
            if !YourApp::Application.assets.find_asset(asset).nil?
                case asset.split('.')[-1]
                    when 'js'
                        javascript_include_tag asset
                    when 'css'
                        stylesheet_link_tag asset
                end
            end
        end
    end
    
  2. layout在您的-file中调用辅助方法:

    <%= include_related_asset(params[:controller].to_param + '_' + params[:action].to_param . 'js') %>
    
  3. 为您的控制器操作创建特定资产。例如。controller_action.js

请不要忘记更改YourApp为您的应用程序的名称。

采用yield

  1. 添加<%= yield :head%>到您的布局头
  2. 从您的操作视图中包含您的资产:

    <% content_for :head do %>
    <%= javascript_include_tag 'controller_action' %>
    <% end %>
    

请参阅Rails 指南以获取更多信息。

于 2012-06-25T18:56:43.437 回答
3

我喜欢albandiguer 的解决方案。我发现 javascript/coffeescript 资产不是单独预编译的。这会导致尝试使用javascript_path. 在我解决了一些人在他的评论中提到的问题后,我将分享我对该问题的解决方案。主要只处理部分控​​制器命名的 JavaScript 文件集。

因此,我构建了一个应用程序助手来检测文件是否存在于 javascript 目录中,而不管 .coffee/.js 扩展名如何:

module ApplicationHelper
  def javascript_asset_path(basename)
    Sprockets::Rails::Helper.assets.paths.select{|i|
      i =~ /javascript/ and i =~ /#{Rails.root}/
    }.each do |directory|
      if Dir.entries(directory).map {|i| i.split('.')[0]}.compact.
          include? basename
        return File.join(directory, basename)
      end
    end
    nil
  end
end

如果存在,此方法将返回 javascript 文件的完整路径。否则返回零。因此,按照 Pencilcheck 的评论,您可以将此方法添加为条件包括:

<%= javascript_include_tag(controller_name) if javascript_asset_path(controller_name) %>

现在你有了一个适当的条件包含。现在讨论预编译资产的问题。通常为了优化,您不希望单独预编译资产。但是,如果您必须这样做,您可以这样做:

# Live Compilation
config.assets.compile = true

您可以将其添加到您的环境配置文件中。首先在您的开发环境文件中对其进行测试。这又是不可取的。Rails 资产管道使用 Sprockets 来优化一切:

Sprockets 加载指定的文件,必要时处理它们,将它们连接成一个文件,然后压缩它们(如果 Rails.application.config.assets.compress 为真)。通过提供一个文件而不是多个文件,可以大大减少页面的加载时间,因为浏览器发出的请求更少。压缩还减少了文件大小,使浏览器能够更快地下载它们。

请阅读文档以获取Sprockets(资产管道)机制的更多详细信息 http://guides.rubyonrails.org/asset_pipeline.html

资产不是单独预编译的。例如,当我尝试:

<%= javascript_include_tag 'event' %>

我得到:

Sprockets::Rails::Helper::AssetFilteredError: 资产被过滤掉并且不会被提供:添加Rails.application.config.assets.precompile += %w( event.js )config/initializers/assets.rb重启你的服务器

因此,您可以包含要单独预编译的资产。我们只需要在我们的资产初始化程序中添加名为 javascript 文件的相关控制器。好吧,我们可以以编程方式做到这一点。

要获取控制器名称列表,我将使用ecoologic 的示例

all_controllers =  Dir[
    Rails.root.join('app/controllers/*_controller.rb')
  ].map { |path|
    path.match(/(\w+)_controller.rb/); $1
  }.compact

现在要获取与控制器名称的基本名称匹配的所有 javascript 文件的名称,您可以使用以下命令:

javascripts_of_controllers = Sprockets::Rails::Helper.assets.paths.select{|a_path|
    a_path =~ /javascript/ and a_path =~ /#{Rails.root}/
  }.map {|a_path|
    Dir.entries(a_path)
  }.flatten.delete_if {|the_file|
    !the_file['.js']
  }.collect {|the_file|
    the_file if all_controllers.any? {|a_controller| the_file[a_controller]}
  }

然后你可以尝试:

# config/initializers/assets.rb
Rails.application.config.assets.precompile += javascripts_of_controllers

这将为您提供与您的控制器名称匹配的所有 javascript 文件的列表,没有目录路径。请注意,如果您的控制器名称是复数,则 javascript 名称也应该是复数。另请注意,如果控制器是单数且 javascript 文件是复数,则仍将包含它,因为the_file[a_controller]在部分匹配时会成功。

随意在您的Rails.application.config.assets.precompile环境中尝试一下。我知道这可以正确地为您提供文件列表。但我会让你去测试它。让我知道以这种方式进行预编译是否有任何细微差别,因为我很好奇。

有关资产如何预编译的非常详尽的解释,请参阅此博客:http ://www.sitepoint.com/asset-precompile-works-part/

于 2014-11-05T12:28:47.153 回答
1

我最近发现了一种为特定控制器使用生成脚本的简单方法。我使用该解决方案gem gon。添加控制器:

class HomesController < ApplicationController
  before_filter :remember_controller

  private

  def remember_controller
    gon.controller = params[:controller]
  end
end

之后打开你的homes.js.cofee并在文件的开头添加:

jQuery ->
  if gon.controller == "sermons"
    # Place all functions here...

就这些。

于 2013-08-09T15:07:24.013 回答