如何在Rails中有条件地将哈希添加到*args
数组?如果存在原始值,我不想踩踏原始值。
例如,我有一个接收数组的方法:
def foo(*args)
# I want to insert {style: 'bar'} into args but only if !style.present?
bar(*args) # do some other stuff
end
我已经开始使用rails提供的extract_options和reverse_merge方法:
def foo(*args)
options = args.extract_options! # remove the option hashes
options.reverse_merge! {style: 'bar'} # modify them
args << options # put them back into the array
bar(*args) # do some other stuff
end
它有效,但看起来很冗长,而且不是很红宝石。我觉得我错过了什么。
答案 0 :(得分:8)
是的,#extract_options!
是在Rails中实现它的方法。如果你想要更优雅,你必须使用别名,或者找到你自己的方式来处理这个需求,或者由已经完成它的人搜索gem。
答案 1 :(得分:0)
参加聚会有点晚-但是如果您需要定期进行此操作,则值得为此使用一些实用程序方法-例如类似于以下内容,它将options
哈希合并为args
-ary-并负责将其与可能存在的hash-args合并,或者仅在不存在哈希的情况下将其追加为新哈希args
:
def merge_into_args!(opts={}, *args)
opts.each do |key, val|
if args.any?{|a| a.is_a?(Hash)}
args.each{|a| a.merge!(key => val) if a.is_a?(Hash)}
else
args << {key => val}
end
end
args
end
如果您想将修改后的options
哈希合并回*args
并将它们传递给另一种方法,例如:
# extract options from args
options = args.extract_options!
# modify options
# ...
# ...
# merge modified options back into args and use them as args in another_method
args = merge_into_args!(options,*args)
another_method(*args)
# or as 1-liner directly in the method call:
another_method(*merge_into_args!(options,*args))
# and in your case you can conditionally modify the options-hash and merge it
# back into the args in one go like this:
another_method(*merge_into_args!(options.reverse_merge(style: 'bar'),*args))
更多示例:
# args without hash
args = ["first", "second"]
# merge appends hash
args = merge_into_args!({ foo: "bar", uk: "zok" },*args)
#=> ["first", "second", {:foo=>"bar", :uk=>"zok"}]
# Another merge appends the new options to the already existing hash:
args = merge_into_args!({ ramba: "zamba", halli: "galli" },*args)
#=> ["first", "second", {:foo=>"bar", :uk=>"zok", :ramba=>"zamba", :halli=>"galli"}]
# Existing options are updated accordingly when the provided hash contains
# identical keys:
args = merge_into_args!({ foo: "baz", uk: "ZOK!", ramba: "ZAMBA" },*args)
#=> ["first", "second", {:foo=>"baz", :uk=>"ZOK!", :ramba=>"ZAMBA", :halli=>"galli"}]