【问题标题】:PaperTrial versions handling changeset errorPaperTrial 版本处理变更集错误
【发布时间】:2024-01-07 18:41:01
【问题描述】:

这是我的模型的样子,所以我可以正确解决我的问题

class Product

  has_paper_trail
  
  belongs_to :category

end

在我的 HTML 方面,我需要使用 PaperTrial 版本加载所有日志。像这样

@product.versions.each |version|
 version.changeset.each do |k, v|
   - if k.to_s == "category_id"
    - old_record = v[0].blank? ? " No Record " : Category.find(v[0].to_i).name
    - new_record = v[1].blank? ? " No Record " : Category.find(v[1].to_i).name
    = "Category" + " From: " + "#{old_record} " + " To: " + "#{new_record}"
 

在我的 HTML 中看起来不错,但是。有一个场景。该类别将被删除。我会在这个视图中得到一个错误。因为我的“Category.find”。 find 方法找不到已删除的 Category。

有没有办法存储类别名称而不是 ID。所以我可以摆脱使用“查找”

或者有更好的方法来实现这些东西?

【问题讨论】:

  • 如果您想保留已删除类别数据的历史记录(例如类别名称),那么您也应该软删除类别。如果products 表只存储category_id,而不是category_name,那么您就没有记录该数据。
  • 当然,另一种选择是对数据库进行非规范化 - 所以categories.name 也存储在products.category_name 中。但这并不理想,因为现在您需要复制信息并担心诸如“如果类别更改名称怎么办,那么我需要在其他地方更新所有这些重复的数据字段”。
  • 我的意思是您可以两个数据库列:products.category_id products.category_name。这意味着名称将被存储在不同的地方,而不是一个地方。从好的方面来说,这是一种存储产品历史记录的简单方法,但在不利方面,您会复制数据 - 并且存在两个表之间的值不同步的风险。
  • 或者... 就像我说的,你需要软删除categoriesproducts。这样您仍然可以检索已删除的类别数据,例如名称。
  • @DeezNuuts 当通过 Active Record(Ruby on Rails 打包的默认 ORM 库)删除记录时,不是实际从数据库中删除记录,而是使用删除时间填充 deleted_at 列

标签: ruby-on-rails ruby ruby-on-rails-5 ruby-on-rails-6 paper-trail-gem


【解决方案1】:

我建议将category_name 属性添加到您的产品模型以进行缓存。

# migration
rails g migration AddCategoryNameToProducts category_name

# Product model
  before_validation :cache_category_name
  def cache_category_name
    self.category_name = category&.name if category_name != category&.name
  end

但如果您已经投入生产,您必须先填写数据。而且你不能填写数据,已经被删除了。

# console or migration
Category.find_each(&:save!)

这个场景保留了被删除的类别名称,另外它会比很多Category.find高效得多。

或者您可以按照其他人的建议进行某种软删除。

【讨论】:

  • 感谢您的解释。这启发了我。但我刚刚开始使用我的产品模型。其他协会怎么样。像has_many。我会那样做吗????
  • 这是一种可能性。它对一些参数有好处。但是,如果项目让您倾向于其中的很多内容,那么创建软删除解决方案可能会更容易、更好。因此,您只需将模型标记为已删除,但它仍然存在于您的数据库中。它可能需要对您的代码库进行更多更改,甚至可能需要一个新的 gem。这是一个相当复杂的话题。我将从这里开始:github.com/westonganger/paper_trail-association_tracking
  • 谢谢兄弟,我稍后会回到您的代码并阅读所有文档。生病需要休息。这个项目给了我新冠