ruby-on-rails - rails - heroku panel
Cómo omitir universalmente toques de base de datos al precompilar los recursos en Heroku (10)
Estoy implementando una aplicación Rails 3.1 en la pila Cedar de Heroku. Con Heroku Cedar and Rails 3.1 , puede compilar los activos usted mismo localmente, deje que Heroku los compile cuando presione (durante la "compilación de slug"), o haga que se compilen justo a tiempo mientras se ejecuta la aplicación. Quiero hacer la opción del medio, dejar que Heroku precompile los activos.
Cuando Heroku ejecuta los activos: tarea de precompilación, los errores con "no se pudo conectar al servidor" porque la aplicación está intentando conectarse a la base de datos, pero no hay ninguna base de datos disponible en esa etapa de compilación de slug. La falta de conexión a la base de datos es esperable e inevitable en este momento. Estoy buscando una forma de superarlo, porque una conexión de base de datos no es crucial para la precompilación de activos.
La parte de mi aplicación que intenta conectarse a la base de datos es Devise. Hay una línea devise_for :users
en routes.rb que quiere ver el modelo de Usuario.
Podría escribir una tarea de rake que resuelva devise_for y conviértalo en un prerrequisito de activos: precompilar. Creo que eso resolvería mi problema, pero estoy buscando una solución más universal que pueda usar en cualquier aplicación de Rails 3.1 con este problema en Heroku.
¿Hay algo por ahí, o puede concebir algo que silencie los errores de conexión a la base de datos mientras todavía se ejecuta la aplicación lo suficiente como para tener la ruta y la generación del camino de los activos?
Obviamente, si una aplicación necesita leer / escribir datos durante el inicio, no podemos resumir eso, pero ¿podemos falsificar todos los modelos de ActiveRecord automáticamente?
Deshabilitar AR:
config = Rails.application.config
def config.database_configuration
{}
end
ar = ActiveRecord::Base
def ar.establish_connection
end
EDITAR: Esta respuesta está desactualizada y ya no funciona. Consulte la respuesta de fringd.
No es un trozo universal, pero el dispositivo ha agregado un cheque ahora para solucionar este problema en particular. Mira el issue y fix a Github. Al proporcionar un entorno de configuración RAILS_ASSETS_PRECOMPILE, el dispositivo de configuración debe omitir la construcción de las rutas.
Heroku agregó una bandera no oficial para hacer que el entorno (es decir, también el DB) sea accesible durante la precompilación. Solo pídales que lo enciendan y las dependencias de DB durante las precompilaciones de activos ya no sean un problema. No estoy seguro, si / cuando esta bandera está oficialmente disponible, o si simplemente será el nuevo valor predeterminado.
Heroku ahora tiene disponible un indicador de labs que hará que el entorno de tiempo de ejecución esté disponible durante el tiempo de compilación, lo que significa que su aplicación podrá conectarse con éxito a su base de datos DATABASE_URL
.
Primero necesitas instalar el plugin de labs :
$ heroku plugins:install http://github.com/heroku/heroku-labs.git
luego habilite la función de laboratorios de user-env-compile
:
$ heroku labs:enable user-env-compile --app your-app-name
Me falta reputación suficiente para comentar, así que aquí hay otra respuesta.
Es cierto que la respuesta máxima de @ fringd no funciona en Rails 4. Sin embargo, he encontrado que esta técnica funciona:
https://iprog.com/posting/2013/07/errors-when-precompiling-assets-in-rails-4-0
Aunque reorganicé las variables de BASH de esta manera:
~$ RAILS_ENV=production DATABASE_URL=postgresql://user:[email protected]/dbname bundle exec rake assets:precompile
Por cierto, esta es una ayuda fantástica si necesitas construir una imagen Docker. ¡Pon esa línea en tu archivo Docker para que tu base de datos pueda vivir en un contenedor diferente y los contenedores de tu aplicación no necesiten precompilar los activos cada vez que se inicien!
Para mí, el problema es activerecord llamando a instantiate_observer
en lib/active_record/railtie.rb:92
. Esto cargará los observadores y los respectivos modelos. has_and_belongs_to_many
luego se conecta al db.
Creo que ENV["RAILS_ASSETS_PRECOMPILE"]
este método cuando esté presente ENV["RAILS_ASSETS_PRECOMPILE"]
, que se usa en la solución a la que se vincula Bradley.
EDITAR: Así que este fragmento me lo arregló:
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
Puse esto en ''lib / tasks / assets.rake'' y pude obtener activos: la precompilación para tener éxito. Esto debería funcionar siempre y cuando no accedas a la base de datos como resultado de requerir tu entorno. Obviamente no ayudará con ActiveRecord, pero debería funcionar para todas las aplicaciones basadas en mongoid.
task ''assets:precompile'' => ''assets:stub_mongoid''
task ''assets:stub_mongoid'' do
def Mongoid.load!(*args)
true
end
end
Solución para Rails (4.2 edge):
Agregue lo siguiente como /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
y routes.rb
en tu routes.rb
así:
Precompile.ignore { ActiveAdmin.routes(self) }
Spork.trap_method también es una solución interesante al problema de las rutas de Devise para llamar al modelo al principio del proceso de carga. La solución no se puede aplicar directamente AFAIK, pero está resolviendo el mismo tipo de problema, por lo que podría proporcionar inspiración para alguien.
agregar esto a config / application.rb
config.assets.initialize_on_precompile=false
me tomó un tiempo buscar esto ... agregarlo a config / environments / *. rb NO funcionó
ACTUALIZACIÓN : no funciona con rieles 4