Рельсы перезагружаемся! сбрасывает переменные класса, необходимо перезапустить некоторые инициализаторы

Предположим, мне нужно проанализировать некоторую конфигурацию, чтобы создать экземпляры некоторых Service Singleton (которые можно использовать с Rails или без него).

Пример примера кода:

#services/my_service.rb
module MyService
    @config = nil

    def self.load_config(config)
      @config = config
    end

При использовании с Rail (или Capistrano, SInatra и т. д.) я бы использовал инициализатор для загрузки службы.

#initializers/svc.rb
MyService.load_config(Rails.application.secrets.my_service.credentials)

Но при использовании специально с Rails на каждой консоли rails restart! эта переменная @config очищается, что является проблемой...

Здесь

  • after-reload! ловушки, которые я мог бы использовать для повторного запуска инициализатора?
  • другие типы переменных, которые будут сохранены во время restart!, которые я мог бы использовать здесь?

person Cyril Duchon-Doris    schedule 23.11.2016    source источник
comment
Это старый вопрос, но поскольку есть новые читатели: хуки после перезапуска и т. д. доступны внутри ActiveSupport::Reloader из Rails 5. См. документ rubydoc.info/gems/activesupport/ActiveSupport/Reloader   -  person Cyril Duchon-Doris    schedule 19.08.2017


Ответы (2)


Вы можете определить метод конфигурации как:

def config @config ||= Rails.application.secrets.my_service.credentials end

И вызовите этот метод вместо @config, поэтому, когда переменная конфигурации не установлена, она будет установлена ​​​​снова, иначе она вернет значение.

person Fede Bonisconti    schedule 19.08.2017
comment
Проблема здесь в том, что вы связываете реализацию с фреймворком Rails. Я разделился на инициализатор (который просто предоставляет учетные данные) и сам сервис, потому что сервис можно было использовать вне Rails, а задачей инициализатора была передача секретов Rails. Я добавлю это к моему вопросу, а также к тегу Ruby - person Cyril Duchon-Doris; 19.08.2017
comment
Это правда. Как насчет использования файла yaml вместо секретного? Вы избежите связывания логики между фреймворком и ключами. (Я думаю, что ваша проблема не очень распространенная проблема, ха-ха) - person Fede Bonisconti; 19.08.2017

Видя, что люди все еще читают это, вот реализация, с которой я закончил

# config/initializers/0_service_activation.rb
# Activation done at the end of file

module ServiceActivation
  def self.with_reload
    ActiveSupport::Reloader.to_prepare do
      yield
    end
  end

  module Slack
    def self.service
      ::SlackConnector
    end

    def self.should_be_activated?
      Utility.production? ||
      Utility.staging? ||
      (
        Utility.development? &&
        ENV['ENABLE_SLACK'] == 'true'
      )
    end

    def self.activate
      slack = service
      slack.webhook = Rails.application.secrets.slack&.dig(:slack_webhooks)
      Rails.application.secrets&.dig(:slack, :intercept_channel).try do |channel|
        slack.intercept_channel = channel if channel.present?
      end
      slack.activate
      slack
    end
  end

[
  ServiceActivation::Intercom,
  ServiceActivation::Slack,
  ServiceActivation::Google
] .each do |activator|
  ServiceActivation.with_reload do
    activator.activate if activator.should_be_activated?
    activator.service.status_report
  end
end

Я не показываю свой класс коннектора SlackConnector, но в основном вы можете догадаться об интерфейсе по тому, как он называется. Вам нужно установить URL-адрес веб-перехватчика и сделать другие вещи. Реализация разделена, поэтому можно использовать один и тот же SlackConnector в Rails и в Capistrano для развертывания, поэтому он в основном находится в папке lib/.

person Cyril Duchon-Doris    schedule 03.05.2019