在Ruby on Rails中,如何在开发模式下使全局常量可以自动重新加载,而无需重启服务器?

3

例如,我目前将全局常量放在config/initializers/constants.rb文件中,其内容如下:

KB = 1000

我希望我的应用程序在添加此行代码后,无需重新启动服务器即可立即识别MB

MB = KB * KB

这个可能吗?
2个回答

5

初始化程序是设计为仅在应用程序初始化时执行一次的。如果您希望某些内容可以重新加载,请将其放在lib文件夹内的单独模块中。这里有一个完整的主题,关于自动加载和重新加载常量

  module Colors
    RED = '0xff0000'
  end
请注意,您还需要调整您的application.rb文件。
 config.autoload_paths << "#{Rails.root}/lib"

因此,对于您的情况,它将是 lib 内的一个文件 constants.rb:
module Constants
  KB = 1000
end

然后在您的类中,您可以使用您的常量:

class Something
  include Constants
  MB = KB * KB
end

如果您在页面重新加载时更改KB的值,则MB将随之更改,而无需重启。


1
这个想法是可行的。 如果基类 ApplicationController 的主体“include Constants”,它可以适用于所有 XxxController。 如果 ApplicationHelper 的主体“include Constants”,并且所有其他 XxxHelper 的主体“include ApplicationHelper”,它可以适用于 *.html.erb 和所有 XxxHelper。 - Johnny Wong
但是我们如何确保所有的app/models/*.rb都可以使用这个常量呢?在所有模型类中“include Constants”还不够令人满意...但是答案仍然是有用的。 - Johnny Wong
1
@JohnnyWong:那就切换到Rails 5吧。在那里,所有的模型都是从抽象的ApplicationRecord继承而来,你可以在那里包含你的常量。另外,我有点怀疑你是否想要无法控制地在每个地方都包含某些东西。这可能会导致各种命名冲突等问题。 - user4776684

0

受gen的答案启发,下面的解决方案似乎也可以工作。

  1. config/application.rb:

    ...
    config.autoload_paths << "#{Rails.root}/lib"
    ...
    
  2. config/initializers/init_constants.rb:

    require 'constants'
    
  3. lib/constants.rb:

    KB = 1000
    MB = KB * KB
    
  4. app/controllers/applicaton_controller.rb(在 ApplicationController 类之后):

    class ApplicationController ...
      ...
    end
    require_dependency 'constants' if Rails.env.development?
    

常量似乎在每个请求中自动重新加载。

不太确定为什么会这样工作。


1
我认为第二步是不必要的。 - Ashish Bista
@AshishBista 是的,它可以是可选的。然而,这可能取决于常量是否需要在配置和初始化阶段使用? - Johnny Wong
如果省略步骤2,我怀疑在ApplicationController加载之前使用KB的其他类将未定义。我认为ApplicationController可能不总是第一个自动加载的类。但是,是的,在应用程序早期初始化时,代码留下了常量重复定义的警告。 - Johnny Wong
我相信第一步会处理所有这些事情。 - Ashish Bista
@AshishBista 我检查过,大多数情况下它是有效的。 一些不太常见的情况可能无法正常工作,例如当您需要执行某些依赖于某些config/initializers/*.rb文件中某些常量的操作时。一个简单的例子是在步骤2中将require 'constants'替换为puts "#{KB}"。因此,我认为保留该行代码进行早期初始化是可以的。 :) - Johnny Wong

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接