【问题标题】:Best way to send HTTP on model after_update or after_create在模型 after_update 或 after_create 上发送 HTTP 的最佳方式
【发布时间】:2017-08-31 23:47:12
【问题描述】:

这可能不是最好的问题。但我会尽力解释。 我需要将模型与外部服务同步。

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

我不喜欢在模型内部调用 HTTP,我正在寻找在模型之外实现它的最佳方法。 (PS 我知道我们可以使用带有 base.class_eval 的模块,但它也是最终模型的一部分)

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

【问题讨论】:

  • 您需要事务方法吗?如果更新在第一个系统中有效,但在第二个系统中崩溃(或离线),您是否应该在第一个系统中应用更新?另外,您需要在第二个系统中立即更新吗?考虑一次更新 10k 个模型和 10k 个请求。
  • 也许尝试在模型回调中推送ActiveJob.perform_later,让 Job 处理 HTTP?

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


【解决方案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

【讨论】:

  • 嘿,谢谢。你和其他人是绝对正确的。您的方法适用于我们只有一个创建入口点的情况。问题是系统有很多入口点,可以通过不同的方式创建或更新模型,避免代码重复会很好。
  • @VolodymyrO 我在示例中添加了一些更新逻辑。如果更新非常不同,您也可以将一个块传递给该方法并使用yield self 来获取保存结果。
  • model = Model.create(args) 永远不会伪造。即使验证失败,create 也会返回无效模型。
  • 我要反对@Fede,并说回调已经存在(在框架中)并且比自定义服务基础架构更容易为新手掌握。只要您不滥用回调,它们也是有效的解决方案。也就是说,ActiveJob 或任何其他异步作业/工作者的方式是可行的,因为外部 HTTP 请求会太慢。
  • @Leito 哈哈。确实如此。我有一段时间没有在 Rails 中编程了。使用 create 并检查是否为 persisted? 将起作用。我宁愿使用服务将逻辑与模型本身分离,因为它是一个外部服务,知道如何发出 http 请求不应该是模型的责任
【解决方案2】:

你的心是正确的地方,确保你把代码放在它所属的地方。我建议不要将自定义服务保留为回调,而是将大部分代码移动到它自己的活动作业中(这样你就可以异步运行它)。在我看来,模型负责持久性,因此它是在模型更改时“标记”并让其他人去做同步工作的最佳场所。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-11-17
    • 2013-06-01
    • 2021-03-04
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-09
    • 2021-04-22
    相关资源
    最近更新 更多