我正在尝试将工厂方法集成到此英制到公制转换器中。我可以使它独立运行,但是当它遍历一个哈希值时,它会弹出一个NoMethodError
。我做错了什么?
我已经在工厂中运行了独立的实例变量而没有问题:
@item = "cups"
@number = 89.2
Gramulator.for(@number, @item) # => 828.0300000000001
我已经确认输入可以正常使用。我什至已经成功地使用@dough.unit
和@dough.amount
来运行它:
Gramulator for(@dough.amount, @dough.unit) # => 828.0300000000001
但是当我通过迭代方法本身指出它时,@dough.gramulate
不起作用。
class Unit
def initialize(amount)
@amount = amount
end
def calculate
@amount.to_f
end
end
class Cup < Unit
def calculate
(super * 236.58)
end
end
class Recipe
attr_accessor :amount
attr_reader :name, :unit
def initialize(ingredient_hash)
@ingredient_hash = ingredient_hash
end
def gramulate
puts "CONVERTED TO GRAMS:"
@ingredient_hash.each do |name, quantity|
quantity_array = quantity.split
@name = name
@amount = quantity_array[0].to_f
@unit = quantity_array[1]
Gramulator.for(@amount, @unit)
puts "#{@name}: #{@amount} grams"
end
end
end
module Gramulator
@units = {
"cups" => Cup
# <other measurements>
}
def self.for(unit, amount)
(@units[unit]).new(amount).calculate
end
end
@dough = Recipe.new({
bread_flour: "3.5 cups"
# <other ingredients>
})
预期结果:
CONVERTED TO GRAMS:
bread_flour: 828.0300000000001 grams
实际结果:
CONVERTED TO GRAMS:
NoMethodError: undefined method 'new' for nil:NilClass
答案 0 :(得分:1)
您使用Gramulator.for(@amount, @unit)
,但是Gramulator.for
期望unit, amount
。
这会导致@units[unit]
返回nil,因为您在单位参数中给了它"3.5"
而不是"cups"
。
答案 1 :(得分:0)
致电@units[unit]
会得到nil
,因为在其上方您正在以{strong> unit 和 amount 。参见for
。签名是Gramulator.for(@amount, @unit)
。
话虽这么说... 也许我过于简化了,但是我认为您的代码可以减少。
下面,我将其重写为脚本,可以将其设置为可执行文件(使用def self.for(unit, amount)
)并以 ./ gramulator.rb 运行。
如果需要将其合并到更大的项目中,请随时跳过第一行和最后两行。
chmod +x
请注意,#!/usr/bin/env ruby
class Gramulator
UNITS = { "cups" => 236.58 }
def self.for(unit, amount)
amount.to_f * UNITS[unit]
end
end
class Recipe
def initialize(ingredients)
@ingredients = ingredients
end
def gramulate
puts "CONVERTED TO GRAMS"
@ingredients.each do |name, quantity|
amount, unit = quantity.split
puts "%s: %.2f grams" % [name, amount]
Gramulator.for(unit, amount)
end
end
end
dough = Recipe.new({ bread_flour: "3.5 cups" })
dough.gramulate
返回puts
,因此是避免在循环/迭代矿石方法结束时使用它的好习惯。在这里,您使用的是nil
,这很好,因为您可能不希望重用each
的结果。
但是,在Ruby中,使用其他有用的ingredients.each {...}
方法(如 map , detect 等)可能会带来更多乐趣。它们返回的结果有所不同而不是您要迭代的原始集合,因此循环的最后一行需要是“某物”。我强烈建议您调查一下。
很抱歉,很长一段时间,它只是为了帮助您 Ruby可以为您提供什么。