Rails 3.1资产管道:如何加载特定于控制器的脚本?

时间:2011-07-04 12:49:59

标签: ruby-on-rails ruby-on-rails-3.1 asset-pipeline assets sprockets

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

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

如何只加载特定于控制器的脚本?

6 个答案:

答案 0 :(得分:122)

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

  1. //=require_tree

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

  4. application_helper.rb

    中添加帮助器
    def javascript(*files)
      content_for(:head) { javascript_include_tag(*files) }
    end
    
  5. 进入你的布局:

    <%= yield(:head) %>
    
  6. 在您的视图文件中添加:

    <% javascript 'name_of_the_js_file' %>
    
  7. 然后应该没问题

答案 1 :(得分: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" %>

其中cars.js可以包含

//= require wheel
//= require tyre

享受!

答案 2 :(得分: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") %>

答案 3 :(得分: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 - 文件中的帮助方法:

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

  4. 请不要忘记将YourApp更改为您的应用名称。

    使用yield

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

      <% content_for :head do %>
      <%= javascript_include_tag 'controller_action' %>
      <% end %>
      
    3. 有关详细信息,请参阅Rails guides

答案 4 :(得分:3)

我喜欢albandiguer's solution。我发现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文件的完整路径(如果存在)。否则返回nil。因此,遵循Pencilcheck的评论,您可以为条件包括添加此方法:

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

现在你有一个适当的条件包括。现在讨论预编译资产。通常用于单独优化 you don't want assets precompiled 。但是,如果你必须这样做,你可以这样做:

# Live Compilation
config.assets.compile = true

您可以添加此环境配置文件。首先在开发环境文件中测试它。再次这是不合理的。 Rails资产管道使用Sprockets来优化所有内容:

  

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

请阅读文档,了解Sprockets (Asset Pipeline) 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's example

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/

答案 5 :(得分: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...

就是这样。