使用默认命名参数将“nil”传递给方法
Passing `nil` to method using default named parameters
在一个 Rails 项目中,我正在收集一个包含 10-15 个键值对的散列,并将其传递给 class(服务对象)以进行实例化。对象属性应该从散列中的值设置,除非没有值(或 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
您甚至可以缩短 assemble
列出所有成分的方法
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 比 chickenTacos
更喜欢 chicken_tacos
。
使用命名参数传递值后,该方法调用将无法访问该参数的默认值。
您要么必须 (i) 不在方法配置文件中而是在方法主体中分配默认值,如 sagarpandya82 的回答,或者 (ii) 在将参数传递给方法之前删除 nil
值像这样使用 Rails' Hash#compact
:
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
方法。将 initialize
方法中的第一行替换为:
args = defaults.merge(args.map{|k, v| [k,v] if v != nil }.compact.to_h)
在一个 Rails 项目中,我正在收集一个包含 10-15 个键值对的散列,并将其传递给 class(服务对象)以进行实例化。对象属性应该从散列中的值设置,除非没有值(或 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
您甚至可以缩短 assemble
列出所有成分的方法
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 比 chickenTacos
更喜欢 chicken_tacos
。
使用命名参数传递值后,该方法调用将无法访问该参数的默认值。
您要么必须 (i) 不在方法配置文件中而是在方法主体中分配默认值,如 sagarpandya82 的回答,或者 (ii) 在将参数传递给方法之前删除 nil
值像这样使用 Rails' Hash#compact
:
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
方法。将 initialize
方法中的第一行替换为:
args = defaults.merge(args.map{|k, v| [k,v] if v != nil }.compact.to_h)