如何验证传递给Ruby中方法的函数?

时间:2009-10-11 21:32:28

标签: ruby parameters methods

我正在编写一个库来对Ruby中的字节进行人性化处理(例如,将字节数1025转换为字符串1.1K),而且我仍然停留在设计的一个元素上。

计划是使用Numeric方法扩展humanize,该方法在数字上调用时返回人性化的字符串。在查看Number::Bytes::Human(我喜欢的Perl模块)的源代码后,我决定为该方法添加两个选项:一个使用1000个字节块,另一个使用floor默认舍入函数比ceil

为了最大限度地灵活,方法的定义使用参数的哈希,以便用户可以更改其中一个或两个选项。如果未传递任何参数,则使用默认哈希。这给了我这样的东西:

def humanize(params = {})
  params = {:block => 1024, :r_func => lambda }.merge params
  # yada yada
end

理想情况下,我想让用户将函数作为params[:r_func]的值传递,但我无法弄清楚如何验证它是ceil还是floor。因为我无法理解这一点,所以我最终做了以下事情,感觉非常笨拙:

  def humanize(params = {})
    params = {:block => 1024, :r_func => 'ceil' }.merge params
    if params[:r_func].eql? 'ceil'
      params[:r_func] = lambda { |x| x.ceil }
    elsif params[:r_func].eql? 'floor'
      params[:r_func] = lambda { |x| x.floor }
    else 
      raise BadRound, "Rounding method must be 'ceil' or 'floor'."
    end
    # blah blah blah
  end

如果有人知道偷看Ruby lambda包含的方法的技巧,我很乐意听到它。 (我也很高兴听到任何其他设计建议。)谢谢。

3 个答案:

答案 0 :(得分:7)

没有理由让用户通过一个方法,如果你将成为他们被允许传递的严厉(你知道除了天花板和地板之外还有other rounding schemes,对吗?)

如果您想将用户限制在天花板和地板上,只需允许它们传递符号:ceiling:floor。更灵活的设计是允许该方法采用一个块接收一个参数,要舍入的数字。然后用户可以使用他们喜欢的任何舍入算法,包括自定义算法。

顺便说一下,Numeric#humanize属于那种具有如此流行名称的monkeypatches类别,除了一个小的个人项目之外,你可能会遇到名称空间冲突(并产生微妙的错误)。

答案 1 :(得分:3)

如果你不打算实际调用这个东西,我没有看到调用者传递lambda的任何意义。把它变成符号,你可以做类似的事情:

raise BadRound, "Rounding method must be :ceil or :floor." unless [:ceil, :floor].include? params[:r_func]
op = lambda {|x| x.send params[:r_func]}
# blah blah blah

答案 2 :(得分:2)

为什么让它们传递函数指针而不是布尔值?这样就可以避免必须验证函数的问题。