Ruby on Rails - Альтернативы ИППП?

У меня много разных моделей (близких к 20), которые имеют некоторые общие атрибуты, но в какой-то степени отличаются и в других. Сначала STI кажется привлекательным, но я не знаю, как будут развиваться различные модели с течением времени с быстрой разработкой продукта.

Хорошей параллелью с нашим приложением, которое приходит на ум, является Yelp. Как бы Yelp справился с чем-то в Rails? Все сообщения имеют некоторые общие атрибуты, такие как "адрес". Тем не менее, они сильно отличаются друг от друга. Например, у вас есть опция резервирования для ресторанов и, возможно, не для других. В ресторанах также есть множество других атрибутов, таких как "Алкоголь разрешен", который не распространяется на других. Выполнение этого с помощью STI быстро выйдет из-под контроля.

Итак, каков следующий лучший вариант? HStore с Postgres? Мне не удобно использовать HStore для чего угодно, кроме мелочей. HStore решает некоторые проблемы, в то время как вводит других, таких как отсутствие типов данных, отсутствие проверок ссылочной целостности и т.д. Я бы хотел создать надежную реляционную базу данных. Так что в случае Yelp, вероятно, модель ресторана - это то место, где я собираюсь. Я рассмотрел такие предложения, как здесь: http://mediumexposure.com/multiple-table-inheritance-active-record/, но я не очень-то счастлив сделать так много патчей обезьян, чтобы получить что-то настолько распространенное собирается.

Так что мне интересно, какие существуют другие альтернативы (если есть), или я просто укушу пулю, перемалываю зубы и копирую эти общие атрибуты в 20 моделей? Я думаю, что мои проблемы возникли бы из файлов миграции, а не из самого кода. Например, если я настрою свои миграции для циклического перемещения по таблицам и установил эти атрибуты в таблицах, то я бы смягчил степень проблемы с использованием разных моделей?

Могу ли я игнорировать что-то важное, что может вызвать массу проблем в будущем с помощью отдельных моделей?

4
06 июля '13 в 5:12
источник поделиться
2 ответов

Здесь я вижу несколько вариантов:

  • Укусите пулю и создайте 20 разных моделей с множеством одинаковых атрибутов. Возможно, эти модели со временем будут дрейфовать - добавление новых полей в один конкретный тип - и вы создадите столбец 200 с STI. Может быть, вы этого не сделаете - будущее трудно понять, особенно с поисковым/гибким программным обеспечением.

  • Хранить не ссылочные поля в базе данных NoSQL (document). Используйте реляционную базу данных для частей реляционной записи (у пользователя много обзоров и обзор имеет один бизнес), но сохраняйте специфичные для типа данные в базе данных NoSQL. Храните external_document_id в своих моделях Rails и external_record_id/external_record_type в вашей схеме документов NoSQL, чтобы вы все равно могли запрашивать все бары, разрешающие курение, используя любой NoSQL ORM, который вы используете.

  • Создайте модель атрибутов. Атрибут belongs_to :parent_object, polymorphic: true с полем key и value. При таком подходе у вас может быть базовая модель Business, и каждый бизнес может has_many :attributes. Определенные (нереляционные?) Атрибуты бизнеса (allows_smoking) - это одна запись Attribute. Ключ Attribute может быть строкой или может быть номером, для которого есть константы Ruby. Фактически вы используете сущности Attribute для создания SQL-версии опции №2. Это может быть хорошим вариантом, и я сам использовал это для моделей User или Profile. (Хотя есть некоторые образы производительности, о которых следует знать при таком подходе).

Я действительно беспокоюсь о том, что у многих (независимых) моделей есть что-то, что звучит подклассом. Возможно, вы сможете DRY распространять поведение/методы, используя Concerns (синтаксический сахар над концепцией mixin, см. удивительный SO ответ на проблемы в Rails 4). Конечно, у вас все еще есть (начальная) проблема миграции.

6
06 июля '13 в 5:30
источник

Добавление другой опции здесь: Сериализованное LOB (272). ActiveRecord позволяет вам сделать это с помощью объекта serialize:

class User < ActiveRecord:: Base сериализовать: предпочтения конец

user = User.create(предпочтения: { "background" = > "черный", "display" = > large}) User.find(user.id).preferences # = > { "background" = > "black", "display" = > large}

(Пример кода из ActiveRecord:: Base docs.)

Важным последствием для понимания является то, что атрибуты, хранящиеся в серийном LOB, не будут индексируемыми и, конечно же, не доступны для поиска любым исполнительным образом. Если позже вы обнаружите, что столбец должен быть доступен в качестве индекса, вам нужно будет написать [наиболее вероятно] программу Ruby для выполнения преобразования (хотя по умолчанию сериализация выполняется в Yaml, поэтому любой парсер Yaml будет достаточным).

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

1
10 июля '13 в 6:29
источник

Посмотрите другие вопросы по меткам или Задайте вопрос