可以在 Sequel ORM 中使用 `one_to_many_through` 关联吗?
Possible to use `one_to_many_through` associations in Sequel ORM?
我有一个案例,其中一个模型与另外两个相关。我正在尝试正确设置这 3 个模型之间的模型关系。
一个简化的例子...前 2 个 table 是 clients
和 invoices
:
db.create_table(:clients) do
primary_key :id
String :name
end
db.create_table(:invoices) do
primary_key :id
String :description
Integer :balance
end
第三个 table,称为 files
,包含与 clients
或 invoices
相关的文件的记录:
db.create_table(:files) do
primary_key :id
String :name
String :path
String :type # [image, pdf, word, excel]
end
有 2 个连接器 table 连接 files
到 clients
和 invoices
:
db.create_table(:clients_files) do
Integer :client_id
Integer :file_id
end
db.create_table(:files_invoices) do
Integer :invoice_id
Integer :file_id
end
问题是,如何正确建立模型中的关系,使得每个client
和invoice
可以有一个或多个相关的files
?
我 可以 使用 many_to_many
和 has_many :through
关联来完成此操作,但是,这似乎不是正确的方法,因为给定的 file
只能属于一个 customer
或 invoice
,不能属于多个
我也可以使用多态来做到这一点,但是 documentation discourages this approach:
Sequel discourages the use of polymorphic associations, which is the
reason they are not supported by default. All polymorphic associations
can be made non-polymorphic by using additional tables and/or columns
instead of having a column containing the associated class name as a
string.
Polymorphic associations break referential integrity and are
significantly more complex than non-polymorphic associations, so their
use is not recommended unless you are stuck with an existing design
that uses them.
更正确的关联应该是 one_to_many_through
或 many_to_one_through
,但我找不到正确的关联方式。是否有普通的 Sequel 方法可以实现此目的,或者是否有提供此功能的模型插件?
对于您当前的模式,您只想对文件使用 many_to_many 关联:
Client.many_to_many :files
Invoice.many_to_many :files
为了确保每个文件只能有一个 client/invoice,您可以将 file_id 设为 clients_files 和 files_invoices 的主键(一个普通的唯一 constraint/index 也可以)。然后你可以使用 one_through_one:
File.one_through_one :client
File.one_through_one :invoice
请注意,这仍然允许将文件关联到客户和发票。如果你想阻止这种情况,你需要改变你的架构。您可以将 client_id 和 invoice_id 外键移动到文件 table (或对两个键使用单个连接 table ),并有一个检查约束只检查其中之一已设置。
请注意,避免多态键(除了复杂性之外)的主要原因是它允许数据库强制执行参照完整性。对于当前的连接 table,您没有创建外键,只是创建了整数字段,因此您没有强制执行参照完整性。
我有一个案例,其中一个模型与另外两个相关。我正在尝试正确设置这 3 个模型之间的模型关系。
一个简化的例子...前 2 个 table 是 clients
和 invoices
:
db.create_table(:clients) do
primary_key :id
String :name
end
db.create_table(:invoices) do
primary_key :id
String :description
Integer :balance
end
第三个 table,称为 files
,包含与 clients
或 invoices
相关的文件的记录:
db.create_table(:files) do
primary_key :id
String :name
String :path
String :type # [image, pdf, word, excel]
end
有 2 个连接器 table 连接 files
到 clients
和 invoices
:
db.create_table(:clients_files) do
Integer :client_id
Integer :file_id
end
db.create_table(:files_invoices) do
Integer :invoice_id
Integer :file_id
end
问题是,如何正确建立模型中的关系,使得每个client
和invoice
可以有一个或多个相关的files
?
我 可以 使用 many_to_many
和 has_many :through
关联来完成此操作,但是,这似乎不是正确的方法,因为给定的 file
只能属于一个 customer
或 invoice
,不能属于多个
我也可以使用多态来做到这一点,但是 documentation discourages this approach:
Sequel discourages the use of polymorphic associations, which is the reason they are not supported by default. All polymorphic associations can be made non-polymorphic by using additional tables and/or columns instead of having a column containing the associated class name as a string.
Polymorphic associations break referential integrity and are significantly more complex than non-polymorphic associations, so their use is not recommended unless you are stuck with an existing design that uses them.
更正确的关联应该是 one_to_many_through
或 many_to_one_through
,但我找不到正确的关联方式。是否有普通的 Sequel 方法可以实现此目的,或者是否有提供此功能的模型插件?
对于您当前的模式,您只想对文件使用 many_to_many 关联:
Client.many_to_many :files
Invoice.many_to_many :files
为了确保每个文件只能有一个 client/invoice,您可以将 file_id 设为 clients_files 和 files_invoices 的主键(一个普通的唯一 constraint/index 也可以)。然后你可以使用 one_through_one:
File.one_through_one :client
File.one_through_one :invoice
请注意,这仍然允许将文件关联到客户和发票。如果你想阻止这种情况,你需要改变你的架构。您可以将 client_id 和 invoice_id 外键移动到文件 table (或对两个键使用单个连接 table ),并有一个检查约束只检查其中之一已设置。
请注意,避免多态键(除了复杂性之外)的主要原因是它允许数据库强制执行参照完整性。对于当前的连接 table,您没有创建外键,只是创建了整数字段,因此您没有强制执行参照完整性。