列出所有 paper_trail 版本(包括关联)的正确方法是什么?

Tom*_*Tom 5 ruby-on-rails paper-trail-gem

关于paper_trail gem 的问题

当仅关联更改时,不会为主模型创建版本记录。那么列出特定记录的所有版本(包括其关联)的正确方法是什么?

我应该查询这样的东西吗?(不好的一点是这个 SQL 查询可能很长而且性能很低。)

f = "(item_type = 'Place' AND item_id = ?) OR (item_type = 'PlaceName' AND item_id IN (?))"
PaperTrail::Version.where(f, @place.id, @place.names.map { |n| n.id }) 
Run Code Online (Sandbox Code Playgroud)

还是应该在仅关联更改时创建版本记录?我认为@DavidHam 尝试了同样的事情并提出了类似的问题,但还没有人回答。

小智 3

因此,我找到了一种方法来做到这一点,但它并不完全漂亮,并且每次更改关联时它都不会创建新版本。但是,它确实为您提供了一种按时间顺序检索版本的有效方法,以便您可以查看关联更改之前/之后版本的外观。

首先,我检索给定该模型 id 的关联版本的所有 id:

def associations_version_ids(item_id=nil)
  if !item_id.nil?
    ids = PaperTrail::VersionAssociation.where(foreign_key_id: item_id, foreign_key_name: 'item_id').select(:version_id)

    return ids
  else
    ids = PaperTrail::VersionAssociation.where(foreign_key_name: 'item_id').select(:version_id)

    return ids
  end
end
Run Code Online (Sandbox Code Playgroud)

然后我使用此函数中的 VersionAssociation id 将所有版本放在一起。它将返回 PaperTrail::Version 的按时间顺序排列的数组。因此,这些信息对于活动日志等很有用。通过这种方式将版本及其关联拼凑起来非常简单:

def all_versions
  if !@item_id.nil?
    association_version_ids = associations_version_ids(@item_id)
    all_versions = PaperTrail::Version
                      .where("(item_type = ? AND item_id = ?) OR id IN (?)", 'Item', @item_id, association_version_ids)
                      .where("object_changes IS NOT NULL")
                      .order(created_at: :desc)

    return all_versions
  else
    assocation_ids = associations_version_ids
    all_versions = PaperTrail::Version
                      .where("item_type = ? OR id IN (?)", 'Item', association_ids)
                      .where("object_changes IS NOT NULL")
                      .order(created_at: :desc)

    return all_versions
  end
end
Run Code Online (Sandbox Code Playgroud)

再说一遍,这不是一个完美的答案,因为每次更改时都不会出现新版本,但它是可以管理的。