8

*argsRailsの配列に条件付きでハッシュを追加するにはどうすればよいですか?元の値が存在する場合、それを踏みつけたくありません。

たとえば、配列を受け取るメソッドがあります。

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

それは機能しますが、冗長であまりルビーっぽくないようです。何かが足りなかったような気がします。

4

2 に答える 2

8

はい、#extract_options!Railsでそれを行う方法です。よりエレガントになりたい場合は、エイリアスを作成するか、このニーズに対処する独自の方法を見つけるか、すでにそれを行っている人が宝石を検索する必要があります。

于 2012-06-10T03:07:42.820 に答える
0

パーティーに少し遅れますが、定期的にこれを行う必要がある場合は、これに少しユーティリティメソッドを使用する価値があります-たとえば、-optionsハッシュをargs-aryにマージし、それをマージする次のように-ハッシュが存在しない場合は、既存のハッシュ引数を使用するか、新しいハッシュとして追加するだけです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"}]
于 2018-06-28T18:18:31.637 に答える