Ruby语法'{:age.gt => 60}',它是如何工作的?

时间:2012-05-26 17:11:36

标签: ruby mongoid

我想知道这种语法{:age.gt => 60},我从mongoid找到了这种语法。它是如何工作的?我正在检查mongoid的源代码,它没有扩展Symbol类,并且有一个matchers目录,其中包含gt.rb,lt.rb,....这些文件用于条件逻辑:大于,小于......我无法理解它与Symbol类的关系。

在普通的irb会话中,它会显示错误:

NoMethodError: undefined method `gt' for :age:Symbol

有人能解释我吗?

4 个答案:

答案 0 :(得分:3)

这是由mongoid本身作为this symbol inflections fileMongoid::Criterion::Complex的一部分来完成的。奇怪的是,这个文件在主分支中不再存在,但我在我的项目中使用2.4.7并且它存在(它可能只是移动了但我无法在master中找到它)。

非常有趣的魔法。魔术我不会考虑所有必要的,:field => { :$gt => 5 }看起来对我好,但无论如何:)

答案 1 :(得分:2)

请参阅@ rfunduk对当前发布的2.4.10版本的回答。

在主分支中,它已经改变了。您现在可以在origin库中找到mongoid所需的内容:

https://github.com/mongoid/origin/blob/master/lib/origin/extensions/symbol.rb,特别是这种方法:

module Origin
  module Extensions
    module Symbol
      # ...
      module ClassMethods
        # Adds a method on symbol as a convenience for the MongoDB operator.
        #
        # @example Add the $in method.
        #   Symbol.add_key(:in, "$in")
        #
        # @param [ Symbol ] name The name of the method.
        # @param [ Symbol ] strategy The name of the merge strategy.
        # @param [ String ] operator The MongoDB operator.
        # @param [ String ] additional The additional MongoDB operator.
        #
        # @since 1.0.0
        def add_key(name, strategy, operator, additional = nil, &block)
          define_method(name) do
            method = "__#{strategy}__".to_sym
            Key.new(self, method, operator, additional, &block)
          end
        end

        # ...
      end
    end
  end
end

它根据主gt库中列出的匹配器添加gtemongoid等方法(请参阅strategies.rb文件和matchers/文件夹)。

答案 2 :(得分:2)

相关代码看起来像hereMongoid::Extensions::Symbol::Inflections)。有时使用Tracer

在运行时深入研究这些内容是最容易的
require 'tracer'
require 'mongoid'

Tracer.on {
  :test.gt
}

输出

#0:(irb):9:Object:-: -
#0:(eval):1:Mongoid::Extensions::Symbol::Inflections:>: -
#0:(eval):2:Mongoid::Extensions::Symbol::Inflections:-: -
#0:/home/abe/.rvm/gems/ruby-1.9.3-p125@deleteme/gems/mongoid-2.4.10/lib/mongoid/criterion/complex.rb:21:Mongoid::Criterion::Complex:>:       def initialize(opts = {})
#0:/home/abe/.rvm/gems/ruby-1.9.3-p125@deleteme/gems/mongoid-2.4.10/lib/mongoid/criterion/complex.rb:22:Mongoid::Criterion::Complex:-:         @key, @operator = opts[:key], opts[:operator]
#0:/home/abe/.rvm/gems/ruby-1.9.3-p125@deleteme/gems/mongoid-2.4.10/lib/mongoid/criterion/complex.rb:23:Mongoid::Criterion::Complex:<:       end
#0:(eval):3:Mongoid::Extensions::Symbol::Inflections:<: -

答案 3 :(得分:0)

继续寻找......

...定义范围DSL的方法

  • 使用方法
  • 直接修补SymbolObject
  • 添加method_missing并解析名称