Ruby捕获NameError

时间:2014-09-04 00:11:33

标签: ruby

我有两个类的以下代码

class DeliveryService
  attr_reader :cities

  def initialize *cities 
    @cities = cities
  end
end

class Product
  attr_accessor :name

  def initialize name
    @name = name
  end

  def deliver_to delivery_service, city
    if delivery_service.cities.include?(city)
      puts "Product has been delivered"
    else
      puts "Сontact another delivery service"
    end
  end
end

我想deliver_to方法抛出类似"选择有效的送货服务"提供无效delivery_service时(不存在),但我得到NameError

我试着将它放在我的代码中的不同位置

rescue NameError
  puts "Choose valid delivery service"

但它不起作用

irb(main):001:0> require './DeliveryService.rb'
=> true
irb(main):002:0> fedex = DeliveryService.new "Moscow", "Saint-Petersburg"
=> #<DeliveryService:0x007f66ded31520 @cities=["Moscow", "Saint-Petersburg"]>
irb(main):003:0> product = Product.new "mug"
=> #<Product:0x007f66ded1e498 @name="mug">
irb(main):004:0> product.deliver_to fedex, "Moscow"
Product has been delivered
=> nil
irb(main):005:0> product.deliver_to dhl, "Moscow"
NameError: undefined local variable or method `dhl' for main:Object
    from (irb):6
    from /home/budkin/.rbenv/versions/2.1.2/bin/irb:11:in `<main>'
irb(main):006:0> 

2 个答案:

答案 0 :(得分:1)

在正确对象上使用依赖注入

这是一个设计问题,因为您没有从类中获取NameError;当你从班级外面打电话给product.deliver_to dhl, "Moscow"时,它就会被提升。即使你有一个救援子句作为你的类定义的一部分,也会由调用者引发

解决此问题的正确方法是将有效的Product对象传递给有效的DeliveryService对象。产品不应该对交货情况有任何了解;这违反了单一责任原则。所以:

class DeliveryService
  def deliver product
  end
end

这将为您提供一个实例方法,该方法接收产品,并通过当前的传递服务提供。例如:

product = Product.new :widget
dhl = DeliveryService.new 'Moscow'
dhl.deliver product

即使您执行此反转,如果您传递无效对象也会遇到问题,所以不要这样做。 :)

答案 1 :(得分:0)

dh1不存在,因此您需要包含尝试取消引用dh1的部分代码。

begin
    product.deliver_to dhl, "Moscow" 
rescue NameError => e
    puts e.message
end

虽然这是一个非常混乱的方法。更好的方法是创建包含所有公司的arrayset,然后检查公司是否已在set / array中定义。