Rails 6 Zeitwerk выгружает мой класс после инициализатора - PullRequest
0 голосов
/ 09 апреля 2020

Я реализую класс / модуль синглтона в приложении Rails 6, используя загрузчик Zeitwerk.

# app/lib/mynamespace/mymodel.rb

module Mynamespace
  module Mymodel
    class << self
      attr_accessor :client
    end

    def self.client
      @client ||= "default_value"
    end

    def self.client=(client)
      @client = client
    end
end

Класс Singleton инициализируется в

# config/initializers/mymodel.rb

Mynamespace::Mymodel.client = "my_custom_value"
# Mynamespace::Mymodel.client - this returns correct value

Затем, когда я использую класс синглтона в контроллер

# app/controllers/mycontroller.rb

client = Mynamespace::Mymodel.client

возвращает пустой объект, поскольку он не был инициализирован: client == "default_value", но должен иметь значение "my_custom_value".

Журнал показывает ошибки

DEPRECATION WARNING: Initialization autoloaded the constants Mynamespace::Mymodel

Autoloading during initialization is going to be an error condition in future versions of Rails.

Как правильно настроить одноэлементный класс при использовании Zeitwerk?

1 Ответ

0 голосов
/ 09 апреля 2020

Я считаю, что проблема в том, что, как Zeitwerk загружает ваш код, он сначала загружает Gems из вашего Gemfile, затем запускает инициализаторы, затем загружает код вашего приложения, поэтому попытка запустить Mynamespace::MyModel.client означает, что он должен остановить то, что выполнить и загрузить app/lib/mynamespace/mymodel.rb, чтобы загрузить эту константу, выполнить для нее client=.

Это также означает, что если вы измените код Mynamespace::MyModel, Rails не сможет выполнить горячую перезагрузку константы, поскольку инициализаторы не перезапускаются, вводится циклическая блокировка зависимостей (вы когда-нибудь видели ошибку типа «модуль MyModel удален из дерева, но все еще активен!» или вам пришлось использовать require_dependency перед использованием некоторого кода, который должен быть загружен автоматически, но нет?). Zeitwerk пытается исправить этот класс проблем.

Переместите этот код из config/initializers в config/application.rb, и он все равно будет запускаться при загрузке.

...