【问题标题】:validation and error-handling for service objects服务对象的验证和错误处理
【发布时间】:2023-03-23 07:33:02
【问题描述】:

我在 Rails 中创建了一个服务对象,作为我们的应用程序和 API 之间的接口。

我的想法来自http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/

这是一个小例子:

class PackagesService
  def self.get_package(package_id)
    raise ArgumentError.new("package_id can't be nil") if package_id.blank?
    package = API::get "/packages/#{package_id}"
    package = JSON.parse package,
                          :symbolize_names => true unless package.blank?

  end
end

是否有任何好的模式来处理服务对象的验证和/或抛出错误?

对于验证:

  • 我必须检查所有输入是否为 nil 或类型错误。有什么方法可以轻松验证吗?也许是 Rails 扩展?

对于错误:

  • 我可以捕获所有 API 错误,然后安全地返回 nil。但是使用服务对象的程序员可能不知道 nil 的含义。
  • 我可以捕获 API 错误并引发另一个错误,这意味着在所有函数中都要付出额外的努力
  • 第三个选项是保持原样,让程序员处理来自 API 的所有错误。

如果你知道任何好的模式或者你有更好的想法来接口 API,请告诉我。

【问题讨论】:

    标签: ruby-on-rails validation interface error-handling soa


    【解决方案1】:

    对于简单的情况(例如,只有一个参数),您可以使用 ArgumentError 进行检查和加注。一旦你开始遇到复杂的情况(多个参数、对象等),我就会开始依赖 VirtusActiveModel Validations

    Your linked article 实际上提到了这些(参见“提取表单对象”)。我有时会使用类似的东西来构造服务对象,例如。

    require 'active_model'
    require 'virtus'
    
    class CreatePackage
      include Virtus
      include ActiveModel::Validations
    
      attribute :name, String
      attribute :author, String
      validates_presence_of :name, :author
    
      def create
        raise ArgumentError.new("Invalid package") unless self.valid?
        response = JSON.parse(
          API::post("/packages", self.attributes),
          :symbolize_names => true
        )
        Package.new(response)
      end
    end
    
    class Package
      include Virtus
      attribute :id, Integer
      attribute :name, String
      attribute :author, String
    end
    
    # eg.
    service = CreatePackage.new(
      :name => "Tim's Tams",
      :author => "Tim",
    )
    service.valid? # true; if false, see service.errors
    package = service.create
    
    package.attributes
    # => { :id => 123, :name => "Tim's Tams", :author => "Tim" }
    

    就异常而言,我会将它们保持原样以用于较小的操作(例如此服务类)。但是,如果我要编写更实质性的东西,例如整个 API 客户端库,我包装它们。

    我永远不会只返回零。诸如网络错误或来自服务器的错误或无法解析的响应之类的事情都受益于显式错误。


    最后,还有一种更重的方法,称为use_case。即使您不使用它,它也有很多关于如何处理您可能会感兴趣的服务对象、验证和结果的想法。

    编辑:另外,请查看Mutations。与 use_case 类似,只是更简单且不够全面。

    【讨论】:

    • 非常感谢,这就是我正在寻找的答案!
    猜你喜欢
    • 2011-10-21
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-01
    • 1970-01-01
    相关资源
    最近更新 更多