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)
当我尝试做“动态常数”时,我偶然发现了这一点。
我的目标是能够将特定的数据库条目用作常量。(一旦插入,该行将在特定实例上永远不会改变,但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)
也许在开发模式下自动加载是问题所在?
将为每个请求重新创建模型类,因此您需要一次又一次创建常量。
该问题将在生产模式下消失。您可以在开发模式下关闭自动加载功能,但这将迫使您在代码中的每次更改后重新启动服务器。
参见config / environments / development.rb :(config.cache_classes = false更改为true)。