【问题标题】:Paper Trail: create a version on parent whenever associated model changes?Paper Trail:每当关联模型更改时在父级上创建一个版本?
【发布时间】:2016-01-07 16:59:48
【问题描述】:

我正在开发一个 Rails 应用程序,我需要在 Record 上显示审计跟踪,该记录有_many Data。我的 Record 上有 paper_trail 和相关的 Datum 模型,它可以很好地保存它们的版本。

但是,我需要的是 一个 版本的记录,以便在 一个或多个 相关数据发生更改时创建。目前,它会在每个发生变化的 Datum 上创建版本,但如果 R​​ecord 的属性发生变化,它只会创建 Record 的版本;当关联的数据发生变化时,它不会这样做。

我尝试将 touch_with_version 放入 Record 的 after_touch 回调中,如下所示:

class Record < ActiveRecord::Base
  has_many :data

  has_paper_trail

  after_touch do |record|
    puts 'touched record'
    record.touch_with_version
  end

end

class Datum < ActiveRecord::Base
  belongs_to :record, :touch => true

  has_paper_trail

end

after_touch 回调触发,但不幸的是它为每个 Datum 创建了一个新版本,因此当创建一个 Record 时,它已经有大约 10 个版本,每个 Datum 一个。

有没有办法在回调中判断是否创建了一个版本,所以我不创建多个版本?比如签入一个 Record 回调,如果 Datum 已经触发了一个版本,就不要再做了吗?

谢谢!

【问题讨论】:

  • 我认为after_touch 是个好主意,但要防止Record 的重复版本可能会很棘手。相反,如何开始一个事务,更新你的Data,更新你的Record,然后提交事务。如果所有更新都发生在同一个事务中,你会得到什么结果?
  • 一个事务听起来像我想要的,但我不必创建一个事务,我想我只是免费得到它,因为所有Databelong_toRecord,所以所有这些保存只发生在Record 的创建/更新过程中。另一个问题 - 如果多个 Data 会在 Record 上创建多个版本,我想我需要保留 last 版本,而不是第一个版本,如果我希望 Record 与其数据同步.感谢您的建议——我还是 Rails 的新手,我不确定我是否还在考虑 Rails。正在努力!
  • @JaredBeck,我该如何设置该交易?由于 Rails 关联,Record 的数据属性已经在事务中(我认为?)。我是否应该关闭 paper_trail 回调,例如:has_paper_trail on: [],然后使用 ``` Record.transaction do record.update record.touch_with_version end ``` 创建我自己的 after_createafter_update 回调
  • 有关 ActiveRecord 中事务的文档,您可以从这里开始:guides.rubyonrails.org/…
  • 如果您是 Rails 新手,我不建议您使用 PaperTrail 的关联功能,因为它是实验性的并且有一些已知问题。

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


【解决方案1】:

这对我有用。

class Place < ActiveRecord::Base
  has_paper_trail
  before_update :check_update

  def check_update
    return if changed_notably?

    tracking_has_many_associations = [ ... ]
    tracking_has_has_one_associations = [ ... ]

    tracking_has_many_associations.each do |a|
      send(a).each do |r|
        if r.send(:changed_notably?) || r.marked_for_destruction?
          self.touch
          return
        end
      end
    end
    tracking_has_one_associations.each do |a|
      r = send(a)
      if r.send(:changed_notably?) || r.marked_for_destruction?
        self.touch
        return
      end
    end
  end
end

【讨论】:

  • 您可能需要在调用前加上 :changed_notably?首先调用 paper_trail 。例如而不是changed_notably? =&gt; paper_trail.changed_notably?`
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 2010-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多