はじめに
serviceクラスの実行結果を今までは結構適当にしていました。
例えば、更新した件数を返したり、成功したかどうかをtrue,falseで返したり、まちまちでした。
GitLabではServiceResponse
というクラスを作ってそれを使って実行結果のレスポンスを返していて、とても良いと思ったのでまとめます。
中身
GitLabでは下記の様になっていました。
https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/service_response.rb
# frozen_string_literal: true
class ServiceResponse
def self.success(message: nil, payload: {}, http_status: :ok)
new(status: :success, message: message, payload: payload, http_status: http_status)
end
def self.error(message:, payload: {}, http_status: nil)
new(status: :error, message: message, payload: payload, http_status: http_status)
end
attr_reader :status, :message, :http_status, :payload
def initialize(status:, message: nil, payload: {}, http_status: nil)
self.status = status
self.message = message
self.payload = payload
self.http_status = http_status
end
def success?
status == :success
end
def error?
status == :error
end
def errors
return [] unless error?
Array.wrap(message)
end
private
attr_writer :status, :message, :http_status, :payload
end
使い方
成功した場合は
ServiceResponse.success(message: 'success!')
をserviceクラスの実行した際の戻り値に設定して、
失敗した場合は
ServiceResponse.error(message: 'failed')
をserviceクラスの実行した際の戻り値に設定します。
下記の様に、ステータスを確認できます。
response = ServiceResponse.success(message: 'success!')
response.success? #=> true
response.error? #=> false
response.status #=> :success
response.message #=> 'success!'
controller側では
result = ArticleUpdateService.new(@article, params).call
if result.success?
redirect_to article_path(@article), notice: result.message
elsif result.error?
render :new, alert: result.message
end
みたいな形で成功した場合と失敗した場合で処理を分けることができます。