【发布时间】:2013-10-22 14:03:38
【问题描述】:
我正在尝试编写一个 DSL 来包装 Mongoid 的聚合管道(即 Mongo DB)。
我制作了一个模块,当包含该模块时,它会添加一个接受块的类方法,然后将块传递给将请求传递给 Mongoid 的对象(通过缺少方法)。
所以我可以这样做:
class Project
include MongoidAggregationHelper
end
result = Project.pipeline do
match dept_id: 1
end
#...works!
“match”是Mongoid聚合管道上的一个方法,被拦截并传递。
但是在块外设置的实例变量不可用,因为它是在代理类的上下文中执行的。
dept_id = 1
result = Project.pipeline do
match dept_id: dept_id
end
#...fails, dept_id not found :(
有什么方法可以在块中传递/重新定义外部实例变量?
以下是修剪后的代码:
module MongoidAggregationHelper
def self.included base
base.extend ClassMethods
end
module ClassMethods
def pipeline &block
p = Pipeline.new self
p.instance_eval &block
return p.execute
end
end
class Pipeline
attr_accessor :cmds, :mongoid_class
def initialize klass
self.mongoid_class = klass
end
def method_missing name, opts={}
#...proxy to mongoid...
end
def execute
#...execute pipeline, return the results...
end
end
end
【问题讨论】:
-
你能试试
def pipeline(*args, &block)和Project.pipeline dept_id: dept_id do吗? -
好建议@MrYoshiji,在生产代码中我这样做并且它有效。但是,我想避免将变量作为选项散列传递,如果有什么可以使用的,请使用先前声明的变量。
-
我发布了另一个答案
-
嗨 juwiley,我在 Mongoid 中没有找到
match方法。你能告诉我你在哪里找到这个方法吗? -
@Kuldeep 深埋在 Mongoid 驱动程序中。这就是编写此包装器的基本原理,有一天 Mongoid 将/应该以更清洁的方式公开 API。你可以通过 YourModel.collection.aggregate
标签: ruby-on-rails ruby dsl instance-variables proc