0

我有这个问题,我不能在块内使用重载运算符,而不是使用重载运算符,它使用 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
4

3 回答 3

2

你的问题是你的method_missing

def method_missing meth, *args, &block
  "#{meth.to_s} #{args.first.to_s}"
end

调用时返回一个字符串age。这意味着你的块:

{ age > 25 }

看起来像这样:

{ 'age' > 25 }

aftermethod_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既然事情在正确的位置,扩展以涵盖这些事情应该会更容易。

于 2013-11-06T18:56:38.320 回答
1

在这种情况下:

Query.where { age self > 25 }

该对象self是一个Query对象,因此它使用您定义的运算符。但是,在这种情况下:

Query.where { age > 25 }

对象也不是,age所以它不会使用操作符 from25QueryQuery

于 2013-11-06T17:42:03.120 回答
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's。

于 2013-11-06T21:33:25.327 回答