如何使用Gemfile在Rails 3应用程序中自动加载gemspec依赖项

时间:2011-08-05 17:13:40

标签: ruby-on-rails-3 gem dependencies bundler rails-engines

我有一个Rails 3应用程序,我正在变成一个Rails引擎/ gem。 这个引擎有一些gem依赖项,我把它放在它的.gemspec文件中。

我已经创建了一个新的'父'Rails 3应用程序,我想将我的引擎gem添加到Gemfile并让gem的依赖项自动'加载',但这对我不起作用! bundle install安装gem依赖项很好,但是当我启动服务器时,应用程序因为没有加载而崩溃。

例如,我的引擎的gemspec包含以下行:

s.add_runtime_dependency(%q<rails>, ["= 3.0.7"])
s.add_runtime_dependency(%q<acts_as_commentable>, [">= 3.0.1"])
s.add_runtime_dependency(%q<haml>, [">= 3.1.1"])

..并且父Rails 3应用程序在其Gemfile中包含以下行:

source 'http://rubygems.org'

gem 'my_engine', :path => "~/src/gems/my_engine"

但是我收到以下错误:

undefined local variable or method `acts_as_commentable'
from /home/user/src/gems/my_engine/app/models/account.rb:66:in `<class:Account>'

但是如果我将gem 'acts_as_commentable', '>= 3.0.1'添加到父Rails 3应用程序的Gemfile中,则加载gem并且错误消失。

我使用的是Rails 3.0.8。

有没有人有任何建议?我是否需要更改引擎加载方式?

4 个答案:

答案 0 :(得分:12)

在主Rails应用程序启动期间,Bundler只需要在Gemfile中直接列出的依赖项,而不是任何子依赖项。 你的图书馆/引擎有责任在需要时依赖它。你可以在你的Railtie中使用初始化器。

class MyRailtie < Rails::Railtie
  initializer "require stuff" do
    require "stuff"
  end
end

答案 1 :(得分:3)

在我们的Rails引擎中,我们使用了一个小技巧来自动地要求依赖项。遗憾的是,您无法指定它们是否应加载.gemspec,这将允许更好的控制。

Gem.loaded_specs["our_rails_engine"].dependencies.each do |d|
  begin
    require d.name
  rescue LoadError => le
    # Put exceptions here.
    raise le if d.name !~ /factory_girl_rails/
  end
end

答案 2 :(得分:2)

我正在看Spree(Rails Engines的超级英雄!),他们在spree_core-0.60.1/lib/spree_core.rb执行此操作:

require "rails/all"

require 'state_machine'
require 'paperclip'
require 'stringex'
require 'will_paginate'
require 'nested_set'
require 'acts_as_list'
require 'resource_controller'
require 'active_merchant'
require "meta_search"
require "find_by_param"

所以答案是在你的gem中,你必须逐个要求它所有的gem依赖。嗯,这就是我现在要做的。但如果将来发生变化,请发表评论。

答案 3 :(得分:1)

似乎它不起作用,我创建了一个主机项目和一个带有rails 3引擎的子项目。

将宝石添加到引擎的gemspec

s.add_dependency 'simple_form'

然后将require添加到engine_name.rb,如下所示

require 'simple_form'

但是如果删除主机项目的Gemfile中的行[gem'simple_form'],它将立即显示未定义的