假设我们有3个不同的应用程序-serviceapp,subscriptionapp,ecomapp,所有应用程序都是用ruby编写的,并且在后端使用相同的数据库,在后端使用表。因此,这三个应用程序的用户表都相同。如果用户是使用相同电子邮件和凭据的serviceapp的一部分,则可以登录subscriptionapp或ecomapp,反之亦然。
为所有应用程序选择相同的用户表和其他表的原因是出于商业角度考虑-销售和cdm团队使用相同的单个crm和票务系统来跟踪所有内容。 Devise与LDAP一起在所有三个应用程序中使用,因此登录和注册工作正常,没有任何问题。
问题:
到目前为止,用户的last_login_at仅是一列,因此我们真的无法确定他上次登录哪个应用程序。但现在我们必须开始分别记录这些详细信息,例如他上次分别登录serviceapp,ecomapp和subscription应用程序的时间。
我们也开始使用一个特定应用程序的新crm-subscriptionapp,对于该特定应用程序的客户(用户),我们必须存储其他信息,例如来自crm的unq_id等。
我的最初想法是在用户表本身中添加这些列。但是将来我们可能会在用户表中添加一些特定于应用程序的额外信息。因此,将其添加到主用户表将不是一个好主意。在这种情况下我应该如何进行?我虽然创建了三个不同的表(例如subscriptionapp_client,ecomapp_client,serviceapp_client),但将它们与用户表(如用户has_one *** _ client)相关联。
如果存在关联,例如user.subscriptionapp_client.present?
他是该应用程序的客户端,则我们可以将最后一次登录存储在crm_uniq_id中,并将其存储在该表本身中。
还有其他合适的方法可以解决这里的问题吗?我正在阅读有关MTI的信息,但看起来它不能解决问题。
答案 0 :(得分:0)
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 pattern的升级。
它与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次连接。
除非每种类型的要求完全不同,否则这并不是很吸引人。