Until now, the execution result of the service class has been fairly appropriate.
For example, it returned the number of updates, and whether it was successful or not, with true and false, and so on.
In GitLab, I created a class called ServiceResponse
and used it to return the response of the execution result, and I thought it was very good, so I will summarize it.
In GitLab, it was as follows.
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
If successful
ServiceResponse.success(message: 'success!')
Is set as the return value when the service class is executed,
If it fails
ServiceResponse.error(message: 'failed')
Is set as the return value when the service class is executed.
You can check the status as shown below.
response = ServiceResponse.success(message: 'success!')
response.success? #=> true
response.error? #=> false
response.status #=> :success
response.message #=> 'success!'
On the controller side
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
You can divide the process depending on whether it succeeds or fails.
Recommended Posts