2013-06-21 30 views
10

我在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 

是否有處理驗證和/或引發錯誤的服務對象有什麼好的模式?

爲了驗證:

  • 我要檢查所有的輸入,零或錯誤的類型。有什麼方法可以輕鬆驗證嗎?也許是軌道延伸?

錯誤:

  • 我可以捕捉所有API錯誤,然後安全返回零。但是使用服務對象的程序員可能不知道nil的含義。
  • 我可以捕獲API錯誤,並引發另一個錯誤,這意味着在所有函數中做這些額外的工作
  • 第三個選項是保持原樣並讓程序員處理來自API的所有錯誤。

讓我知道你是否知道任何好的模式,或者如果你有更好的想法來連接API。

回答

13

對於簡單的情況(例如只有一個參數),那麼你的檢查和提高與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一樣,除了更簡單和不太全面。

+1

非常感謝,這是我一直在尋找的答案! – ieldanr