Определение динамической константы в Rails

Я определяю константу в инициализаторе в Rails, используя следующий синтаксис:

MyModule.const_set('MYCONSTANT','foobar')

Он работает, если я запускаю консоль и пишу

MyModule::MYCONSTANT 

Я получаю foobar, как ожидалось.

Проблема в том, что когда я пытаюсь вызвать ее в модели, константы там нет.

Где D должна динамически определять мою константу, что она может быть доступна и в моих моделях?

Если я статически определяю его в своем lib/mymodule.rb, он работает, но я бы хотел определить некоторые константы во время выполнения.

Ответ 1

Может быть, автозагрузка в режиме разработки является проблемой?

Ваш класс модели воссоздается для каждого запроса, поэтому вам нужно будет создавать константу снова и снова.

Проблема просто исчезнет в режиме производства. Вы можете отключить автозагрузку в режиме разработки, но это заставит вас перезапустить сервер после каждого изменения вашего кода.

См. config/environment/development.rb: config.cache_classes = false (изменение на true).

Ответ 2

если вы хотите сохранить config.cache_classes = false, вы можете поставить

MyModule.const_set('MYCONSTANT','foobar')

в следующий блок в application.rb:

config.to_prepare do
MyModule.const_set('MYCONSTANT','foobar')
end

Ответ 3

Я наткнулся на это, поскольку я пытался сделать "динамические константы".

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

Я придумал решение, которое может применяться к этому случаю в зависимости от того, почему вы пытаетесь создать динамические константы. Вот пример в моей утилите, но довольно легко заменить определение атрибута чем-то другим.

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

И вот как я его протестировал:

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