Rails 3.1 asset pipeline:如何加载特定于控制器的脚本?

发布于 2024-11-18 03:53:20 字数 235 浏览 4 评论 0原文

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

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

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

If I generate a new controller in Rails 3.1, also a javascript file with the name of the controller will added automatically. Firstly, I thought this javascript file will used only, when the related controller is called.

By default there is the instruction //= require_tree . in the application.js-file, that include every javascript file on it's tree.

How could I load only the controller specific script?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

野稚 2024-11-25 03:53:20

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

  1. application.js 中删除 //=require_tree

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

  3. application_helper.rb中添加一个助手

    def javascript(*文件)
      content_for(:head) { javascript_include_tag(*files) }
    结尾
    
  4. 到你的布局中:

    <%= 产量(:head) %>
    
  5. 将其添加到您的视图文件中:

    <% javascript 'name_of_the_js_file' %>;
    

然后应该没问题

To load only the necessary name_of_the_js_file.js file:

  1. remove the //=require_tree from application.js

  2. keep your js file (that you want to load when a specific page is loaded) in the asset pipeline

  3. add a helper in application_helper.rb

    def javascript(*files)
      content_for(:head) { javascript_include_tag(*files) }
    end
    
  4. yield into your layout:

    <%= yield(:head) %>
    
  5. add this in your view file:

    <% javascript 'name_of_the_js_file' %>
    

Then it should be ok

一身骄傲 2024-11-25 03:53:20

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

请参阅 http://apidock.com/ rails/ActionController/Metal/controller_name/class

<%= javascript_include_tag "application", controller_name %>

controller_name.js 将被加载并且也在资产中,因此您可以从这里需要其他文件。

例如,渲染 cars#index 将给出

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

cars.js 可以包含

//= require wheel
//= require tyre

Enjoy 的位置!

An elegant solution for this is to require controller_name in your javascript_include_tag

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

<%= javascript_include_tag "application", controller_name %>

controller_name.js will be loaded and is in the asset also, so you can require other files from here.

Example, rendering cars#index will give

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

where cars.js can contain

//= require wheel
//= require tyre

Enjoy !

注定孤独终老 2024-11-25 03:53:20

我总是将其包含在我的布局文件中。它可以限制你的 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") %>

I always include this inside my layout files. It can scope your js to action

<%= 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") %>
橙幽之幻 2024-11-25 03:53:20

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

动态添加资产

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

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

    模块ApplicationHelper
        def include_相关_资产(资产)
        # v-----{更改此}
            if !YourApp::Application.assets.find_asset(asset).nil?
                case asset.split('.')[-1]
                    当“js”
                        javascript_include_tag 资产
                    当'css'
                        stylesheet_link_tag 资源
                结尾
            结尾
        结尾
    结尾
    
  2. 在您的布局文件中调用帮助程序方法:

    <%= include_lated_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' %>
    <%结束%>
    

请参阅 Rails 指南 了解更多信息。

Your problem can be solved in different ways.

Add the assets dynamically

Please consider that this isn't a good solution for the production mode, because your controller specifics won't be precompiled!

  1. Add to our application helper the following method:

    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. Call the helper method in your layout-file:

    <%= include_related_asset(params[:controller].to_param + '_' + params[:action].to_param . 'js') %>
    
  3. Create specific assets for your controller actions. E. g. controller_action.js

Please don't forget to change YourApp to the name of your app.

Use yield

  1. Add <%= yield :head%> to your layout head
  2. Include your assets from your action views:

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

Please see the Rails guides for further information.

时光暖心i 2024-11-25 03:53:20

我喜欢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 为 true)。通过提供一个文件
而不是很多,可以大大减少页面的加载时间
因为浏览器发出的请求较少。压缩也减少了
文件大小,使浏览器能够更快地下载它们。

请阅读文档,了解 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

现在获取与控制器名称的基本名称,您可以使用以下内容:

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/

I like albandiguer's solution. With which I've found that javascript/coffeescript assets are not individually precompiled. Which causes all sorts of errors trying to use javascript_path. I'll share my solution to that problem after I address an issue a few people mentioned in his comments. Mainly dealing with only a partial set of controller named JavaScript files.

So I built an application helper to detect if the file exists in the javascript directory regardless of .coffee/.js extension:

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

This method will return the full path to the javascript file if it exists. Otherwise it returns nil. So following Pencilcheck's comment you can add this method for a conditional include:

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

And now you have a proper conditional include. Now for the issue of precompiled assets. Generally for optimization you don't want assets precompiled individually. You can however do it if you must:

# Live Compilation
config.assets.compile = true

You can add this do your environment config file. Test it in your development environment file first. Again this is ill-advisable. The Rails asset pipeline uses Sprockets to optimize everything:

Sprockets loads the files specified, processes them if necessary,
concatenates them into one single file and then compresses them (if
Rails.application.config.assets.compress is true). By serving one file
rather than many, the load time of pages can be greatly reduced
because the browser makes fewer requests. Compression also reduces
file size, enabling the browser to download them faster.

PLEASE READ the documentation for further details of the mechanics of Sprockets (Asset Pipeline) http://guides.rubyonrails.org/asset_pipeline.html

Assets aren't precompiled individually. For example when I try:

<%= javascript_include_tag 'event' %>

I get:

Sprockets::Rails::Helper::AssetFilteredError: Asset filtered out and
will not be served: add Rails.application.config.assets.precompile +=
%w( event.js )
to config/initializers/assets.rb and restart your
server

So you can include which assets to be precompiled individually. We just need to add the relevant controller named javascript files in our asset initializer. Well we can do this programatically.

To get a list of controller names I will use ecoologic's example:

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

And now to get the name of all javascript files that match the basename of the controller name you can use the following:

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]}
  }

Then you can try:

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

This will get you a list of all javascript files, without directory path, that match your controller name. Note if your controller name is plural, the javascript name should be as well. Also note if the controller is singular and the javascript file is plural this will still include it because of the_file[a_controller] will succeed on a partial match.

Feel free to try this out in your Rails.application.config.assets.precompile setting. I know that this gets you the list of files correctly. But I'll leave you to test it. Let me know if there are any nuances involved with precompiling this way as I am curious.

For a very thorough explanation on how assets precompile see this blog: http://www.sitepoint.com/asset-precompile-works-part/

骄傲 2024-11-25 03:53:20

我最近发现了一种简单的方法来为特定控制器使用生成的脚本。我使用该解决方案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...

仅此而已。

I recently found a simple approach to use generated scripts for specific controller. I use for that solution gem gon. Add in a controller:

class HomesController < ApplicationController
  before_filter :remember_controller

  private

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

After that open your homes.js.cofee and add in the beginning of file:

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

That is all.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文