Как мне структурировать Rakefile с некоторыми задачами, которые должны выполняться во время развертывания, и другими, которые даже не могут быть определены во время развертывания?

Я работаю с простым (или я так думал) приложением Sinatra, которое использует несколько гемов на разных этапах цикла разработки / развертывания приложения:

  • Бандлер для управления зависимостями
  • Грабли для задач сборки
  • Звездочки для прекомпиляции активов
  • RSpec 2 для испытаний
  • Капистрано для развертывания

Gemfile включает в себя rspec в test группа.

Rakefile определяет assets:compile задача по переводу Sass в CSS и CoffeeScript в JavaScript и конкатенации полученных файлов.

Капистрано бежит bundle install --without development test поэтому на рабочий сервер устанавливаются только гемы, необходимые для производства (и компиляции активов). Он также запускает задачу Cap, которая в конечном итоге выполняется bundle exec rake assets:compile на сервере.

Пока это все хорошо, но я бы хотел добавить задачу RSpec Rake в мой Rakefile, и там все пошло не так. Он работает нормально, когда я бегу локально, но когда я бегу cap deploy Я получаю сообщение об ошибке на сервере: no such file to load -- rspec/core/rake_task,

Это имеет смысл: RSpec не устанавливается на сервере, когда мы устанавливаем пакет, и задача spec на самом деле никогда не будет выполняться там. Ошибка происходит только из-за попытки определить задачу.

Я могу придумать несколько вариантов, чтобы справиться с этим, но ни один из них не кажется мне вполне подходящим:

  • Заворачивать require 'rspec/core/rake_task' в begin...rescue блокировать и игнорировать ошибки
  • принимать rspec вне test группа или иным образом заставить его быть установленным на сервере
  • Используйте другой rakefile во время развертывания, который включает только assets:compile задача
  • Определите мое собственное spec задача, которая требует только RSpec при вызове
  • Запускайте прекомпиляцию локально, а не на сервере (мой любимый из этих вариантов)

Каковы лучшие практики здесь?

3 ответа

Решение

Лично, учитывая, что Rake не вызывается на сервере очень часто, я бы сделал его простым и удобным rescue:

begin
  require 'rspec/core/rake_take'
rescue LoadError
end

Я не уверен, почему с Rails я никогда не сталкивался с этим.

Я бы решил это, сделав

require 'rspec/core/rake_task' if defined?(RSpec)

Аргументация проста. Другие решения, вероятно, также подойдут, но я считаю, что они добавляют больше сложности, чем гибкости. Если в будущем появится больше подобных случаев, я бы рассмотрел альтернативное решение.

У меня была почти идентичная проблема.

Не уверен, что это "лучшая практика", но в итоге я сделал это в Rakefile:

if (Rails.env.migration? || Rails.env.production?)
  # define rake tasks that depend on gems installed only in dev/test envs
end

(Я использую отдельную среду для миграций, которая указывает на ту же базу данных, что и рабочая, но имеет более высокие привилегии базы данных, необходимые для внесения изменений в схему.)

Другие вопросы по тегам