How to convert this ActiveRecord::Observer to a Service object?
How would one convert the following ActiveRecord::Observer to a Service object (or maybe multiple objects)?
The PushService
updates all connected browsers via WebSocket of all changes. It does this by POST-ing to an external process. Since migrating from Thread.new
to Sidekiq, the observer broke. A Sidekiq job started in an :after_create can run before the transaction is actually committed, so it will raise an ActiveRecord::NotFound error.
It is recommended to use an :after_commit hook, but then information needed by the PushService
such as record.changes
will not be available.
The interesting use case that this observer fulfills is that when a new message is created, which is a reply to another message. It will automatically run two callbacks. An :after_create for the reply-message and an :after_touch for the thread-message.
I am interested to see how this behavior can be run by using an explicit service object.
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
You can set up subscribers and listeners using a gem called wisper.
So in your PushService class, you would include Wisper::Publisher
There is an exact example on the Github page for using this as a service. This way, the firing off of events will be taken care of the actual objects.
So whenever PushService does something that requires updating connected browsers
def some_action
#some code
publish(:done_something, self)
end
Then the Service object can be listening for this event with the subscribe
method.
上一篇: 你可以手动管理事务提交/回滚吗?