如何使用图示和一个可选的散列在同一时间定义在红宝石的方法? [重复](How to define

2019-07-17 10:58发布

这个问题已经在这里有一个答案:

  • 图示参数后的可选参数 6回答

我可以这样定义的方法:

def test(id, *ary, hash_params)
  # Do stuff here
end

但是这使得hash_params参数强制性的。 这些不工作之一:

def t(id, *ary, hash_params=nil)  # SyntaxError: unexpected '=', expecting ')'
def t(id, *ary, hash_params={})   # SyntaxError: unexpected '=', expecting ')'

有没有一种方法,使之选?

Answer 1:

你不能做到这一点。 你必须考虑关于Ruby如何能够确定哪些属于*ary ,什么属于可选的哈希值。 由于红宝石无法了解你的心思,上面的参数组合(图示+可选)是不可能为它在逻辑上解决。

你要么必须重新安排你的论点:

def test(id, h, *a)

在这种情况下, h不会是可选的。 或者,然后手动编程它:

def test(id, *a)
  h = a.last.is_a?(Hash) ? a.pop : nil
  # ^^ Or whatever rule you see as appropriate to determine if h
  # should be assigned a value or not.


Answer 2:

有通过使用阵列扩展这种支持中的ActiveSupport extract_options!

def test(*args)
  opts = args.extract_options!
end

如果最后一个元素是一个散列,那么它会从数组弹出并返回它,否则它会返回一个空的哈希值,这在技术上是一样的,你想要什么(*args, opts={})做的。

的ActiveSupport阵列#extract_options!



Answer 3:

除了卡斯佩斯回答 :

您可以使用飞溅参数和检查,如果最后一个参数是一个哈希值。 然后你把哈希作为设置。

一个代码示例:

def test(id, *ary )
  if ary.last.is_a?(Hash)
    hash_params =   ary.pop
  else
    hash_params =   {}
  end
  # Do stuff here

  puts "#{id}:\t#{ary.inspect}\t#{hash_params.inspect}"
end


test(1, :a, :b )
test(2, :a, :b, :p1 => 1, :p2 => 2 )
test(3, :a,  :p1 => 1, :p2 => 2 )

结果是:

1:  [:a, :b]    {}
2:  [:a, :b]    {:p1=>1, :p2=>2}
3:  [:a]    {:p1=>1, :p2=>2}

这将使问题,如果你的阵列参数应该包含在最后位置的哈希值。

test(5, :a,  {:p1 => 1, :p2 => 2} )
test(6, :a,  {:p1 => 1, :p2 => 2}, {} )

结果:

5:  [:a]    {:p1=>1, :p2=>2}
6:  [:a, {:p1=>1, :p2=>2}]  {}


Answer 4:

你可以(误)使用可选块在参数列表的末尾:

def test(id,*ary, &block)
  if block_given?
    opt_hash = block.call
    p opt_hash
  end
  p id
  p ary
end

test(1,2,3){{:a=>1,:b=>2}}
# output:
# {:a=>1, :b=>2} #Hurray!
# 1
# [2, 3]


Answer 5:

@Casper是正确的。 只有一个参数可以有图示操作。 参数会被分配给第1左到右非splatted参数。 其余的参数会被分配到图示参数。

你可以这样做,因为他建议。 你也可以这样做:

def test(id,h={},*a)
  # do something with id
  # if not h.empty? then do something with h end
  # if not a.empty? then do something with a end
end

下面是一些样品IRB运行:

001 > def test (id, h={}, *a)
002?>   puts id.inspect
003?>   puts h.inspect
004?>   puts a.inspect
005?>   end
 => nil 
006 > test(1,2,3,4)
1
2
[3, 4]
 => nil 
007 > test(1,{"a"=>1,"b"=>2},3,4)
1
{"a"=>1, "b"=>2}
[3, 4]
 => nil 
008 > test(1,nil,3,4)
1
nil
[3, 4]
 => nil

也许,我应该补充。 你可以有一个可选的参数作为最后一个参数,但它必须是一个块的/ proc。

例如:

def test(a,*b, &c)
  puts a.inspect
  puts b.inspect
  c.call if not c.nil?
end

下面是一些示例电话:

006 > test(1,2,3)
1
[2, 3]
 => nil 
007 > test(1,2,3) {puts "hello"}
1
[2, 3]
hello
 => nil 


文章来源: How to define a method in ruby using splat and an optional hash at the same time? [duplicate]