Как сделать gemspec зависимостями autoload в приложении Rails 3, используя Gemfile

У меня есть приложение Rails 3, которое я превращаю в Rails engine/gem. Этот движок имеет некоторые зависимости от gem, которые я вложил в него .gemspec.

Я создал новое "родительское" приложение Rails 3, и я хотел бы добавить свой жемчуг в 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' в Gemfile родительского Rails 3, то жемчуг будет загружен и ошибка исчезнет.

Я использую Rails 3.0.8.

Есть ли у кого-нибудь предложения? Нужно ли мне что-то менять в отношении загрузки моего двигателя?

Ответ 1

Во время загрузки основного Rails-приложения Bundler потребует только зависимостей, непосредственно перечисленных в Gemfile, но не любых зависимостей. Обязанность вашей библиотеки/двигателя требовать ее зависимости, когда она сама понадобится. Вы можете сделать это с помощью инициализаторов в вашем Railtie.

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

Ответ 2

В нашем Rails Engine мы использовали небольшой трюк, чтобы автоматически требовать зависимости. К сожалению, вы не можете указать, должны ли они загружаться в .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

Ответ 3

Я смотрю на 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"

Итак, ответ заключается в том, что в вашем драгоценном камне вам нужно каждый раз использовать все его зависимости. Что ж, пока я это сделаю. Но прокомментируйте, если это произойдет в будущем.

Ответ 4

Кажется, он не работает, я создаю проект-хост и суб-проект с движком rails 3.

Добавлен драгоценный камень в двигатель gemspec

s.add_dependency 'simple_form'

то добавили require к engine_name.rb, как показано ниже

require 'simple_form'

Но если удалить строку [gem "simple_form" ] в файле проекта Gemfile, он будет показывать undefined немедленно