【发布时间】:2021-03-16 15:33:24
【问题描述】:
我有一堂课有以下交易:
# frozen_string_literal: true
class InactivateEmployee
include ServiceResult
def call(id)
begin
ActiveRecord::Base.transaction do
employee = Employee.find(id)
employee.update(is_active: false)
if employee.tasks.any?
employee.tasks.delete_all
end
response(code: 204, value: employee)
rescue ActiveRecord::ActiveRecordError
raise ActiveRecord::Rollback
end
rescue ActiveRecord::Rollback => e
response(code: 422, errors: e)
end
end
end
ServiceResult 在哪里:
# frozen_string_literal: true
# ServiceResult should be included in each Service Class to have a unified returned object from each service
ServiceResultResponse = Struct.new(:success?, :response_code, :errors, :value, keyword_init: true)
module ServiceResult
def response(code:, errors: nil, value: nil )
ServiceResultResponse.new(
success?: code.to_s[0] == '2',
response_code: code,
errors: errors,
value: value
)
end
end
问题 1: 这段代码可以吗?有什么可以改进的?
问题 2 如何使用 Rspec 测试此交易?如何在我的测试中模拟 destroy_all 引发和错误?我尝试过这样的事情 - 但它不起作用....
before do
allow(ActiveRecord::Associations::CollectionAssociation).to receive(:delete_all).and_return(ActiveRecord::ActiveRecordError.new)
end
【问题讨论】:
-
ServiceResult的用途是什么?
-
我已经在这个项目中有几个服务,我希望它们都有一个统一的响应对象。我曾经使用过来自dry-rb (dry-rb.org/gems/dry-monads/1.0/result) 的Result monad,但是在这个项目中,我们不允许使用任何未经许可的gem)。但是.... OpenStruct 这里有异味.... 简单的 Struct 会好很多(代码已更新)。
标签: ruby-on-rails rspec rspec-rails ruby-on-rails-5.1