Как сделать автозагрузку зависимостей gemspec в приложении Rails 3, используя Gemfile - PullRequest
11 голосов
/ 05 августа 2011

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

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

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

Ответы [ 4 ]

12 голосов
/ 07 августа 2011

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

class MyRailtie < Rails::Railtie
  initializer "require stuff" do
    require "stuff"
  end
end
3 голосов
/ 23 января 2014

В нашем 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
2 голосов
/ 06 августа 2011

Я смотрю на Шпрее (супергероя 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"

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

1 голос
/ 02 декабря 2011

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

Добавлен камень в спецификацию двигателя

s.add_dependency 'simple_form'

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

require 'simple_form'

Но если удалить строку [gem 'simple_form'] в Gemfile хост-проекта, она немедленно покажет undefined

...