在模型after_update或after_create上发送HTTP的最佳方法

时间:2017-08-30 07:48:17

标签: ruby-on-rails ruby-on-rails-5

可能不是最好的问题。但我会尝试解释。 我需要将Model与外部服务同步。

因此,有许多可以更新或创建模型的入口点。 所以我需要监听after_update和after_create事件。

我不喜欢在模型中调用HTTP,而且我正在寻找从模型中完成它的最佳方法。 (PS我知道我们可以使用带有base.class_eval的模块,但是它也是最终模型的一部分)

我找到了实施的https://github.com/krisleech/wisper库 发布者/订阅者方法。 这是最好的方式吗?

2 个答案:

答案 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建议的这个或服务。