我正在尝试理解这个功能。
我可以看到属性和类型被传递给opal
()方法。
只要type_name
为type
或type
,Symbol
就会从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
答案 0 :(得分:5)
<<DEF
和DEF
之间的所有内容都只是一个字符串,#{ ... }
可以像其他任何字符串一样处理该字符串。
class_eval
将导致解释器在模块的上下文中运行字符串。
因此,如果您知道attr
和type
是什么,那么您可以找出正在运行的代码以向该类添加方法。
让我们说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方法,并在类级别进行评估。