我有这个问题,我不能在块中使用重载运算符,而不是使用重载运算符,它使用ruby默认运算符并返回:
ArgumentError: comparison of String with 25 failed
用例允许将类用作:
Query.where { age > 25 }
作为一个通知,不要介意下面的method_missing
方法,在这个上下文中,它仅用于抛出上面提到的错误消息,这里的代码如下:
class Query
class << self
def > arg
"> #{arg.to_s}"
end
def method_missing meth, *args, &block
"#{meth.to_s} #{args.first.to_s}"
end
def where &block
"SELECT * FROM table WHERE #{class_eval &block}"
end
end
end
如果我在块中添加self
,则重载的运算符运行正常:
Query.where { age self > 25 }
=> "SELECT * FROM table WHERE age > 25"
取出self
,会返回此错误:
Query.where { age > 25 }
=> ArgumentError: comparison of String with 25 failed
答案 0 :(得分:2)
您的问题是method_missing
:
def method_missing meth, *args, &block
"#{meth.to_s} #{args.first.to_s}"
end
在调用age
时返回一个字符串。这意味着您的阻止:
{ age > 25 }
看起来像这样:
{ 'age' > 25 }
在调用method_missing
来处理age
电话后。这是你的ArgumentError
。
您需要method_missing
以正确的字符串形式和的方式返回知道如何回复>
的内容。例如:
class Query
class Wrapper
def initialize str
@str = str
end
def > arg
@str += "> #{arg.to_s}"
end
def to_s
@str
end
end
class << self
def method_missing meth, *args, &block
Wrapper.new("#{meth.to_s} #{args.first.to_s}")
end
def where &block
"SELECT * FROM table WHERE #{class_eval &block}"
end
end
end
这将使Query.where { age > 25 }
按照您希望的方式运行。当你拨打where
时,这仍然会给你留下一个不可束缚的字符串(即Query.where { age > 25 }.where { pancakes < 11 }
之类的东西不起作用)但是扩展Query
以涵盖这些事情应该会更容易正确的地方。
答案 1 :(得分:1)
在这种情况下:
Query.where { age self > 25 }
对象self
是Query
对象,因此它使用您定义的运算符。
但是,在这种情况下:
Query.where { age > 25 }
age
和25
都不是Query
个对象,因此它不会使用Query
中的运算符
答案 2 :(得分:0)
Query.where {age self > 25}
发生了这种情况:
class_eval {age self > 25}
=> class_eval {age Query > 25}
=> class_eval {age Query.>(25)}
=> class_eval {age "> #{25.to_s}"}
=> class_eval {age "> 25"}
=> method_missing(age, ["> 25"])
=> "#{age.to_s} #{["> 25"].first.to_s}"
=> "age > 25"
我们拥有Query.where {age > 25}
:
class_eval {age > 25}
会引发错误,因为age
被认为是v
的接收者。
您可以将Query.where { age > 25 }
更改为Query.where { age "> 25" }
并删除'Query#>'
方法。您可能不需要某些to_s
。