简体   繁体   English

如何向* args添加哈希?

[英]How do I add a hash to *args?

How do I conditionally add a hash to an *args array in Rails? 如何有条件地在Rails中的*args数组中添加哈希? I don't want to stomp on the original value if one exists. 如果存在原始值,我不想踩踏原始值。

For instance, I have an method that receives an array: 例如,我有一个接收数组的方法:

def foo(*args)
  # I want to insert {style: 'bar'} into args but only if !style.present?
  bar(*args)                              # do some other stuff 
end

I've started using the extract_options and reverse_merge methods provided by rails: 我已经开始使用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

It works but seems verbose and not very ruby-ish. 它有效,但看起来很冗长,而且不是很红宝石。 I feel like I've missed something. 我觉得我错过了什么。

Yes, #extract_options! 是的, #extract_options! is the way to do it in Rails. 是在Rails中实现它的方法。 If you want to be more elegant, you'll have to alias it, or find your own way of handling this need, or search for gem by someone who has already done it. 如果你想要更优雅,你必须使用别名,或者找到你自己的方式来处理这个需求,或者由已经完成它的人搜索gem。

A bit late to the party - but in case you need to do this on a regular basis it's worth using a little utility method for this - eg like the following, which merges an options -hash into an args -ary - and takes care of merging it with possibly existing hash-args or just appending it as new hash, if no hash is present in the args : 派对有点迟了 - 但是如果您需要定期执行此操作,则值得使用一个小实用程序方法 - 例如,如下所示,将options -hash合并到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

This comes in handy if you want to merge a modified options -hash back into *args and pass these along to another method, eg: 如果你想将修改后的options -hash合并回*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))

Some more examples: 更多例子:

# 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"}]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM