2013-06-21 4 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 в порядке. Как только вы начинаете иметь сложные случаи (несколько аргументов, объектов и т. Д.), Я начинаю опираться на Virtus и ActiveModel 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" } 

Что касается исключений, я бы оставил их как есть для меньших действий (например, этот класс обслуживания). I будет обернуть их, если я напишу что-то более существенное, например, как вся клиентская библиотека API.

Я бы никогда не вернулся. Такие вещи, как сетевая ошибка или плохой или непревзойденный ответ от сервера, выигрывают от явных ошибок.


Наконец, есть гораздо более тяжелый подход называется use_case. Даже если вы не используете его, у него есть куча идей о том, как решать объекты обслуживания, проверки и результаты, которые могут вам показаться интересными.

Редактировать: Кроме того, ознакомьтесь с Mutations. Как use_case, кроме более простого и менее всеобъемлющего.

+1

Большое спасибо, это тот ответ, который я искал! – ieldanr