Wołanie zewnętrznych serwisów - best practices

Witam,

Mam pytanie związane z wołaniem zewnętrznych serwisów w aplikacji railsowej.

Dla przykładu, przed utworzeniem rekordu muszę zawołać zewnętrzy serwis i wykonać jakąś operację, jeżeli ta operacja wykona się poprawnie, tworzę rekord u siebie, jeżeli zewnętrzny serwis (z jakiegoś powodu) zwróci mi błąd to nie tworze u siebie żadnego rekorku tylko wtświetlam flasha z błędem.

Innym przkładem może być natychmiastowa płatność, klient wybiera sobie jakiś produkt/usługę na stronie i jest proszony o dokonanie natychmiastowej płatności. Jeżeli serwis płatności potwierdzi, że płatność została dokonana poprawnie to tworzymy rekord u siebie, jeżeli nie, to wyświetlamy flasha.

Czy możecie mnie nakierować na dobre praktyki dla tego przypadku.

  1. Czy dobrym rozwiązaniem będzie utworzenie “service objectu” i wołanie go w kontrolerze w: before_action :check_service, only: :create ?

  2. Czy przeieść to sprawdzenie gdzieś do modelu?

  3. Może jakieś inne rozwiązanie?

Będę bardzo wdzięczny za pomoc.

Pozdrawiam,
Bartek.

Rozwiązanie nr 1. to dobry pomysł tyle, że ja bym nie używał before_action tylko wywołał ten service object bezpośrednio w metodzie Create albo najlepiej żebyś zrobił osobny ‘service object’ dla logiki, która się dzieje w Create np. services/payments/create_payment.rb i w tym service object’ie użył tego pierwszego service object’u np.

module Payments
  class CreatePayment
     def initialize(payment_params)
       @payment_params = payment_params
     end

    def call
      if CheckService.new(payment_params).call
        Payment.create(@payment_params)
      end
    end
  end

w payments_controller.rb

 def create
   Payments::CreatePayment.new(payment_params).call
   # w zależności od rezultatu robisz odpowiedni redirect_to
 end

Hmm, w sumie to takim rozwiązaniu nie pomyślałem.

Dziękuję Ci bardzo!

Moj “best practice” w takich wypadkach:

  • nowy gem z pojedyncza odpowiedzialnoscia: “wołanie zewnetrznego serwisu”
  • tam jego testy i implementacja
  • “semantic versioning”
  • jedna funkcja publiczna = jeden endpoint w API

A jak to wywolywac? before|after, lub explicit, tam gdzie potrzebujesz…

T.

Zdecydowanie popieram. Before/after callbacki bardzo zaburzają czytelność a to jest core’owa funkcjonalność twojego endpointu więc wstawianie tego do before_action tylko by wprowadzało zamęt.