【问题标题】:Passing instance variables to DSL based on instance eval基于实例 eval 将实例变量传递给 DSL
【发布时间】: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


【解决方案1】:

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

# 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

【讨论】:

  • 希望我可以无缝地做到这一点而不必传递任何东西,但看起来不可能
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-25
  • 2021-08-20
  • 2014-09-15
  • 2018-09-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多