Ruby捕获名称错误

Ruby捕获名称错误,ruby,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 delive

我有以下两个类的代码

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
我想
delivery\u to
方法在提供的
delivery\u服务无效(不存在)时抛出类似于“选择有效的delivery服务”的东西,但我得到的却是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> 
irb(main):001:0>require./DeliveryService.rb'
=>正确
irb(main):002:0>fedex=DeliveryService.new“莫斯科”、“圣彼得堡”
=> #
irb(主):003:0>产品=产品。新“杯子”
=> #
irb(主要):004:0>产品交付至联邦快递,“莫斯科”
产品已交付
=>零
irb(主要):005:0>产品交付至dhl,“莫斯科”
NameError:未定义的局部变量或main:对象的“dhl”方法
来自(irb):6
from/home/budkin/.rbenv/versions/2.1.2/bin/irb:11:in`'
irb(主要):006:0>

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

begin
    product.deliver_to dhl, "Moscow" 
rescue NameError => e
    puts e.message
end
虽然这是一个相当混乱的方法。更好的方法是创建一个包含所有公司的
数组
,然后检查该
集中是否定义了公司
/
数组

对正确的对象使用依赖项注入 这是一个设计问题,因为您不会从类中得到NameError;当你在课堂外呼叫
product.deliver_到dhl“Moscow”
时,会引发此问题。即使类定义中有一个rescue子句,调用方也会引发NameError

解决此问题的正确方法是将有效的产品对象传递给有效的DeliveryService对象。一个产品无论如何都不应该知道任何关于交付的信息;这违反了单一责任原则。因此:

class DeliveryService
  def deliver product
  end
end
这将为您提供一个获取产品并通过当前交付服务交付的实例方法。例如:

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

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

我需要
为任何不存在的公司发布一条消息