Зависимость, включенная в gemspec, не добавленную к конвейеру активов в двигателе rails

Я пишу движок rails, который имеет некоторые зависимости. Я указал зависимости в gemspec, и движок обнаруживает их при запуске bundle install (т.е. Gemfile.lock выглядит правильно). Когда я хочу использовать плагин в файле Ruby, я могу сделать это, но мне нужно явно require dependency-name в верхней части файла.

Однако, когда я хочу использовать конвейер активов зависимостей, звездочки не могут найти его.

Приложение, которое я использую (на данный момент), является фиктивным приложением, которое входит в тестовую папку с плагинами rails. Звездочки могут найти активы, если я укажу их в движке Gemfile (который действительно является фиктивным приложением Gemfile), но не если я укажу их в gemspec. Я не хочу полагаться на Gemfile, потому что это означает, что для любого приложения, использующего мой плагин, необходимо вручную добавить все мои зависимости в их Gemfile. По той же причине я не хочу, чтобы решение включало обновление файла конфигурации приложения.

Это работает (в рубиновом файле), когда зависимость от gemspec включена:

require 'dependency-name'

но это (в JS файле) не работает, когда зависимость включена в gemspec:

//= require 'dependency-name'

Ни один require не требуется, если зависимость включена в Gemfile. Я думаю, что это довольно ясно, но дайте мне знать, если вам нужно больше деталей.

Ответы

Ответ 1

Мне нужно было включить зависимость явно в мой engine.rb, чтобы его активы оказались в моем конвейере активов. Не уверен, почему это необходимо, поскольку ответ Аластора звучал правильно для меня. Стоит отметить, что зависимости - это драгоценные камни, которые я создал с помощью bundler, хотя я не понимаю, почему это должно иметь значение.

module MyRailsPluginFull
  class Engine < ::Rails::Engine
    require 'dependency1'
    require 'dependency2'
  end
end

Добавлено 11/23/12

Проведя еще некоторое время, работая с двигателями, я думаю, что теперь я понимаю это более полно. Gemspecs - это всего лишь список зависимостей, которые требуются, но gemspec не указывает приложению при загрузке загружать файлы из этих зависимостей. Gemfiles, с другой стороны, загружают все файлы во время запуска.

Добавлено 3/20/2015

Мое выражение более двух лет назад о том, что "Gemfiles, с другой стороны, загружает все файлы во время запуска", не совсем верно. В основном это относится к Rails, которая по умолчанию запускает Bundler.require, чтобы потребовать все зависимости, перечисленные в Gemfile, как показано в файле генератора здесь - обратите внимание, что, хотя значение по умолчанию поведение Rails изменилось с Rails3 на Rails 4, как обсуждалось здесь , оба используют Bundler.require. Тем не менее, для использования Bundler.setup существует сильный аргумент, а затем явный require "dependency1" в зависимости от того, какой файл фактически зависит от depedency1. См. эту дискуссию Bundler.require по сравнению с Bundler.setup.

Кроме того, как отмечает @nruth в комментариях, это может привести к загрузке ненужных классов. Однако, если зависимость хорошо разработана, ее классы будут в основном автозагружаться, создавая минимальные накладные расходы, требующие полной зависимости. В качестве альтернативы, если он определяет свой движок в файле, который может потребоваться изолированно, вы можете просто включить файл движка, который должен добавить необходимые файлы к вашему пути к ресурсам, что позволит вам потребовать его активы в ваших манифестах CSS и JS. См. этот пример бутстрап-сасса, где драгоценный камень добавляет все свои активы в 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 assets to the list of paths
      app.config.assets.paths << ...
    end
  end
end

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

Ответ 2

Вы разработали свой движок в соответствии с http://edgeguides.rubyonrails.org/engines.html? Если ваш класс движка наследует Rails:: Engine, он действительно должен найти все активы самостоятельно.