2017-08-30 68 views
0

可能不是最好的問題。但我會盡力解釋。 我需要將Model與外部服務進行同步。在模型after_update或after_create上發送HTTP的最佳方法

因此,可以更新或創建模型的入口點很多。 所以我需要聽after_update和after_create事件。

我不喜歡在模型中調用HTTP,我正在尋找最好的方法來完成模型。 (PS我知道我們可以使用base.class_eval模塊,但在和它也是最終模型的一部分)

我發現https://github.com/krisleech/wisper庫實現 發佈者/訂戶的方法。 這是做這件事的最好方法嗎?

+0

你需要交易方法嗎?如果更新在第一個系統中有效,但在第二個系統中崩潰(或脫機),是否應該在第一個系統中應用更新?另外,你需要在第二個系統中立即更新嗎?考慮一次更新10k模型,以及10k個請求。 –

+0

也許嘗試在你的模型回調中推送一個'ActiveJob.perform_later',並讓Job處理HTTP? –

回答

0

使用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 
+0

嘿,謝謝。 你和其他人絕對是對的。 當我們只有一個創建入口時,您的方法正在運行。 問題是,系統有很多入口點,可以用不同的方式創建或更新模型,避免代碼重複會很好。 –

+0

@VolodymyrO我在示例中添加了一些更新邏輯。如果更新非常不同,您還可以將方塊傳遞給方法,並使用'yield self'來獲得保存結果。 –

+0

'model = Model.create(args)'永遠不會是虛假的。即使驗證失敗,「create」也會返回無效的模型。 – Leito

0

你的心是正確的地方,確保你的代碼保持在它所屬的位置。我建議將它保留爲回調函數,而不是自定義服務,但將大部分代碼移到它自己的活動作業中(這樣可以異步運行它)。我看待它的方式是,該模型負責持久性,因此它是模型更改時「標記」並讓其他人前往並執行同步工作的最佳位置。

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建議的這個或服務。

相關問題