Considere una aplicación de Rails 6 que tenga app/models/application_record.rb . Esta aplicación de Rails 6 utiliza el cargador Zeitwerk.
class ApplicationRecord endSi quiero agregar funcionalidad a ApplicationRecord a través de un módulo:
# app/models/concerns/fancy_methods.rb module FancyMethods def fancy_pants puts "I'm wearing fancy pants" end endy haz lo siguiente:
class ApplicationRecord include FancyMethods endRecibiré una advertencia o un error de desaprobación:
DEPRECATION WARNING: Initialization autoloaded the constant FancyMethods. Being able to do this is deprecated. Autoloading during initialization is going to be an error condition in future versions of Rails. Reloading does not reboot the application, and therefore code executed during initialization does not run again. So, if you reload FancyMethods, for example, the expected changes wont be reflected in that stale Module object. This autoloaded constant has been unloaded. Please, check the "Autoloading and Reloading Constants" guide for solutions. (called from <top (required)> at /Users/peter/work/recognize/config/environment.rb:5) He leído muchos artículos, incluidos los documentos de carga automática de Rails , pero nada aborda realmente este caso mínimo pero común de extender ApplicationRecord. Sí, podría envolver ApplicationRecord en un bloque .to_prepare como:
Rails.configuration.to_prepare do class ApplicationRecord < ActiveRecord::Base include FancyMethods end endPero esto parece un olor a código y podría causar otros problemas inesperados ahora o en el futuro.
¡Lo averigué! El problema era que había un requerimiento explícito en un inicializador que cargaba ApplicationRecord.
# config/initializers/setup_other_fancy_thing.rb require 'application_record' module OtherFancyThing def also_fancy puts 'also fancy' end end ApplicationRecord.send(:include, OtherFancyThing)La forma en que depuré esto fue que yo:
config/initializers a un directorio temporal e hizo que la advertencia desapareciera! Entonces, sabía que tenía que ser uno de los inicializadores. A partir de ahí, solo fue cuestión de dividir y conquistar hasta que encontré el inicializador infractor.¡Estupendo! Entonces, básicamente, no necesita definir el módulo e incluirlo de esa manera. Idiomáticamente, defines el módulo en su propio archivo, normal:
# app/models/other_fancy_thing.rb module OtherFancyThing def also_fancy puts 'also fancy' end endy luego
# app/models/application_record.rb class ApplicationRecord include FancyMethods end Cada vez que se carga ApplicationRecord , por ejemplo, como un efecto secundario o cargando algún modelo normal, se cargará FancyMethods sin problemas.