0

我正在处理这个要求:我有一个很大的对象关系模型,其中实体之间的联系非常紧密。让我们以这种关系为例:一栋建筑有很多公寓,一个公寓有很多分区。现在,我想要的是:当任何部门发生变化时,我想“通知”建筑物,或者更好地标记建筑物已被“更新”或“修改”。

  • 当前解决方案:我们有一个自己编写的实现,我们将在其中将分区标记为“影响”建筑物,并且每次更新分区时都会更新建筑物的“修改”时间戳。

  • 期望的解决方案:一个已经存在的“开箱即用”的实现(一个gem,一个插件,也许是上帝),这将使我们免于重构我们的实现的工作。

  • 不需要的解决方案:请不要告诉我用 :autosave => true 标记所有这些关联。我想要一个可排队的解决方案。

当然,也欢迎不包含所需解决方案但建议改进当前解决方案性能的解决方案。在缺乏理想的解决方案的情况下,我们肯定会改进现有的解决方案。

一个小编辑:

这种行为必须是通用的。它不仅适用于建筑案例,任何具有关联的模型都可以具有这种行为。这将始终是相同的:获取受影响的关联并更新它们。现在,我不想用相同的例程编写不同的观察者。

关于性能问题:更新受影响的关联更新也必须触发其受影响的关联。现在,让我们假设 1 个建筑物影响 100 个分区,每个分区影响 100 个椅子。现在,观察者解决方案仅适用于业务级别。也就是说,我必须实例化每个 AR 实例,以便观察者可以采取行动。我认为这是糟糕的表现。如果 A 影响 100 个 B,我用一个 DB 语句来做。但是,当我使用 SQL 完成所有操作时,如何触发这 100 个观察者呢?

所以,回到主要的更新点:这种行为是通用的,最重要的是,性能必须是顶级的(例如,关联可能会触发 has_many 关联的 nxn 更新)。

4

2 回答 2

3

您可以使用observer. 创建名称为audit_observer.rb的文件app/models

class AuditObserver < ActiveRecord::Observer
  observe :division

  def after_update(division)
    division.logger.info('Division is updated at #{division.updated_at}')
    ######Your logic goes here 
  end
end
于 2012-10-23T15:07:44.247 回答
0

所以,我解决它的方法是混合了关于观察者设计模式实现的各种建议。因此,首先,该模式的基本实现都不适合我。为什么?我想要一个模型 A 观察其关系 B 的概念,B 被其关系 A 观察,并且这个观察的例程在其他地方定义,在一个(让我们称之为)通知程序中。

为什么我不能使用 Ruby 'observer' 库?理论上我可以做到这一点,但是被观察的对象调用一个名为“changed”的方法来通知它的观察者,而“changed”是一个被 ActiveRecord 覆盖的方法,即被“dirty”库覆盖。

为什么我不能使用 AR“观察者”?因为这里的观察者就是我想要的通知者。该例程未在模型中实现,但我不能说必须通知哪些其他 AR 模型。这是一个障碍。

我是怎么解决的?我自己创建了一个库,使用 ActiveModel::Observing 库,它允许我实现我想要的功能。我设计我会有这个 DSL:

类 A < ActiveRecord has_one :b

 observes :b, :on => :create, :notifiers => :update_observer

结尾

所以这意味着,当 b 被创建时,有一个通知器 update_observer 可以到达 b 和 a 并对其进行处理。所以,在这种情况下:

class UpdateObserverNotifier < Notifier

  def action(observable, observer)
    observer.update_attributes(updated_at: observable.updated_at)
  end
end

对观察者的 DSL 调用将在各自的类中注入“观察者”和“可观察”行为。Notifier 基类将具有通知行为,并且它可以访问可观察对象和观察者对象,以防可观察对象中的某些内容必须在观察者中镜像。如果你的动作触发了观察者的回调,它也会通知观察者本身的潜在观察者。

是的,就是这样。感谢您的建议,否则我不会实现它。

于 2012-11-16T16:02:06.117 回答