Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 带有自定义定义上下文的实例\u eval_Ruby_Class Eval_Instance Eval - Fatal编程技术网

Ruby 带有自定义定义上下文的实例\u eval

Ruby 带有自定义定义上下文的实例\u eval,ruby,class-eval,instance-eval,Ruby,Class Eval,Instance Eval,我试图为已经存在的lib创建DSL定制,我对Ruby块上下文有一些误解 假设我们有一个保存为proc的块 some_block = Proc.new do def testing; end puts self.inspect if self.kind_of? Class puts self.instance_methods.include? :testing else puts self.methods.include? :testing e

我试图为已经存在的lib创建DSL定制,我对Ruby块上下文有一些误解

假设我们有一个保存为proc的块

some_block = Proc.new do 
   def testing; end
   puts self.inspect
   if self.kind_of? Class 
     puts self.instance_methods.include? :testing
   else
     puts self.methods.include? :testing
   end
   puts self.singleton_class.instance_methods.include? :testing
   implicit_calling_context
end

def implicit_calling_context
  "implicit calling context is definition context"
end
当我们简单地产生一个块时,这个块的自身上下文不会改变

class N
  def some_method
    yield
  end
  def self.implicit_calling_context
    puts "implicit calling context is N"
  end

  def implicit_calling_context
    puts "implicit calling context is N instance"
  end
end

N.new.some_method &some_block
# => main       # block self context stays definition one (closure) 
#    false
#    false
#    implicit calling context is definition context
当我们打电话时

N.class_eval &some_block

# => N         # block self context changed to N
#  true        # block definition context became N
#  false
#  implicit calling context is N
此块中的self变为N,默认的definee保持不变

当我们调用instance_eval on instance时

N.new.instance_eval &some_block
# => #<N:0x007fc0422294f8>
#    true
#    true
#    implicit calling context is N instance
N.new.instance\u eval和一些块
# => #
#真的
#真的
#隐式调用上下文是N个实例
某些_块中的self-context会切换到N个实例,但默认的definee会变成N个实例元类

在实例上下文和其他地方的代理定义者上下文中是否有任何方便的方法来生成块

例如,我有一个Delegator实例,其中包含一些类,我想将definee上下文代理给它:

class Definee
end

class MyDelegator < SimpleDelegator
  def work *args
     puts "some additional work"
     __getobj__.work *args
  end
end

MyDelegator.new(Definee).instance_eval do
  work "some base work"
  def test_my_work
     "should be defined on Definee"
  end
end

# I expecting that test_my_work should be defined as Definee instance method
# and :work should be called on MyDelegator.new(Definee) instance
# with "some base work" arg.
类定义者
结束
类MyDelegator
所以Definee已经实现了DSL,我用instance_eval来描述它,但是定义上下文是不正确的。类_eval将被委托给Definee,并且不会调用MyDelegator的任何方法,所以它也不会解决问题

也许有更优雅的方式来做这样的事情。有什么想法吗

编辑:

使用从模块继承的类作为委托器,解决了定义上下文切换的问题

class Definee
end

class MyDelegator < Module
  def initialize definee, &block
    @definee = definee
    self.class_eval &block
    @definee.include self
  end
  def work *args
    puts "some additional work"
    @definee.work *args
  end

  def method_missing *args, &block
    @definee.send *args, &block
  end
end

MyDelegator.new(Definee) do
  work "some base work"
  def test_my_work
     "should be defined on Definee"
  end
end
类定义者
结束
类MyDelegator<模块
def初始化定义对象(&block)
@被定义者
自我等级评估和闭塞
@包括自己
结束
def work*参数
把“一些额外的工作”
@definee.work*args
结束
def方法_缺少*参数和块(&block)
@definee.send*args和block
结束
结束
MyDelegator.new(Definee)do
做“一些基础工作”
def测试我的工作
“应在定义对象上定义”
结束
结束

什么?你能展示一下你想要完成什么而不是让我们都困惑吗?我正在尝试代理DSL调用和在DSL范围内声明的方法定义(看最后一个代码块)。好吧,我也有点困惑地问这样一个奇怪的问题,只是想弄清楚ruby是如何切换上下文的。ykatz对此有一个很好的话题,但对我来说这个话题还不清楚。如果你能帮忙,那就太好了=|实际的DSL应该是什么样子的?我认为你太关心技术方面的问题了。退一步,从更高的层次看一看。好吧,我解决了我的问题,只需在从模块继承的类上使用class_eval,方法_缺少定义(而不是delegator实例),并将其包含到Definee类中。