2017-10-12 37 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