Rails中的动态常量定义

VP.*_*VP. 19 ruby metaprogramming ruby-on-rails

我使用以下语法在Rails中的初始化程序中定义一个常量:

MyModule.const_set('MYCONSTANT','foobar')
Run Code Online (Sandbox Code Playgroud)

它工作,如果我启动一个控制台并写

MyModule::MYCONSTANT 
Run Code Online (Sandbox Code Playgroud)

我按预期收到了foobar.

问题是,当我尝试在模型中调用它时,常量不存在.

D应该在哪里动态定义我的常量,它在我的模型中也可以使用?

如果我在我的lib/mymodule.rb中静态定义它,它可以工作,但我想在运行时定义一些常量.

小智 16

如果你想保留config.cache_classes = false,你可以把

MyModule.const_set('MYCONSTANT','foobar')
Run Code Online (Sandbox Code Playgroud)

进入application.rb中的以下块:

config.to_prepare do
MyModule.const_set('MYCONSTANT','foobar')
end
Run Code Online (Sandbox Code Playgroud)


Cry*_*ark 6

当我尝试做“动态常数”时,我偶然发现了这一点。

我的目标是能够将特定的数据库条目用作常量。(一旦插入,该行将在特定实例上永远不会改变,但ID在不同实例上可以不同)。

我想出了一种解决方案,可以根据您尝试使用动态常量的原因来应用于这种情况。这是我用例中的一个示例,但是用其他方法替换属性定义相当容易。

class MyModel < ActiveRecord::Base
  def self.MY_CONST
    @my_const ||= MyModel.find_by(code: 'my_const_code')
  end
end
Run Code Online (Sandbox Code Playgroud)

这是我测试的方式:

require 'test_helper'

class MyModelTest < ActiveSupport::TestCase
  test "mymodel constant defined" do
    assert_equal MyModel.find_by(code: 'my_const_code'), MyModel.MY_CONST
  end
end
Run Code Online (Sandbox Code Playgroud)


Ars*_*en7 5

也许在开发模式下自动加载是问题所在?

将为每个请求重新创建模型类,因此您需要一次又一次创建常量。

该问题将在生产模式下消失。您可以在开发模式下关闭自动加载功能,但这将迫使您在代码中的每次更改后重新启动服务器。

参见config / environments / development.rb :(config.cache_classes = false更改为true)。