我正在编写一个具有一些依赖关系的rails引擎。我已经在gemspec中指定了依赖项,并且当我运行bundle install
时引擎正在找到它们(即Gemfile.lock看起来正确)。当我想在Ruby文件中使用插件时,我可以这样做,但需要在文件顶部显式require dependency-name
。
但是,当我想使用依赖项的资产管道时,链接器无法找到它。
我正在使用的应用程序(目前)是一个虚拟应用程序,它位于rails插件的测试文件夹中。如果我在引擎的Gemfile(实际上是虚拟应用程序的Gemfile)中指定它们,Sprockets可以找到资产,但如果我在gemspec中指定它们则不会。我不想依赖Gemfile,因为这意味着任何使用我的插件的应用都需要手动将我的所有依赖项添加到他们的Gemfile中。出于同样的原因,我不想要一个涉及更新应用程序配置文件的解决方案。
当从gemspec中包含依赖项时,这可以(在ruby文件中):
require 'dependency-name'
但是当从gemspec中包含依赖项时,这(在JS文件中)不起作用:
//= require 'dependency-name'
当Gemfile中包含依赖项时,不需要require
。我认为这很清楚,但如果您需要更多细节,请告诉我。
答案 0 :(得分:27)
我需要在我的engine.rb中明确包含依赖项,以使其资产最终出现在我的资产管道中。不知道为什么这是必要的,因为Alastor的答案听起来对我来说是正确的。值得注意的是,依赖关系是我使用bundler创建的宝石,但我不明白为什么这会产生影响。
module MyRailsPluginFull
class Engine < ::Rails::Engine
require 'dependency1'
require 'dependency2'
end
end
已添加11/23/12
花了更多时间与Engines合作,我想我现在对此更加了解。 Gemspec只是所需的依赖项列表,但gemspec并不指示应用程序在启动时从这些依赖项加载文件。另一方面,Gemfiles会在启动期间加载所有文件。
已添加2015年3月20日
我2年前发表的声明“另一方面,Gemfiles在启动时加载所有文件”并不完全正确。在Rails中大多数情况下都是如此,它默认运行Bundler.require
以要求Gemfile中列出的所有依赖项,如生成器文件here中所示 - 请注意,虽然Rails的默认行为从Rails3更改为Rails正如所讨论的那样here,两者都使用Bundler.require
。但是,有一个强有力的理由可以使用Bundler.setup
,然后在实际依赖require "dependency1"
的文件中使用显式depedency1
。
请参阅Bundler.require
与Bundler.setup
的{{3}}。
另外,正如@nruth在评论中指出的那样,这可能导致加载不必要的类。但是,如果依赖项设计得很好,那么它的类将主要被自动加载,从而为需要整个依赖项创建最小的开销。或者,如果它在一个可以单独使用的文件中定义其引擎,您可以只包含引擎文件,该文件应该将必要的文件添加到您的资产路径中,这样您就可以在CSS&amp; JS表现出来。请参阅this discussion,其中gem将其所有资产添加到config.assets.paths
,并将其中一部分添加到config.assets.precompile
。
虽然这个问题已经存在了几年,我甚至不记得当时正在编写的Rails引擎,但我怀疑正确的方法可能更接近于此:
module MyRailsPluginFull
class Engine < ::Rails::Engine
initializer 'bootstrap-sass.assets.precompile' do |app|
require 'dependency1'
# add dependency1's assets to the list of paths
app.config.assets.paths << ...
end
end
end
但请注意,这不应该是必要的 - 依赖本身应该已经定义了这个初始化程序,因此只需要它就足够了,就像上面的bootstrap示例那样。
答案 1 :(得分:0)
您根据http://edgeguides.rubyonrails.org/engines.html设计了引擎?如果您的引擎类继承自Rails :: Engine,它实际上应该自己找到所有资产。