gpt4 book ai didi

ruby-on-rails - 基于实例 eval 将实例变量传递给 DSL

转载 作者:太空宇宙 更新时间:2023-11-03 16:03:28 24 4
gpt4 key购买 nike

我正在尝试编写一个 DSL 来包装 Mongoid 的聚合管道(即 Mongo DB)。

我制作了一个模块,当包含该模块时,它会添加一个接受 block 的类方法,它将 block 交给一个对象,该对象将请求传递给 Mongoid(通过缺少方法)。

所以我可以这样做:

class Project
include MongoidAggregationHelper
end

result = Project.pipeline do
match dept_id: 1
end

#...works!

“match”是Mongoid聚合管道上的一个方法,被拦截并传递。

但是在 block 外设置的实例变量不可用,因为它是在代理类的上下文中执行的。

dept_id = 1

result = Project.pipeline do
match dept_id: dept_id
end

#...fails, dept_id not found :(

有什么方法可以在 block 中传递/重新定义外部实例变量?

下面是修剪后的代码:

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

最佳答案

您可以执行以下操作:(无限数量的参数,有点必须使用哈希)

# definition
def pipeline(*args, &block)
# your logic here
end

# usage
dept_id = 1
result = Project.pipeline(dept_id: dept_id) do
match dept_id: dept_id
end

或者您可以使用命名参数,如果您知道执行 DSL 需要多少个参数:

# definition
def pipeline(dept_id, needed_variable, default_variable = false, &block)
# your logic here
end

# usage
dept_id = 1
result = Project.pipeline(dept_id, other_variable) do
match dept_id: dept_id
end

关于ruby-on-rails - 基于实例 eval 将实例变量传递给 DSL,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19520116/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com