ruby-on-rails - Ruby On Rails - 用于保存 CRUD 操作参数/有效负载的数据库结构
问题描述
我想要的是
我想制作一个表格以将“CRUD 操作信息本身”保存在我的数据库中。
eg)
①<code>新建行{"name": "Tom", "price": 200}
②<code>查找一行 WHERE {"age": 30}
③<code>删除行 WHERE {"name" : "John"}
④<code>更新行 WHERE {"name": "Ted"} SET {"price": 300}
我的想法
为了实现上述目标,我创建了两个模型。
①CrudOperation
t.string :crud_type # this should be one of CRUD ("create", "read", "update", "delete")
t.string :target_database
②CrudOperationParameter
t.integer :crud_operation_id # reference
t.string :key
t.value :value
CrudOperation 有很多 CrudOperationParameter-s。
问题
我的模型似乎运行良好,除了 crud_type 是“更新”。
像那样
①新建行{"name": "Tom", "price": 200}
**CrudOperation**
id: 1
crud_type: "create"
target_database: "XXXX"
**CrudOperationParameter**
crud_operation_id: 1
key: "name"
value "Tom"
**Another CrudOperationParameter**
crud_operation_id: 1
key: "price"
value "200"
但是当涉及到用更新类型注册 CrudOperation 时,就会出现问题。
④更新行 WHERE {"name": "Ted"} SET {"price": 300}
**CrudOperation**
id: 1
crud_type: "update"
target_database: "XXXX"
**CrudOperationParameter**
crud_operation_id: 1
key: "name"
value "Ted"
**Another CrudOperationParameter**
crud_operation_id: 1
key: "price"
value "300"
由于 CrudOperationParameter 只有键值列,我无法确定该 CrudOperationParameter 是用于 UPDATE 语句中的 WHERE 子句还是 SET 子句。
你能教我更好的数据库模式来保存这些数据吗?
解决方案
你所拥有的基本上是实体属性值模式的半生不熟版本(或反模式,取决于你问的是谁)。
如果我真的必须这样做,我会将其设置为:
class CrudOperation < ApplicationRecord
has_many :crud_operation_parameters
accepts_nested_attributes_for :crud_operation_parameters
enum crud_type: {
create: "create",
read: "read",
update: "update",
delete: "delete"
}
# Convenience setter that maps a hash of attributes
# into a an array of key value attibutes suitible for `accepts_nested_attributes_for`
# and sets the nested attributes
# @return [Array]
def parameters=(hash)
self.crud_operation_parameters_attributes = hash.map do |key, value|
{
key: key,
value: value
}
end
end
end
class CrudOperationParameter < ApplicationRecord
belongs_to :crud_operation
end
# 1. create new row {"name": "Tom", "price": 200}
CrudOperation.create!(
crud_type: :create,
parameters: {
name: "Tom",
price: 200
}
)
# 1. create new row {"name": "Tom", "price": 200}
CrudOperation.create!(
crud_type: :update,
parameters: {
name: "Tom",
price: 200
}
)
我提到这是一个半生不熟的尝试,因为您缺少 Attribute 表,您可以在其中规范化属性的定义并存储诸如类型信息之类的东西。相反,您的解决方案有一个字符串列,其中包含大量可以非规范化的重复项。
但是现代 RDBMS 系统具有诸如 JSON、JSONB 和 HSTORE 之类的列类型,它们可以用来代替 EAV 来存储不适合给定模式的数据。
与 EAV 不同,您不必将所有属性存储在单个列类型(通常是字符串)中并进行类型转换或创建一组属性表来存储不同类型的属性(例如 StringCrudOperationParameter 和 FloatCrudOperationParameter)。
在 Postgres 上使用 JSONB,我会将其设置为:
# rails g model crud_operation crud_type:string payload:jsonb conditions:jsonb
class CrudOperation < ApplicationRecord
enum crud_type: {
create: "create",
read: "read",
update: "update",
delete: "delete"
}
end
# 1. create new row {"name": "Tom", "price": 200}
CrudOperation.create!(
crud_type: :create,
payload: {
name: "Tom",
price: 200
}
)
# 2. find a row WHERE {"age": 30}
CrudOperation.create!(
crud_type: :read,
conditions: {
age: 30
}
)
# 3. delete row WHERE {"name": "John"}
CrudOperation.create!(
crud_type: :delete,
conditions: {
name: "John"
}
)
# 4. update the row WHERE {"name": "Ted"} SET {"price": 300}
CrudOperation.create!(
crud_type: :update,
conditions: {
name: "John"
},
payload: {
price: 300
}
)