可以在 Sequel ORM 中使用 `one_to_many_through` 关联吗?

Possible to use `one_to_many_through` associations in Sequel ORM?

我有一个案例,其中一个模型与另外两个相关。我正在尝试正确设置这 3 个模型之间的模型关系。

一个简化的例子...前 2 个 table 是 clientsinvoices:

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,包含与 clientsinvoices 相关的文件的记录:

db.create_table(:files) do
    primary_key :id
    String :name
    String :path
    String :type # [image, pdf, word, excel]
end

有 2 个连接器 table 连接 filesclientsinvoices:

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

问题是,如何正确建立模型中的关系,使得每个clientinvoice可以有一个或多个相关的files

可以 使用 many_to_manyhas_many :through 关联来完成此操作,但是,这似乎不是正确的方法,因为给定的 file 只能属于一个 customerinvoice,不能属于多个

我也可以使用多态来做到这一点,但是 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_throughmany_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,您没有创建外键,只是创建了整数字段,因此您没有强制执行参照完整性。