可能不是最好的问题。但我会尝试解释。 我需要将Model与外部服务同步。
因此,有许多可以更新或创建模型的入口点。 所以我需要监听after_update和after_create事件。
我不喜欢在模型中调用HTTP,而且我正在寻找从模型中完成它的最佳方法。 (PS我知道我们可以使用带有base.class_eval的模块,但是它也是最终模型的一部分)
我找到了实施的https://github.com/krisleech/wisper库 发布者/订阅者方法。 这是最好的方式吗?
答案 0 :(得分:1)
使用ActiveRecord的回调是一种非常肮脏的方式。
您应该将模型的创建/更新包装在服务中,以避免代码重复并封装此逻辑。
此外,使用活动作业执行异步HTTP请求将是一个好主意。
class MyService
def create(args)
model = Model.create(args)
ActiveJob.perform_later(model) if model.persisted?
model
end
def update(model, args)
result = model.update_attributes(args)
ActiveJob.perform_later(model) if result
result
end
end
答案 1 :(得分:0)
你的心是正确的地方,确保你保留代码所属的地方。我建议不要使用自定义服务作为回调,而是将大部分代码移动到它自己的Active Job(这样你就可以异步运行它)。我看待它的方式,模型负责持久性,因此它是#34; flag"当模型被更改并让别人去做同步工作时。
class Foo < ActiveRecord::Base
after_commit :create_external, on: :create
private
def create_external
CreateExternalFooJob.perform_later self
end
end
class CreateExternalFooJob < ApplicationJob
queue_as :default
def perform(foo)
# Create object in external service with HTTP
end
end
after_commit
也可以在:update
和:destroy
上触发,以便您保持外部服务同步。
Rails有办法将回调移动到它自己的类,它被称为Observers并且它在4.0之后被移动到它自己的gem。如果你使用了太多的回调,请考虑@Fede建议的这个或服务。