如何将这个ActiveRecord :: Observer转换为Service对象?

时间:2012-11-21 11:31:10

标签: ruby-on-rails ruby activerecord observers sidekiq

如何将以下ActiveRecord :: Observer转换为Service对象(或多个对象)?

PushService通过WebSocket更新所有连接的浏览器的所有更改。它通过POST到外部进程来完成此操作。自从Thread.new迁移到Sidekiq后,观察员破了。 Sidekiq作业开始于:after_create可以在事务实际提交之前运行,因此它将引发ActiveRecord :: NotFound错误。

建议使用:after_commit钩子,但PushService所需的信息(例如record.changes)将无法使用。

此观察者实现的有趣用例是,当创建新消息时,这是对另一消息的回复。它会自动运行两个回调。答:after_create表示回复消息,并且:after_touch表示线程消息。

我很想知道如何使用显式服务对象来运行此行为。

class PushObserver < ActiveRecord::Observer
    observe :message

  def after_create(record)
    Rails.logger.info "[Observe] create #{record.inspect}"
    PushService.new(:create, record).publish
  end

  def after_update(record)
    Rails.logger.info "[Observe] update #{record.changed.inspect}"
    PushService.new(:update, record).publish
  end

  def after_touch(record)
    Rails.logger.info "[Observe] touched #{record.changes.inspect}"
    PushService.new(:touch, record).publish
  end

  def after_destroy(record)
    Rails.logger.info "[Observe] destroy #{record.inspect}"
    PushService.new(:destroy, record).publish
  end
end

1 个答案:

答案 0 :(得分:1)

您可以使用名为wisper的宝石设置订阅者和侦听器。

因此,在您的PushService类中,您将包含Wisper::Publisher Github页面上有一个确切的示例,可以将其用作服务。这样,事件的发射将被处理实际对象。

因此,每当PushService执行需要更新已连接浏览器的内容时​​

def some_action
  #some code
  publish(:done_something, self)
end

然后,Service对象可以使用subscribe方法监听此事件。