Ruby 使用默认命名参数将“nil”传递给方法
在Rails项目中,我正在收集一个包含10-15个键值对的散列,并将其传递给一个类(服务对象)进行实例化。除了没有值(或Ruby 使用默认命名参数将“nil”传递给方法,ruby,named-parameters,Ruby,Named Parameters,在Rails项目中,我正在收集一个包含10-15个键值对的散列,并将其传递给一个类(服务对象)进行实例化。除了没有值(或nil)外,应根据哈希中的值设置对象属性。在这种情况下,希望将属性设置为默认值 在创建对象之前,我不想检查散列中的每个值是否不是nil,而是想找到一种更有效的方法 我正在尝试使用带有默认值的命名参数。我不知道这是否有意义,但我想在使用nil调用参数时使用默认值。我为此功能创建了一个测试: class Taco def initialize(meat: "steak", ch
nil
)外,应根据哈希中的值设置对象属性。在这种情况下,希望将属性设置为默认值
在创建对象之前,我不想检查散列中的每个值是否不是nil
,而是想找到一种更有效的方法
我正在尝试使用带有默认值的命名参数。我不知道这是否有意义,但我想在使用nil
调用参数时使用默认值。我为此功能创建了一个测试:
class Taco
def initialize(meat: "steak", cheese: true, salsa: "spicy")
@meat = meat
@cheese = cheese
@salsa = salsa
end
def assemble
"taco with: #@meat + #@cheese + #@salsa"
end
end
options1 = {:meat => "chicken", :cheese => false, :salsa => "mild"}
chickenTaco = Taco.new(options1)
puts chickenTaco.assemble
# => taco with: chicken + false + mild
options2 = {}
defaultTaco = Taco.new(options2)
puts defaultTaco.assemble
# => taco with: steak + true + spicy
options3 = {:meat => "pork", :cheese => nil, :salsa => nil}
invalidTaco = Taco.new(options3)
puts invalidTaco.assemble
# expected => taco with: pork + true + spicy
# actual => taco with: pork + +
我认为关键字参数不适合你的情况。看起来杂烩更合适
class Taco
attr_accessor :ingredients
def initialize(ingredients = {})
@ingredients = ingredients
end
def assemble
"taco with: #{ingredients[:meat]} + #{ingredients[:cheese]} + #{ingredients[:salsa]}"
end
end
您甚至可以缩短assembly
方法来列出所有成分
def assemble
string = "taco with: " + ingredients.values.join(" + ")
end
它将如你所期望的那样工作
options1 = {:meat => "chicken", :cheese => false, :salsa => "mild"}
chicken_taco = Taco.new(options1)
puts chicken_taco.assemble() # output: taco with: chicken + false + mild
值得一提的是,Ruby更喜欢
chicken\u tacos
而不是chickenTacos
一旦您通过一个命名参数传递了一个值,那么该方法调用就不再访问该参数的默认值
您必须(i)在sagarpandya82的答案中,不是在方法概要文件中而是在方法主体中指定默认值,或者(ii)在使用Rails的Hash#compact将参数像这样传递给方法之前,删除nil
值:
options3 = {:meat => "pork", :cheese => nil, :salsa => nil}
invalidTaco = Taco.new(options3.compact)
如果您想采用面向对象的方法,可以在单独的方法中隔离默认值,然后使用
Hash#merge
:
class Taco
def initialize (args)
args = defaults.merge(args)
@meat = args[:meat]
@cheese = args[:cheese]
@salsa = args[:salsa]
end
def assemble
"taco with: #{@meat} + #{@cheese} + #{@salsa}"
end
def defaults
{meat: 'steak', cheese: true, salsa: 'spicy'}
end
end
然后按照@sawa的建议(谢谢),使用Rails“Hash#compact
作为您的输入哈希,该哈希已明确定义了nil
值,您将获得以下输出:
taco with: chicken + false + mild
taco with: steak + true + spicy
taco with: pork + true + spicy
编辑:
如果您不想使用Rails的奇妙的Hash#compact
方法,您可以使用Ruby的Array#compact
方法。将初始化
方法中的第一行替换为:
args = defaults.merge(args.map{|k, v| [k,v] if v != nil }.compact.to_h)
谢谢你的回答!有没有办法为您在回答中提到的一些
成分散列键提供默认值?例如,如果肉
没有作为配料提供,它仍然会打印墨西哥玉米卷,并带有:{default_meat}+{other_component_a}+…
?配料[:meat]| |=“default meat”
将允许您有条件地为该键指定默认值(如果未指定)。我删除了我的答案,因为我无法获得所需的输出。如果您知道如何修复,请随意将其纳入您的答案。@sagarpandya2我看不出您的答案有任何错误。至少,它比公认的答案要好得多,后者甚至不考虑默认值(除了在事后对OP的评论做出的回应)。OP想要taco,第一个字符串为:chicken+false+mild
。我的代码打印的墨西哥玉米卷带有:鸡肉+正品+淡味
。这是唯一的原因。你能看到修复方法吗?谢谢@sawa,但我认为在这种情况下使用|
是有缺陷的,所以我提交了一个新的答案,其中包含了你的答案。@sawa我非常喜欢Hash#compact方法,它在这种情况下的使用。感谢您对Ruby语言进行了更多的介绍!感谢您提供的格式帮助sawaUsingHash#merge
以及Hash#compact
是确保我的对象的属性获得默认值而不是nil
值的一种很好的方法。非常感谢你!