让我们假设我们有一个产品集合,每个产品都有自己的具体说明,比如价格.

我们想开具包含上述产品的发票.使用从InvoiceProduct通过:has_many的直接关联是行不通的,因为产品可能会改变,而发票必须是不变的,从而导致发票价格、概念等的改变.

我首先想到的是有一个像InvoiceProduct这样的中间型号,它将与Invoice相关联,并从Product创建.每个InvoiceProduct对于其父发票来说都是唯一的,并且是不变的.这个选项会随着更多发票的开具而显著增加数据库的大小,所以我认为这不是一个好的选项.

我现在正在考虑向发票模型添加一个序列化字段,其中包含与其关联的所有产品信息,即发票包含的项目集合的散列.这样,即使产品在future 被修改,我们也可以以不变的方式拥有它们.

不过,我不确定这种方法可能存在的中期或长期负面影响.很想听听你对此的看法.

此外,如果有一些我可能忽略的更明显的方法,我也很想听听.

干杯

推荐答案

不是的.

序列化的列在现代应用程序中没有立足之地.它们是在本机JSON/JSONB列广泛使用之前的一种过度使用的肮脏黑客,只有一些缺点.该规则的唯一例外是使用应用程序端加密时.

JSON/JSONB列可以用于有限数量的任务,在这些任务中,数据不能由固定的模式定义,或者如果您只是存储原始的JSON响应--但它不应该是您定义模式的方式,因为you're just shooting yourself in the foot.是用于特殊作业(job)的特殊工具.

更好的替代方法是实际使用良好的关系数据库设计,并将销售时的价格和其他所有信息存储在单独的表中:

class Order < ApplicationRecord
  has_many :line_items
end
# rails g model line_item order:belongs_to product:belongs_to units:decimal unit_price:decimal subtotal:decimal
# The line item model is responsible for each item of an order 
# and records the price at the time of order and any discounts applied to that line
class LineItem < ApplicationRecord
  belongs_to :order
  belongs_to :product
end
class Product < ApplicationRecord
  has_many :line_items
end 

序列化的列无论如何都不是一成不变的--它实际上更容易被反规范化和损坏,因为没有数据库端约束来确保它的正确性.

实际上,通过使用触发器,许多数据库中的表都是不可变的.

优点:

  • 不违反1NF.
  • 要使用的规范化固定数据模式-约束可确保数据在数据库级别上的有效性.
  • 连接是一种非常强大的工具,并不像您想象的那样昂贵.
  • 如果需要,您可以在应用程序外部实际访问和理解数据.
  • DECIMAL数据类型.JSON/JSONB只有一个使用IEEE 754浮点的数字类型.
  • 您拥有了一个实际的模型和关联,而不必处理原始的散列.
  • 您可以在正常的查询中查询数据.
  • 您可以在数据库级别生成聚合,并使用实例化视图等工具.

Ruby-on-rails相关问答推荐

使用Hotwire/Turbo的Rails在链接悬停时获取请求

确定当前太平洋时区是PST还是PDT

用变量替换 find_or_create_by 中的键

使用带有 Paper Trail gem 的子类

Rails 模型.有效吗?刷新自定义错误并错误地返回 true

如何在我的 rails 应用程序中测试 ActiveRecord::RecordNotFound?

上传图片 Ruby on Rails

FactoryGirl + Faker - 为数据库种子数据中的每个对象生成相同的数据

Rails 成语避免在 has_many 中重复:通过

如何让 ActiveAdmin 使用强参数?

Rails 3 SSL 路由从 https 重定向到 http

为什么 Ruby on Rails 使用 http://0.0.0.0:3000 而不是 http://localhost:3000?

Rspec - Rails - 如何遵循重定向

为什么 RSpec 在 Rails 下这么慢?

停止 Rails 为视图和助手生成规范测试?

# 轨道中的 TODO

用于在多行上链接调用的 Ruby 约定

扩展 Devise SessionsController 以使用 JSON 进行身份验证

列出关联模型的名称

Rails:弃用警告:您没有设置 config.secret_key_base