Quiero establecer un atributo de clase cuando se inicia mi aplicación Rails. Requiere inspeccionar algunas rutas, por lo que las rutas deben cargarse antes de que se ejecute mi código personalizado. Estoy teniendo problemas para encontrar un lugar confiable para enganchar enInicializador de rieles que se ejecuta * después de que se carguen las rutas?
Esta aplicación funciona perfectamente en el entorno de "prueba":.
config.after_initialize do
Rails.logger.info "#{Rails.application.routes.routes.map(&:path)}"
end
Pero no trabajo en el entorno de "desarrollo" (las rutas están vacíos)
Por ahora parece que tengo cosas que funcionan en modo de desarrollo ejecutando el mismo código en config.to_prepare
que entiendo sucede antes de cada solicitud. Desafortunadamente, usar to_prepare
solo no parece funcionar en modo de prueba, de ahí la duplicación.
Tengo curiosidad por saber por qué las rutas se cargan antes de after_initialize en modo de prueba, pero no en modo de desarrollo. Y realmente, ¿cuál es el mejor gancho para esto? ¿Hay un solo gancho que funcione para todos los entornos?
* * EDITAR sugerencia
de mu de recarga de las rutas era grande. Me dio acceso constante a las rutas dentro de after_initialize en todos los entornos. Para mi caso de uso, creo que todavía necesito ejecutar el código de to_prepare también, ya que estoy configurando un atributo de clase en un modelo y los modelos se vuelven a cargar antes de cada solicitud.
Así que esto es lo que terminé haciendo.
[:after_initialize, :to_prepare].each do |hook|
config.send(hook) do
User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq
end
end
Parece un poco complicado para mí. Creo que prefiero hacer algo como:
config.after_initialize do
User.exclude_routes_from_usernames!
end
config.to_prepare do
User.exclude_routes_from_usernames!
end
Pero no estoy seguro de si User
es el lugar adecuado para estar examinando Rails.application.routes
. Creo que podría hacer lo mismo con el código en lib/pero no estoy seguro si eso es correcto tampoco.
Otra opción es simplemente aplicar la sugerencia de mu en to_prepare. Eso funciona, pero parece que hay un retraso notable en volver a cargar las rutas en cada solicitud en mi entorno de desarrollo, por lo que no estoy seguro de si esta es una buena opción, aunque es SECO, al menos.
config.to_prepare do
Rails.application.reload_routes!
User.invalid_usernames += Rails.application.routes.routes.map(&:path).join("\n").scan(/\s\/(\w+)/).flatten.compact.uniq
end
Gran idea! Resulta que en realidad estamos usando esto para la misma cosa (estoy actualizando un 'atributo_categoría' llamado' Usuario.nombres_válidos_inválidos' que se usa como una lista de exclusión con 'validates_exclusion_of'). Creo que todavía necesito el to_prepare para el modo de desarrollo. Sin él, funciona bien en la primera solicitud (ahora que estoy usando tu sugerencia), pero después de eso creo que mi 'User.invalid_usernames = Set.new' lo está golpeando. Parece que solo estás usando after_initialize, así que me pregunto si hay alguna forma inteligente de solucionarlo. – poochenza
Esta respuesta me ayudó mucho, así que la acepto aunque no termine usándola (¡abierta a críticas si crees que debería hacerlo!) Aquí está mi solución completa, me encantaría tu opinión si tienes tiempo: http: //stackoverflow.com/a/8713207/1126857 – poochenza
@poochenza: utilicé 'after_initialize' para asegurarme de que no aparecían nuevos conflictos entre lanzamientos: si agrega una ruta'/pancakes' y publica dos semanas más tarde, desea saber si Al mismo tiempo, alguien creó un usuario de "panqueques" en el sistema de producción. Luego comparo los nuevos nombres de usuario con las rutas a medida que se crean o actualizan los nombres de usuario. –