Короткая версия:
Как предоставить отдельные конфигурации ActiveRecord в rails app и gem (живущих в одном исходном коде) на основе одного и того же config/database.yml
. Конфигурации отличаются только schema_search_path
значением
Длинная версия:
У меня есть приложение rails ( parent ), и я извлекаю его часть в гем ( child ). Дочернее приложение - это просто драгоценный камень со своими моделями. Не двигатель рельсов или двигатель рельсов. Его модели будут жить в той же базе данных Postgres, но в отдельной схеме. Например. родительские модели приложений находятся в public
схемах, а дочерние модели приложений находятся в child
схемах.
В качестве идентификатора я управляю миграциями с помощью standalone-migrations
gem и запускаю миграции отдельно на parent и child , поэтому child получает свой собственный schema_migrations
таблица в его схеме
Rails позволяет включать в конфигурацию БД schema_search_path
, поэтому я планировал использовать ее для предоставления двух конфигураций.
Я бы хотел не копировать config/database.yml
в дочерний гем, поскольку файл будет на 100% одинаковым, за исключением schema_search_path
для каждой среды.
Моя идея (которая не работает) состояла в том, чтобы использовать railtie обратные вызовы инициализатора в геме child для установки Child::ApplicationRecord.configurations = conf_with_the_correct_schema_search_path
При таком подходе модели child (например, доступ к которым осуществляется с помощью Child::Name.all
) работают, но добавленная вручную конфигурация (в railtie) также используется для приложения parent . Поскольку единственная схема в schema_search_path
- это child
, ни одна из родительских моделей не будет найдена.
При назначении конфигураций вручную в консоли rails я могу получить доступ к обеим моделям приложения, пока я не выполню ModelBaseClass.establish_connection
, который будет использовать последнюю конфигурацию и сделает либо parent , либо child модели недоступны. Например.
- в родитель :
ApplicationRecord.configurations = YAML.load(...)
- in child : создать на основе родительского конфига
Пример дочерней конфигурации:
add_child_schema_lookup = ->(acc, keyval) do
k, v = keyval
acc.merge({k => v.merge(schema_search_path: 'child')})
end
child_configs = ApplicationRecord.configurations.reduce({}, &add_child_schema_lookup)
Child::ApplicationRecord.configurations = child_configs