6

我有一个 Audit 类,用于通过属性存储操作。

class Audit < ActiveRecord::Base
  attr_accessible :activity
  belongs_to :by, :polymorphic => true
  belongs_to :on, :polymorphic => true
  attr_accessible :by, :on
end

:by 和 :on 的多态关联用于存储应审计的任何类型的对象。主要是因为多态在模式中被分解为类型和 id,因此应该能够存储我所有的模型对象。

  create_table "audits", :force => true do |t|
    t.string   "activity"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
    t.integer  "on_id"
    t.string   "on_type"
    t.integer  "by_id"
    t.string   "by_type"
  end

我遇到的问题来自所有被审计的对象也都在使用 paranoia gem。paranoia gem 在每个模型表中引入了一个 deleted_at 列,该列通过其 default_scope 来检查该模型上的每个查询,default_scope 设置为“where(deleted_at is null)”。paranoia gem 还提供了一个 .with_deleted 方法,它允许通过打开 default_scope 进行直接查询,结果还返回已被偏执/软删除的对象。

但是,如果我有任何已删除的项目,我会尝试使用列出的所有已审核项目。

Audit.all

我不知道如何告诉 Rails 为每个添加 .with_deleted 调用的多态 :by 和 :on 对象运行查找查询。我的猜测是,rails 通过以下方式查找多态关系的对象

eval(type).find(id)

在我的情况下,这会给我应用了偏执狂宝石的 default_scope 的对象。

我试图在 Audit 中覆盖 self.find_by_sql 但没有运气。我陷入了一些 Arel 方法中,我需要进一步阅读这些方法才能继续前进。

我看到了以下解决方案,但我不知道该怎么做。

  1. 覆盖多态查找。如何?
  2. 在评估之前将原始 SQL 作为字符串获取,并 sub/gsub Where deleted_at is null 部分。

任何和所有关于如何解决这个问题的建议都将不胜感激。

4

1 回答 1

6

试试这个:

def on!
  if on_type && on_id
    on_type.constantize.with_deleted.find(on_id)
  end
end

如果记录已被真正删除,这将引发 ActiveRecord::RecordNotFound 错误,否则将返回“on”对象,即使它被标记为已删除。

于 2014-03-20T23:05:16.747 回答