self.class_eval<

时间:2009-06-10 04:55:10

标签: ruby

我正在尝试理解这个功能。

我可以看到属性和类型被传递给opal()方法。

只要type_nametypetypeSymbol就会从String获取其值。否则,name上会调用type方法。我想name方法类似于class方法来获取type参数的类。

self.class_eval之后我有点迷失,但我的猜测是,这可能会定义一个代码块,可以添加到self引用的类中。

这是如何工作的我不确定。

如果有人能解释self.class_eval << DEF之后发生的事情,我们将不胜感激。

    def opal(attr, type)
      self.ds "#{attr}_id"
      type_name = (type.is_a?(Symbol) || type.is_a?(String)) ? type : type.name
      self.class_eval <<DEF
  def #{attr}
    if defined?(@#{attr})
      @#{attr}
    else 
      @#{attr} = if self.#{attr}_id
          #{type_name}.get(self.#{attr}_id)
        else
          nil
        end
    end
  end

  def #{attr}=(value)
    self.#{attr}_id = value.key
    @#{attr} = value
  end
DEF
    end

2 个答案:

答案 0 :(得分:5)

<<DEFDEF之间的所有内容都只是一个字符串,#{ ... }可以像其他任何字符串一样处理该字符串。

class_eval将导致解释器在模块的上下文中运行字符串。

因此,如果您知道attrtype是什么,那么您可以找出正在运行的代码以向该类添加方法。

让我们说attr"foo"type"Bazzle"。正在运行的代码是:

def foo
  if defined?(@foo)
    @foo
  else 
    @foo = if self.foo_id
      Bazzle.get(self.foo_id)
    else
      nil
    end
  end
end

def foo=(value)
  self.foo_id = value.key
  @foo = value
end

答案 1 :(得分:3)

为了便于理解,让我们假设'attr'的值是'foo',这就是现在的样子:

self.class_eval <<DEF
  def foo
    if defined?(@foo) # Return the value of attr if it's defined
      @foo
    else 
      @foo = if self.foo_id
          #{type_name}.get(self.foo_id)
        else
          nil
        end
    end
  end

  def foo=(value) # Define setter
    self.foo_id = value.key
    @foo = value
  end
DEF

所以它只是为@foo定义一些getter和setter方法,并在类级别进行评估。