Моделирование таблицы пользователей для одной базы данных нескольких приложений - PullRequest
1 голос
/ 29 апреля 2019

Скажем, у нас есть 3 разных приложения - serviceapp, subscriptionapp, ecomapp, все они написаны в ruby ​​на рельсах и используют одну и ту же базу данных в бэкенде и таблицы в бэкэнде. Таким образом, таблица пользователей для всех этих трех приложений одинакова. Если пользователь является частью serviceapp, используя тот же адрес электронной почты и учетные данные, он может войти в subscriptionapp или ecomapp и наоборот.

Причиной выбора одной и той же таблицы пользователей и другой таблицы для всех приложений является бизнес-перспектива - та же единая система управления продажами и билетами для продаж и команда CDM для отслеживания всего. Devise используется во всех трех приложениях вместе с LDAP, поэтому вход в систему и регистрация работают без проблем.

Проблема:

До сих пор пользователь last_login_at представлял собой один столбец, поэтому мы не можем точно определить, в каком приложении он последний раз входил в систему. Но теперь мы должны начать регистрировать эти детали отдельно, например, когда он последний раз входил в serviceapp, ecomapp, приложение подписки по отдельности.

Также мы начинаем использовать новый crm одного конкретного приложения - subscriptionapp, а для клиентов (пользователей) этого конкретного приложения мы должны хранить дополнительную информацию, такую ​​как unq_id из crm и т. Д.

Моя первоначальная мысль - добавить эти столбцы в саму пользовательскую таблицу. Но в будущем мы можем добавить немного дополнительной информации в таблицу пользователей, которая зависит от приложения. Следовательно, добавление его в основную таблицу пользователей не будет хорошей идеей для этого. Как мне поступить в этом случае? Несмотря на то, что я создал три разные таблицы, такие как subscriptionapp_client, ecomapp_client, serviceapp_client связывал их с пользовательской таблицей, такой как user has_one *** _ client.

Если существует такая связь, как если бы user.subscriptionapp_client.present? он был клиентом этого приложения, и мы можем сохранить последний вход в систему по адресу crm_uniq_id и все в этой таблице.

Есть ли другой хороший подход, который мог бы решить проблему здесь? Я читаю о MTI, но похоже, что это не решит проблему.

1 Ответ

0 голосов
/ 30 апреля 2019

Наследование отдельных таблиц с помощью JSON.

class CreateClientAccount < ActiveRecord::Migration[5.2]
  def change
    create_table :client_accounts do |t|
      t.references :user
      t.string :uid # the unique id on the client application
      t.string :type
      t.integer :sign_in_count
      t.datetime :last_sign_in_at
      t.jsonb :metadata
      t.timestamps
    end
    add_index :client_accounts, [:user_id, :type], unique: true
  end
end

class User
  has_many :client_accounts
  has_one :service_account, class_name: 'ServiceApp::ClientAccount'
  # ...
end

class ClientAccount < ApplicationRecord
  belongs_to :user
  validates_uniqueness_of :user_id, scope: :type
end

module ServiceApp
  class ClientAccount < ::ClientAccount
  end
end

module SubscriptionApp
  class ClientAccount < ::ClientAccount
  end
end

module EcomApp
  class ClientAccount < ::ClientAccount
  end
end

Это позволяет избежать очень непривлекательного дублирования наличия количества таблиц X в схеме для обслуживания, а столбец JSONB по-прежнему дает вам тоннугибкости.Однако во многих отношениях это просто обновление по шаблону EAV .

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

Одна таблица для каждого типа.

class User < ApplicationRecord
  has_one :subscription_account
  has_one :service_account 
  # ...
end

class ClientAccount < ApplicationModel
  self.abstract_class = true 
  belongs_to :user
end

class SubscriptionAccount < ClientAccount
end

class ServiceAccount < ClientAccount
end

# ...

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

Это не так уж и привлекательно, если только требования для каждого типа не отличаются друг от друга.

...