Rails重新加载!重置 class 个变量,需要重新运行一些初始化程序

Rails reload! resets class variables, need to rerun some initializers

假设我需要解析一些配置来实例化一些服务单例(可以使用或不使用 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 变量被清除,这是一个问题...

有吗

您可以将配置方法定义为:

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

并调用这个方法而不是@config,所以当配置变量被取消设置时,它会被重新设置,否则它会return值。

看到人们还在阅读这篇文章,这是我最终得到的实现

# 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

我没有显示我的连接器 class SlackConnector,但基本上你可以从它的调用方式猜出接口。您需要设置 webhook url,并执行其他操作。实现是分离的,所以可以在 Rails 和 Capistrano 中使用相同的 SlackConnector 进行部署,所以它基本上在 lib/ 文件夹中