Результат работы сервиса
Каждый вызов сервиса возвращает результат (если не выброшено исключение). Результат может быть успешным или провальным.
Успешный результат
Успешный результат означает, что все операции завершились без проблем.
Пример:
service_result = UsersService::Accept.call(user: User.first)Возвращает:
# => <ApplicationService::Result @failure?=false, @success?=true, @user=..., @user?=true>Провальный результат
Провальный результат означает, что внутри произошла ожидаемая проблема. Ожидаемые проблемы не выбрасывают исключений — они вызываются через методы fail!.
Провальный результат возможен только при вызове через метод .call. Это позволяет обрабатывать ответы от внешних API.
Пример результата при неудаче:
# => <ApplicationService::Result @error=There is some problem with the user, @failure?=true, @success?=false>Содержимое результата
Result содержит данные независимо от исхода.
При успехе доступны все output атрибуты. Методы-хелперы success? и failure? определяют результат.
service_result = UsersService::Accept.call(user: User.first)
service_result.success? # => true
service_result.failure? # => falseПри неудаче Result также содержит error с полным описанием ошибки.
service_result = UsersService::Accept.call(user: User.first)
service_result.success? # => false
service_result.failure? # => true
service_result.error
# => #<ApplicationService::Exceptions::Failure: There is some problem with the user>Подробнее о неудачной работе сервиса здесь.
Обработка результата
Обработайте результат после вызова через call.
Два варианта: методы success?/failure? или хуки on_success/on_failure.
Методы
Метод success?
service_result = NotificatorService::Slack::Error::Send.call(...)
return if service_result.success?
fail!(
message: "The message was not sent to Slack",
meta: { reason: service_result.error.message }
)Метод failure?
Передайте тип в failure? для проверки конкретных типов неудач. См. типы неудач. Тип по умолчанию — all (любой тип неудачи).
service_result = NotificatorService::Slack::Error::Send.call(...)
return unless service_result.failure?
fail!(
message: "The message was not sent to Slack",
meta: { reason: service_result.error.message }
)Проверка конкретного типа неудачи:
service_result = NotificatorService::Slack::Error::Send.call(...)
return unless service_result.failure?(:validation)
fail!(
message: "The message was not sent to Slack",
meta: { reason: service_result.error.message }
)Методы-предикаты для удобной проверки типов:
WARNING
Output атрибуты Result также имеют методы-предикаты. Избегайте конфликтов имён.
service_result = NotificatorService::Slack::Error::Send.call(...)
return unless service_result.all?
fail!(
message: "The message was not sent to Slack",
meta: { reason: service_result.error.message }
)Хуки
Альтернативный подход к обработке результата:
NotificatorService::Slack::Error::Send
.call(...)
.on_failure do |exception:|
fail!(
message: "The message was not sent to Slack",
meta: { reason: exception.message }
)
endМетод on_success предоставляет аргумент outputs со всеми output атрибутами. Передайте тип в on_failure:
NotificatorService::Slack::Error::Send
.call(...)
.on_success do |outputs:|
notification.update!(original_data: outputs.response)
end.on_failure(:all) do |exception:|
fail!(
message: "The message was not sent to Slack",
meta: { reason: exception.message }
)
end