ruby - Controller 和交互器错误处理的最佳实践

标签 ruby error-handling hanami

# users_show_controller.rb
class Controllers::Users::Show
  include Hanami::Action

  params do
    required(:id).filled(:str?)
  end

  def call(params)
    result = users_show_interactor(id: params[:id])

    halt 404 if result.failure?
    @user = result.user
  end
end

# users_show_interactor.rb
class Users::Show::Interactor
  include Hanami::Interactor

  expose :user
  def call(:id)
    @user = UserRepository.find_by(:id)
  end
end

我有一个 Controller 和一个像上面那样的交互器。 我正在考虑在 Controller 上区分 ClientError 和 ServerError 的更好方法。

我想如果我能像下面这样处理错误就好了。

handle_exeption StandardError => :some_handler

但是,hanami-interactor 包装了内部引发的错误,因此, Controller 通过来自交互器的结果对象接收错误。

我不认为在 Controller 上重新引发错误是个好方法。

result = some_interactor.call(params)
raise result.error if result.failure

如何实现这样的错误处理程序? 我知道 if 语句很容易增加,所以这种方式并不明智。

def call(params)
  result = some_interactor.call(params)
  handle_error(result.error) if result.faulure?
end

private

def handle_error(error)
  return handle_client_error(error) if error.is_a?(ClientError)
  return server_error(error) if error.is_a?(ServerError)
end

最佳答案

实际上不是面向 hanami 的方式,但请查看 dry-monads with do notation .基本思路是,你可以按照下面的方式编写类似交互器的处理代码

def some_action
  value_1 = yield step_1
  value_2 = yield step_2(value_1)
  return yield(step_3(value_2))
end 

def step_1
  if condition
    Success(some_value)
  else
    Failure(:some_error_code)
  end
end

def step_2
  if condition
    Success(some_value)
  else
    Failure(:some_error_code_2)
  end
end

然后在 Controller 中,您可以使用 dry-matcher 匹配故障:

matcher.(result) do |m|
  m.success do |v|
    # ok
  end

  m.failure :some_error_code do |v|
    halt 400
  end

  m.failure :some_error_2 do |v|
    halt 422
  end
end

匹配器可以在所有 Controller 的prepend代码中定义,因此很容易去除代码重复。

关于ruby - Controller 和交互器错误处理的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51607163/

相关文章:

ruby-on-rails - 通过 Rails 3 中的唯一列值选择所有列

ruby-on-rails - 目录 : Securing a Closed API

像 PHP nowdoc 这样的 Ruby 多行字符串?

error-handling - 如何从NServiceBus放入错误队列的消息中获取错误stacktrace?

validation - 选择在哪里放置验证?

ruby-on-rails - 如何在 Rails ActiveJob 中创建日常工作(类似 cron)?

c++ - 我们应该如何实现 std::error_code 兼容的 API?

haskell - Haskell进入元组

ruby - Hanami link_to 助手只呈现最后一个元素

ruby - 如何使用花见记录器?