需要 return 对象的 :name,即使它被软删除(使用偏执狂)

Need to return the :name of an object, even if it was soft deleted (using paranoia)

我在系统中有 Users 可以 soft_deleted 使用 paranoia (2.0.2)TimeRecords 跟踪有多少 :hours 一个 user 完成了给定的作业,以及整个作业的总 :cost 是多少(:cost = :rate * :hours 以保持简单)。

这些记录会持续存在,因此即使将来 user 的费率发生变化,您仍然可以准确了解他们过去对给定任务收取的费用。 输入软删除。可以使用软删除(设置 deleted_at: Time.now)从系统中删除 user,但我需要他们的名字仍然显示链接到他们过去收费的:hours:cost。我有一个可行的解决方案,但对我来说感觉太老套了,而且我一直无法找到更优雅的解决方案。我很感激任何 suggestions/help 人可能必须以 正确的方式 而不是简单的方式来做到这一点。

当前解决方案:

class TimeRecord < ActiveRecord::Base
  belongs_to :user

  delegate :name, to: :user, prefix: true, allow_nil: true

  def name
    user_name || "#{User.with_deleted.find(user_id).name}" rescue 'n/a'
  end
end

如果您的 TimeRecord 需要名称,无论 User 是否仍然存在,那么我建议将 user_name 存储在 TimeRecord 和 User 上而不是委托它。

当用户的名字发生变化时,我会相应地更新相关的TimeRecords。

最好假装软删除记录被真正删除以保持参照完整性。由于您已经说过 TimeRecord 保留了当时用户的 "Snapshot" ,因此解决方案应该很清楚:将 name 添加到您存储在 TimeRecord 中的字段作为快照.

即使不允许用户更改其名称,这也是这种反规范化的完美用例。

如果您想包含关联的软删除对象,您可以像这样简单地取消关联范围:

class TimeRecord < ActiveRecord::Base
  belongs_to :user, -> { with_deleted } # associate soft-deleted user
  delegate :name, to: :user, prefix: true, allow_nil: true
end