2

There's a method that's usually called with named arguments and it looks like this

def foo(x = nil, y = nil)
  fail ArgumentError, "x must be present" unless x
  fail ArgumentError, "y must be present" unless y
  # do stuff with x and y
end

I want to rewrite as something like

def foo(x = nil, y = nil)
  required_arguments :x, :y
  # do stuff with x and y
end

or

class Foo
  required_arguments :bar, :x, :y

  def bar(x = nil, y = nil)
  end
end

I've tried to implement second approach with alias_method_chain but the problem is that __method__ is evaluated in the context of my utility module so I can't access the parameters of the method I need to check. Any ideas?

4

2 回答 2

3

If you use ruby 2.0 you can use keyword arguments:

def foo(x: (fail ArgumentError), y: (fail ArgumentError))
  # do stuff with x and y
end

And in ruby 2.1 you have proper required arguments:

def foo(x:, y:)
  # do stuff with x and y
end

This way you do actually have named parameters (you called them named parameters in your question, but that's a bit confusing imho), so you have to call the method like this:

foo(x: 1, y: 2)
于 2013-11-01T08:03:53.530 回答
0

这种运行时断言的价值是有限的,但它们确实有它们的用途。我已将它们合并到YSupport. 输入gem install y_support您的命令行,并按如下方式使用它

require 'y_support/typing'

def foo x=nil, y=nil
  x.aT; y.aT
  # do stuff with x and y
end

助记符: In aT,a表示“断言”,T表示-如果断言失败,则TypeError引发。TypeError如果#aT在没有参数的情况下调用方法,它只是强制接收者必须为真。如果提供了一个块,则可以写入任何断言。例如,以下调用强制接收者可以被 3 整除:

6.aT { |n| n % 3 == 0 }  #=> 6
7.aT { |n| n % 3 == 0 }  #=> TypeError: 7:fixnum fails its check!

在检查方法参数的情况下,ArgumentError适用于参数数量错误和类似问题的情况。当参数类型错误时,我更喜欢 raise TypeError#aT可以使用两个字符串参数自定义方法的错误消息。第一个描述接收者,第二个描述块断言。例如:

7.aT "number of apples", "be divisible by three" do |n| n % 3 == 0 end
#=> TypeError: Number of apples fails to be divisible by three!

如果该#aT方法通过,则返回其接收者,因此可以链接断言:

81.aT( "no. of apples", "divisible by 3 ) { |n|
  n % 3 == 0
}.aT( "no. of apples", "be a square" ) { |n|
  root = n ** 0.5; root == root.floor
} ** 0.5 #=> 9.0

其他更专业的运行时断言在 中可用YSupport,例如:

[ 1, 2, 3 ].aT_kind_of Enumerable #=> [ 1, 2, 3 ]
:foobar.aT_respond_to :each
#=> TypeError: Foobar:symbol does not respond to method 'each'!
:foobar.aT_respond_to :each, "object returned from the black box"
#=> TypeError: Object returned from the black box does not respond to method 'each'!
7.aT_equal 8
#=> TypeError: 7:fixnum must be equal to the prescribed value (8:fixnum)!

您可以在 中自行查找更多这些方法YSupport,如果您遗漏了什么,欢迎您贡献。

作为这篇文章的后记,如果你习惯了ActiveSupport's 的#present?方法,它的运行时断言YSupport是:

[].aT_present "supplied array"
#=> TypeError: Supplied array not present!
于 2013-11-01T07:16:17.977 回答