如何在Rails 3.1资产管道中动态地要求资产? [英] How can I dynamically require assets in the Rails 3.1 asset pipeline?

查看:264
本文介绍了如何在Rails 3.1资产管道中动态地要求资产?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基于插件的系统,用于Rails中的应用程序开发。每个插件都实现了一个带有MVC组件的引擎等等。主要应用程序只是将所有工作委托给安装的插件的空线程。



我目前从Rails 2.3.5升级到Rails 3.1,我试图让资产管道与我的框架一起工作。



我遇到的问题是尝试以编程方式要求我我们可以手动添加它们:

  // = require< plugin_manifest_path> 

一切都按预期工作。然而,由于我的框架中有几十个插件,每个安装都有不同的组合,所以我想根据安装的插件来更改这个清单。我试过这个解决方案:

 <%= 
Rails.plugins.collect do | plugin |
// = require#{plugin}
end.join(\\\

%>

但是我发现资产管道编译的需求/指令阶段在ERB扩展之前发生,所以生成的评论只是以评论的方式结束。



是否有其他机制可以包含可能起作用的编译路径?在指令处理之前预先处理清单文件的任何方式?



如果我不能想到更好的东西,我可以必须编写一个在部署时生成一个plugin.js清单文件的耙子/部署任务,但如果可能,我会喜欢更清晰和更优雅的东西。谢谢!



编辑:找到解决方案,一旦stackoverflow让我发布完整的解决方案。

解决方案

确定,所以这里是解决方案:



在内部,资产管道(又名Sprockets)需要指令调用 context.require_asset()来实际需要指令中指定的任何路径。原来,这意味着在ERB扩展期间,存在 require_asset 方法可用。所以,正确的解决方案是:

  // ...标准的application.js东西在这里... 
/ / = require_tree。
<%
Rails.plugins.each do | plugin |
require_asset(plugin.to_s)
end
%>

添加了,并且都按预期工作。呃!



如果你想知道那个 Rails.plugins 位,我添加了一个扩展名到Rails模块以根据config.plugins的加载顺序获取加载的实际插件列表。为了完整性,这里是:

  module Rails 
def self.plugins
#获取排序列表所有安装的插件
all = Dir.glob(Rails.path('vendor / plugins / * / init.rb'))。collect {| p | p.extract(/ \ /([^ \ /] +)\ / init.rb $ /)}
all.sort!
all.collect! {| P | p.to_sym}

#获取我们的加载订单规范
load_order = Rails.application.config.plugins

#拆分加载顺序,重新组装替换:all关键字与
#套插件不在头或尾
头,tail = load_order.split(:全部)
全 - =头
全 - =尾巴

#全套!
head + all + tail
end
end

最终细节是在每个插件的app / assets / javascripts目录中创建一个< plugin_name> .js 清单文件。




I have a plugin-based system that I use for application development in Rails. Each plugin implements an engine with MVC components, etc. The main application is simply an empty harness that delegates all the work to the plugins that are installed.

I'm currently upgrading to Rails 3.1 from Rails 2.3.5, and am trying to get the asset pipeline working with my framework.

The problem I'm having is trying to programmatically require my plugin's assets into, for example, the application.js manifest.

I can manually add them like so:

//= require <plugin_manifest_path>

And everything works as expected. However, as there are dozens of plugins in my framework, and each installation has a different mix, I want to have this manifest change based on which plugins are installed. I tried this as a solution:

<%=
Rails.plugins.collect do |plugin|
  "//= require #{plugin}"
end.join("\n")
%>

But what I discovered is that the require/directive phase of the asset pipeline compilation happens before ERB expansion, so the generated comments were simply ending up as comments.

Is there another mechanism for including paths for compilation that might work? Any way to pre-process a manifest file before the directive processing kicks in?

If I can't think of anything better, I may have to write a rake/deployment task that generates a plugin.js manifest file on deploy, but I'd love something more clear and elegant if possible. Thanks!

EDIT: Solution found, will post full solution as soon as stackoverflow lets me. See comments below in the mean time...

解决方案

OK, so here's the solution:

Internally, the asset pipeline (aka Sprockets) require directive calls context.require_asset() to actually require whatever path is specified in the directive. Turns out, that means that the require_asset method is present and available during ERB expansion. So, the correct solution was:

// ... Standard application.js stuff here ...
//= require_tree .
<%
Rails.plugins.each do |plugin|
  require_asset(plugin.to_s)
end
%>

Added that in, and all worked as expected. Whew!

In case you're wondering about that Rails.plugins bit, I added an extension to the Rails module to get the actual list of plugins that are loaded, in load order, based on config.plugins. For completeness, here it is:

module Rails
  def self.plugins
    # Get sorted list of all installed plugins
    all = Dir.glob(Rails.path('vendor/plugins/*/init.rb')).collect {|p| p.extract(/\/([^\/]+)\/init.rb$/) }
    all.sort!
    all.collect! {|p| p.to_sym }

    # Get our load order specification
    load_order = Rails.application.config.plugins

    # Split the load order out, and re-assemble replacing the :all keyword with the
    # set of plugins not in head or tail
    head, tail = load_order.split(:all)
    all -= head
    all -= tail

    # All set!
    head + all + tail
  end
end

And the final detail was creating a <plugin_name>.js manifest file in each plugin's app/assets/javascripts directory.

Hope that helps someone!

这篇关于如何在Rails 3.1资产管道中动态地要求资产?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆