Rails 5 管理来自 monad 的结果
Rails 5 manage result from monads
我已经安装了 Rails 5 个应用 dry-monads。 Monad 用于在 AppointmentsController
中的 create
操作中创建 Appointment
对象。它们在最后一步中 return Success
或 Failure
具有以下结构:
# services/appointments/create.rb
(...)
def call
Success(appointment_params: appointment_params)
(...)
.bind(method(:save_appointment))
end
private
def save_appointment(appointment)
if appointment.save
Success(appointment)
else
Failure(failure_appointments: appointment, appointments_errors: appointment.errors.full_messages)
end
end
每次操作后(成功或失败)我想发送一封电子邮件并在AppointmentsController
中显示相应的json:
class Api::AppointmentsController < ApplicationController
def create
succeeded_appointments = []
failure_appointments = []
appointments_errors = []
batch_create_appointments_params[:_json].each do |appointment_params|
appointment = ::Appointments::Create.new(appointment_params).call
if appointment.success?
succeeded_appointments << appointment.value!
else
failure_appointments << appointment.failure[:failure_appointments] &&
appointments_errors << appointment.failure[:appointments_errors]
end
end
if failure_appointments.any?
AppointmentMailer.failed_mail(email, failure_appointments.size, appointments_errors).deliver_now
render json: {
error: appointments_errors.join(', '),
}, status: :bad_request
elsif succeeded_appointments.any?
AppointmentMailer.success_mail(email, succeeded_appointments.size).deliver_now
render json: {
success: succeeded_appointments.map do |appointment|
appointment.as_json(include: %i[car customer work_orders])
end,
}
end
end
我想知道是否有更好、更快的方法来记录这些错误,而不是像在 create
行动?到目前为止,创建操作看起来很重。
为批量创建创建单独的服务对象:
# services/appointments/bulk_create.rb
class Appointments::BulkCreate
def initialize(bulk_params)
@bulk_params = bulk_params
end
def call
if failed_results.any?
AppointmentMailer.failed_mail(email, failed_results_errors.size, failed_results_errors).deliver_now
Failure(failed_results_errors.join(', '))
else
AppointmentMailer.success_mail(email, success_appointments.size).deliver_now
Success(success_appointments)
end
end
private
attr_reader :bulk_params
def failed_results
results.select(&:failure?)
end
def success_results
results.select(&:success?)
end
def success_appointments
@success_appointments ||= success_results.map do |appointment|
appointment.as_json(include: %i[car customer work_orders])
end
end
def failed_results_errors
@failed_results_errors ||= failed_results.map do |failed_result|
failed_result.failure[:appointments_errors]
end
end
def results
@results ||= bulk_params.map do |appointment_params|
::Appointments::Create.new(appointment_params).call
end
end
end
那么您的控制器将如下所示:
class Api::AppointmentsController < ApplicationController
def create
result = ::Appointments::BulkCreate.new(batch_create_appointments_params[:_json]).call
if result.success?
render json: { success: result.value! }, status: :ok
else
render json: { error: result.failure }, status: :bad_request
end
end
end
我已经安装了 Rails 5 个应用 dry-monads。 Monad 用于在 AppointmentsController
中的 create
操作中创建 Appointment
对象。它们在最后一步中 return Success
或 Failure
具有以下结构:
# services/appointments/create.rb
(...)
def call
Success(appointment_params: appointment_params)
(...)
.bind(method(:save_appointment))
end
private
def save_appointment(appointment)
if appointment.save
Success(appointment)
else
Failure(failure_appointments: appointment, appointments_errors: appointment.errors.full_messages)
end
end
每次操作后(成功或失败)我想发送一封电子邮件并在AppointmentsController
中显示相应的json:
class Api::AppointmentsController < ApplicationController
def create
succeeded_appointments = []
failure_appointments = []
appointments_errors = []
batch_create_appointments_params[:_json].each do |appointment_params|
appointment = ::Appointments::Create.new(appointment_params).call
if appointment.success?
succeeded_appointments << appointment.value!
else
failure_appointments << appointment.failure[:failure_appointments] &&
appointments_errors << appointment.failure[:appointments_errors]
end
end
if failure_appointments.any?
AppointmentMailer.failed_mail(email, failure_appointments.size, appointments_errors).deliver_now
render json: {
error: appointments_errors.join(', '),
}, status: :bad_request
elsif succeeded_appointments.any?
AppointmentMailer.success_mail(email, succeeded_appointments.size).deliver_now
render json: {
success: succeeded_appointments.map do |appointment|
appointment.as_json(include: %i[car customer work_orders])
end,
}
end
end
我想知道是否有更好、更快的方法来记录这些错误,而不是像在 create
行动?到目前为止,创建操作看起来很重。
为批量创建创建单独的服务对象:
# services/appointments/bulk_create.rb
class Appointments::BulkCreate
def initialize(bulk_params)
@bulk_params = bulk_params
end
def call
if failed_results.any?
AppointmentMailer.failed_mail(email, failed_results_errors.size, failed_results_errors).deliver_now
Failure(failed_results_errors.join(', '))
else
AppointmentMailer.success_mail(email, success_appointments.size).deliver_now
Success(success_appointments)
end
end
private
attr_reader :bulk_params
def failed_results
results.select(&:failure?)
end
def success_results
results.select(&:success?)
end
def success_appointments
@success_appointments ||= success_results.map do |appointment|
appointment.as_json(include: %i[car customer work_orders])
end
end
def failed_results_errors
@failed_results_errors ||= failed_results.map do |failed_result|
failed_result.failure[:appointments_errors]
end
end
def results
@results ||= bulk_params.map do |appointment_params|
::Appointments::Create.new(appointment_params).call
end
end
end
那么您的控制器将如下所示:
class Api::AppointmentsController < ApplicationController
def create
result = ::Appointments::BulkCreate.new(batch_create_appointments_params[:_json]).call
if result.success?
render json: { success: result.value! }, status: :ok
else
render json: { error: result.failure }, status: :bad_request
end
end
end