我有一个基于插件的系统,我在Rails中用于应用程序开发。每个插件都实现了一个带有MVC组件等的引擎。主应用程序只是一个空的线束,它将所有工作委托给安装的插件。
我目前正在从Rails 2.3.5升级到Rails 3.1,并试图让资产管道与我的框架一起工作。
我遇到的问题是尝试以编程方式将我的插件资源放入例如application.js清单中。
我可以像这样手动添加它们:
//= require <plugin_manifest_path>
一切都按预期工作。但是,由于我的框架中有许多插件,并且每个安装都有不同的组合,我希望根据安装的插件进行此清单更改。我尝试了这个解决方案:
<%=
Rails.plugins.collect do |plugin|
"//= require #{plugin}"
end.join("\n")
%>
但我发现资产管道编译的require / directive阶段发生在ERB扩展之前,因此生成的注释最终只是注释。
是否有其他机制可以包含可能有效的编译路径?在指令处理开始之前预先处理清单文件的任何方法?
如果我想不出更好的事情,我可能必须编写一个rake / deployment任务,在部署时生成一个plugin.js清单文件,但如果可能的话,我会喜欢更清晰,更优雅的东西。谢谢!
编辑:找到解决方案,只要stackoverflow允许我就会发布完整解决方案。请参阅以下评论的平均时间......
答案 0 :(得分:13)
好的,所以这是解决方案:
在内部,资产管道(又名Sprockets)需要指令调用context.require_asset()
来实际需要指令中指定的任何路径。事实证明,这意味着require_asset
方法在ERB扩展期间存在并可用。所以,正确的解决方案是:
// ... Standard application.js stuff here ...
//= require_tree .
<%
Rails.plugins.each do |plugin|
require_asset(plugin.to_s)
end
%>
添加了,并且所有工作都按预期工作。呼!
如果您想知道Rails.plugins
位,我在Rails模块中添加了一个扩展,以获取基于config.plugins按加载顺序加载的实际插件列表。为了完整起见,这里是:
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
最后的细节是在每个插件的app / assets / javascripts目录中创建一个<plugin_name>.js
清单文件。
希望能帮助别人!