Как универсально пропускать штрихи базы данных при предварительной компиляции активов на Heroku
Я развертываю приложение Rails 3.1 в стек кера Героку. С Heroku Cedar и Rails 3.1 вы можете сами компилировать активы самостоятельно, пусть Heroku скомпилирует их, когда вы нажимаете (во время "компиляции слизняков" ) или их компилируете просто во время работы приложения. Я хочу сделать средний вариант, позволяя Heroku прекомпилировать активы.
Когда Heroku запускает активы: прекомпиляционная задача, ошибки с "не могут подключиться к серверу" , потому что приложение пытается подключиться к базе данных, но база данных отсутствует доступный на этом этапе компиляции пули. Отсутствие соединения с базой данных ожидается и неизбежно на данный момент. Я ищу способ пройти мимо него, потому что соединение с базой данных не имеет решающего значения для предварительной компиляции ресурсов.
Часть моего приложения, которое пытается подключиться к базе данных, - Devise. В строке маршрутов route.rb есть строка devise_for :users
, которая хочет посмотреть модель User.
Я мог бы просто написать граблиную задачу, которая заглушает devise_for и сделает ее предпосылкой для активов: precompile. Я думаю, что это решило бы мою проблему, но Я ищу более универсальное решение, которое я мог бы использовать в любом приложении Rails 3.1 с этой проблемой на Heroku.
Есть ли что-нибудь там, или вы можете понять что-либо, что затмевает ошибки подключения к базе данных, при этом все еще работает приложение достаточно, чтобы генерировать маршрут и путь к ресурсам?
Очевидно, что если приложение должно читать/записывать данные во время запуска, мы не можем его заглушить, но можем ли мы автоматически подделывать каждую модель ActiveRecord?
Ответы
Ответ 1
EDIT: этот ответ устарел и больше не работает. См. ответ fringd.
Не совсем универсальная укупорка, но разработка теперь добавила проверку, чтобы исправить эту конкретную проблему. См. issue и исправить в Github. Предоставляя конфигурацию конфигурации RAILS_ASSETS_PRECOMPILE, вы должны пропустить создание маршрутов
Ответ 2
добавить это в config/application.rb
config.assets.initialize_on_precompile=false
взял меня на время, чтобы выследить это... добавив его в config/environment/*. rb НЕ работал
ОБНОВЛЕНИЕ: он не работает с рельсами 4
Ответ 3
Heroku теперь создает флаг labs, который сделает среду выполнения доступной во время компиляции, а это значит, что ваше приложение будет который может успешно подключиться к вашей базе данных DATABASE_URL
.
Сначала вам нужно установить плагин labs:
$ heroku plugins:install http://github.com/heroku/heroku-labs.git
затем включите функцию user-env-compile
labs:
$ heroku labs:enable user-env-compile --app your-app-name
Ответ 4
Для меня проблема - это активировать вызов instantiate_observer
в lib/active_record/railtie.rb:92
. Это загрузит наблюдателей и соответствующие модели. has_and_belongs_to_many
затем соединяется с db.
Я думаю, что я переопределю этот метод, когда присутствует ENV["RAILS_ASSETS_PRECOMPILE"]
, который используется при создании исправления, связанного с Bradley.
EDIT: этот сниппл исправил его для меня:
namespace :assets do
# Prepend the assets:precompile_prepare task to assets:precompile.
task :precompile => :precompile_prepare
# This task will be called before assets:precompile to optimize the
# compilation, i.e. to prevent any DB calls.
task 'precompile_prepare' do
# Without this assets:precompile will call itself again with this var set.
# This basically speeds things up.
ENV['RAILS_GROUPS'] = 'assets'
# Devise uses this flag to prevent connecting to the db.
ENV['RAILS_ASSETS_PRECOMPILE'] = 'true'
# Prevent loading observers which will load the models which in turn may hit
# the DB.
module ActiveModel::Observing::ClassMethods
def instantiate_observers; end
end
# Prevent route drawing because certain gems might get called which will hit
# the DB.
class ActionDispatch::Routing::RouteSet
def draw; end
end
end
end
Ответ 5
Временное решение для Rails (4.2 edge):
Добавьте в качестве /config/initializers/precompile.rb
следующее:
module Precompile
# Public: ignore the following block during rake assets:precompile
def self.ignore
unless ARGV.any? { |e| e == 'assets:precompile' }
yield
else
line = caller.first
puts "Ignoring line '#{line}' during precompile"
end
end
end
и используйте его в routes.rb
следующим образом:
Precompile.ignore { ActiveAdmin.routes(self) }
Ответ 6
Я застрял в "lib/tasks/assets.rake" и смог получить активы: прекомпиляция на самом деле преуспела. Это должно работать до тех пор, пока вы фактически не получаете доступ к базе данных в результате требования вашей среды. Очевидно, что это не поможет с ActiveRecord, но он должен работать для всех приложений на основе mongoid.
task 'assets:precompile' => 'assets:stub_mongoid'
task 'assets:stub_mongoid' do
def Mongoid.load!(*args)
true
end
end
Ответ 7
Heroku добавил неофициальный флаг, чтобы сделать среду (то есть также БД) доступной во время предварительной компиляции. Просто попросите их включить его, а зависимости от БД во время предварительного компиляции активов больше не являются проблемой. Не уверен, если/когда этот флаг официально доступен, или если он будет просто новым значением по умолчанию.
Ответ 8
Spork.trap_method также является интересным решением проблемы Devise routes_ для вызова модели в начале процесса загрузки. Решение не может быть применено непосредственно AFAIK, но оно решает одну и ту же проблему, поэтому это может послужить источником вдохновения для кого-то.
Spork.trap_method
Ответ 9
Мне не хватает репутации, чтобы комментировать, так что вот еще один ответ.
Верно, что ответ на самый высокий рейтинг @fringd не работает на Rails 4. Я, однако, нашел, что этот метод работает:
https://iprog.com/posting/2013/07/errors-when-precompiling-assets-in-rails-4-0
Хотя, я перегруппировал переменные BASH следующим образом:
~$ RAILS_ENV=production DATABASE_URL=postgresql://user:[email protected]/dbname bundle exec rake assets:precompile
Кстати, это фантастическая помощь, если вам нужно создать образ Docker. Поместите эту строку в свой файл Docker, чтобы ваша БД могла жить в другом контейнере, а ваши контейнеры приложений не должны прекомпилировать активы каждый раз, когда они запускаются!
Ответ 10
Отключить AR:
config = Rails.application.config
def config.database_configuration
{}
end
ar = ActiveRecord::Base
def ar.establish_connection
end