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