将争论变成接收者

时间:2012-10-07 10:44:04

标签: ruby

我创建了以下扩展程序

class String
  def is_a_number? s  # check if string is either an INT or a FLOAT (12, 12.2, 12.23 would return true)
    s.to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) == nil ? false : true
  end
end

如何使其作为链式方法工作?

is_a_number?("10") # returns true
"10".is_a_number? # returns an error (missing arguments)

更新

感谢sawa,mikej和Ramon的回答。正如所建议的那样,我将类更改为Object并删除了参数:

class Object
  def is_a_number?  # check if string is either an INT or a FLOAT (12, 12.2, 12.23 would return true)
    to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/) != nil
  end
end

它现在完美无缺:

23.23.is_a_number? # > true

谢谢你们......

2 个答案:

答案 0 :(得分:2)

当您编写"10".is_a_number?时,您已经拥有了要检查的对象"10",这是is_a_number?的接收者,因此您的方法不需要采用任何参数。

由于matchString上的实例方法,因此您无需为其指定接收器。它只会在调用is_a_number?的同一对象上运行。因为您知道自己已有String个对象,所以也不需要to_s

只需将其写为:

class String
  # check if string is either an INT or a FLOAT (12, 12.2, 12.23 would return true)
  def is_a_number? 
    match(/\A[+-]?\d+?(\.\d+)?\Z/) != nil
  end
end

Ramon's如果您不知道您正在测试的对象是否正在进行,那么您可能希望将扩展程序放在Object而不是String上是一个好点成为一个字符串。


此外,您所描述的并不是方法链接的真正含义;它只是在一个对象上调用一个方法。方法链接是设置返回类型的方法,以便可以按顺序调用多个方法,例如在Rails中,类似

User.where(:name => 'Mike').limit(3) # find the first 3 Mikes

是方法链的一个例子。

答案 1 :(得分:1)

您似乎想要修补Object而不是String(因为您正在调用to_s):

class Object
  def is_a_number?
    to_s.match(/\A[+-]?\d+?(\.\d+)?\Z/).nil?
  end
end

您还可以在模型上使用validates numericality: true替换它。