2017-10-12 51 views
0

這是在Ruby中使用異常的好習慣嗎? (如果object.nil引發ArgumentError的用法)Ruby異常優秀實踐

我應該在這裏刪除ArgumentError嗎?或者編寫自定義異常,如ProductNilError,QuantityMustBeMoreThanZeroError?

def create_order(product, options = { quantity: 1, guests: nil, confirmation_needed: false }) 
    raise ArgumentError, 'product is nil' if product.nil? 

    guests = options.has_key?(:guests) ? options[:guests] : nil 
    quantity = options.has_key?(:quantity) ? options[:quantity] : nil 
    confirmation_needed = options.has_key?(:confirmation_needed) ? options[:confirmation_needed] : nil 

    raise ArgumentError, 'quantity must be > 0' if quantity.nil? || quantity < 0 || quantity == 0 
    raise ArgumentError, 'product of beneficiary_type need guests' if product.is_a_beneficiary_type? && guests.nil? 
    raise ArgumentError, 'guests do not respond_to each (not an array)' if !guests.nil? && !guests.respond_to?(:each) 
    raise ArgumentError, 'product of quantity_type do not need guests' if product.is_a_quantity_type? && !guests.nil? 

    begin 
     order = build_order(guests, product) 
     debit_stock(quantity) 
     pay(order, product, quantity) 
     confirm_order(order) 
    ensure 
     rollback(order, quantity) 
    end 
    end 
+2

這是真的嗎?如果是這樣,爲什麼不使用模型驗證? –

+3

只是一個附註,但'guests = options.has_key?(:guests)?選項[:guests]:nil'是不必要的。哈希值在一個未知的密鑰中已經爲零,你可以只說'guests = options [:guests]' –

+3

應該使用驗證,而不是在我看來引發錯誤。對不起,沒有你的答案,因爲我相信它會需要一些重構。 – vee

回答

2

由於這是在意見建議,我會鼓勵你使用ActiveRecord驗證:

http://guides.rubyonrails.org/active_record_validations.html

這裏你的問題問一個例子:

class Order < ActiveRecord::Base 
    validates :product, presence: true 
    validates :quantity, numericality: { greater_than: 0 } 
    validate :beneficiary_type 

    def beneficiary_type 
    return true unless product.is_a_beneficiary_type? && guests.nil? 
    errors.add(:guests, 'product of beneficiary_type need guests.') 
    end 
end 

當您創建Order實例時,您可以執行這些驗證。一個例子可能是在控制器創建動作:

def create 
    permitted = permitted_params # permit some params 
    @order.new(permitted) 
    if @order.valid? 
    @oder.save! 
    flash[:success] = "Order #{@order.id} has been created!" 
    redirect_to action: :index 
    else 
    render action: :new 
    end 
end