Динамическое создание моделей и/или таблиц в Rails

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

Итак, вот что мне нужно сделать. Приложение хранит и управляет различными типами медиафайлов, но каждое развертывание приложения имеет совершенно разные требования к метаданным для медиафайлов.

Эти метаданные могут содержать произвольное количество полей разных типов (однострочный текст, многострочный текст, флажки, выбранные значения и т.д.), а также часто требуют проверки, в частности, проверки присутствия и уникальности.

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

Один из вариантов, который я рассмотрел, - это использование структуры списка свойств, в которой таблица базы данных просто содержит имя и значение свойства для каждого поля метаданных каждого медиафайла. Однако при прототипировании этого решения быстро стало очевидно, что он просто не будет достаточно эффективным для поиска и поиска записей, особенно когда база данных может быть достаточно большой, например. в недавнем развертывании было 3000 мультимедийных файлов, и было более 20 полей метаданных. Кроме того, запросы на поиск и извлечение соответствующих записей быстро стали очень сложными.

Другой вариант, который используется в настоящее время системой, заключается в том, что конфигурация метаданных определена заранее, и миграция выполняется во время развертывания для создания таблицы и модели со стандартным именем, чтобы связать с ней модель мультимедиа, с которой система затем использует. Это обычно работает очень хорошо, но это вызывает некоторые значительные проблемы с развертыванием и тестированием.

Например, тесты с модулем записи становятся намного более сложными, если вы не знаете конфигурацию до развертывания. Хотя я мог бы написать образец конфигурации и протестировать код таким образом, он не позволит мне проверить конкретные требования конкретного развертывания.

Аналогично, в разработке в настоящее время мне нужно скопировать перенос из конфигурации в основную папку, запустить ее, выполнить все мои тесты и разработки, а затем я должен помнить о откате и удалении этой миграции из основной папки так что приложение находится в стандартном состоянии. Это особенно сложно, когда я исправляю ошибку, и мне нужно, чтобы приложение было настроено в определенной конфигурации для тестирования и отладки. Попытка переключаться между различными конфигурациями становится настоящим кошмаром.

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

Я уверен, что это можно сделать с помощью Rails, но есть очень мало информации, которую я смог найти, которая может указать мне в правильном направлении, как ее построить во время моих исследований за последние несколько дней, чтобы любой помощь или предложения были бы высоко оценены!

Ответ 1

Если я правильно вас понимаю, у Rails есть несколько отличных трюков, которые помогут вам решить эти проблемы.

В ORM ActiveRecord можно моделировать то, что вы пытаетесь сделать в реляционной базе данных, либо с использованием шаблона наследования одиночной таблицы, либо с помощью полиморфных ассоциаций (... немного сложнее, но более гибко). Полиморфная ассоциация позволяет модели относиться к другим типам других моделей. Там в последнее время railscast по этой теме, но я не буду ссылаться на нее, поскольку она требует платной подписки.

На стороне развертывания звучит так, будто вы делаете много вещей вручную, это правильный способ начать, пока не появится шаблон. После того, как вы начнете видеть шаблон, есть отличные программы для автоматизации конфигурации, сборки и развертывания, такие как Capistrano, OpsCode "Шеф-повар" и Puppet, чтобы назвать лишь некоторые из них. Вам также может быть полезно интегрировать вашу конфигурацию и развертывание с репозиторием исходного кода, чтобы обеспечить лучший рабочий процесс. Например, с помощью Git вы можете определить ветки тем для различного типа медиафайла и иметь разную конфигурацию в каждой ветки, которая соответствует ветки темы.

Вы можете проверить отличную книгу Мартина Фаулера "PoEAA и некоторые из тем на веб-сайт. Надеюсь, этот ответ поможет, хотя ответ довольно общий. Ваш вопрос очень широк и не имеет простого ответа.

Ответ 2

каждое развертывание приложения имеет совершенно разные метаданные требования к медиафайлам.

Я рекомендую использовать mongoDB для вашей базы данных и Mongoid для вашего ORM. Это даст вам гибкость, необходимую для изменения схемы по мере необходимости без ужасающих манипуляций с схемами, динамических моделей/таблиц и всего этого ужаса.

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

Это проблема поиска, а не проблема с базой данных. Я рекомендую проверять возможности полнотекстового поиска в последней версии mongoDB. Если это не соответствует вашим потребностям, попробуйте elasticsearch в сочетании с Tire gem (клиент elasticsearch, который прекрасно сочетается с Rails).

Ответ 3

То, что вы описали, звучит точно так же, как и определяющие требования к нетрадиционному механизму хранения, в котором используется хранилище с ключом.

Я чувствую это от:

  • "полностью разные требования к метаданным" и "-" произвольное количество полей разных типов "- хранилища данных с ключевыми значениями часто не имеют схемы и очень гибки для разных макетов записей, которые меняются" на лету ".

  • Приложение должно иметь возможность легко извлекать значения и, самое главное, иметь возможность обрабатывать полные возможности поиска в этих полях. Хранилища ключевого значения сделаны чрезвычайно эффективными при извлечении и фильтрации строк для запросов.

'Структура списка свойств, в которой таблица базы данных просто содержит имя и значение свойства для каждого метаданных, представляет собой в основном хранилище значений ключей.

Некоторые параметры:

Ответ 4

Я вижу несколько разумных способов приблизиться к этому, в зависимости от ваших точных требований:

  • Если это не запрещено писать модели и миграции для каждого из ваших наборов метаданных, тогда продолжайте и создайте модель и выполните миграцию для каждого из них. Затем в вашем конфигурационном файле для каждой среды - например, config/development.rb - загрузить желаемую модель для этой среды в глобальную константу (возможно, ModelConfiguration::MetadataModel внутри lib/model_configuration.rb). Запишите остальную часть вашего приложения, чтобы взаимодействовать только с вашей моделью метаданных с помощью этой константы.

    Этот подход достаточно эффективен; его единственным реальным недостатком является то, что вы создаете дополнительную таблицу в своей базе данных для каждой модели. Во время выполнения неиспользуемые модели никогда не загружаются, поэтому они вообще не влияют на вашу производительность.

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

    • Попросите свой конфигуратор загрузить текущую желаемую конфигурацию модели в глобальную константу в некоторой легко усваиваемой форме (возможно, ModelConfiguration::ModelJSON).

    • Напишите один класс модели, который при загрузке выглядит в ModelConfiguration::ModelJSON и вызывает метод класса для установки соответствующих полей и проверок на себя из этой конфигурации.

    • Напишите задачу Rake для создания таблицы в соответствии с вашей конфигурацией. См. http://edgeguides.rubyonrails.org/command_line.html#custom-rake-tasks для быстрого свертывания того, как писать задачу Rake. Простейший подход, вероятно, заключается в создании одноразовой миграции из вашего конфига, а затем запуск этой миграции (путем вызова .up на нем). Недостатком здесь является то, что однократная миграция исчезнет после выполнения задачи, поэтому вы потеряете доступ к rake db:rollback.

    Этот подход очень общий, и его самым большим преимуществом является то, что вам не нужно менять код, чтобы получить изменение конфигурации, что дает вам большую свободу в том, как вы храните и развертываете свои конфигурации.