【问题标题】:How to convert this ActiveRecord::Observer to a Service object?如何将此 ActiveRecord::Observer 转换为 Service 对象?
【发布时间】:2012-11-21 11:31:09
【问题描述】:

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

PushService 通过 WebSocket 更新所有连接的浏览器的所有更改。它通过 POST 到外部进程来做到这一点。自从从Thread.new 迁移到 Sidekiq 后,观察者就崩溃了。在 :after_create 中启动的 Sidekiq 作业可以在事务实际提交之前运行,因此会引发 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

【问题讨论】:

  • 您好!你找到解决问题的方法了吗?我们遇到了同样的问题,不知道该怎么办

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


【解决方案1】:

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

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

所以每当 PushService 做一些需要更新连接的浏览器的事情时

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

那么Service对象就可以通过subscribe方法监听这个事件了。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-27
    • 2021-01-28
    • 2018-10-29
    • 1970-01-01
    相关资源
    最近更新 更多