Kernel#eval
我们已经知道instance_eval和class_eval,现在接触*eval的第三个成员——eval方法。eval方法会直接执行代码字符串。
array = [10, 20]
element = 30
eval("array << element") # => [10, 20, 30]
heredoc字符串语法
使用«开头,后面紧跟结束序列(在这里是end_eval),在此之后在下一个end_eval之前,都是定义的字符序列。
POSSIBLE_VERBS = ['get','put']
POSSIBLE_VERBS.each do |m|
eval <<-end_eval
def #{m} (path, *args, &b)
r[path].#{m} (*args, &b)
end
end_eval
end
这里会定义get和put两个方法,并且转发给r[path]的get和put。
绑定对象
我们可以通过创建Binding方法来捕获并带走当前的作用域,然后给eval传一个Binding对象就可以在它的作用域中执行代码
class MyClass
def my_method
@x = 1
binding
end
end
b = MyClass.new.my_method # => 这里的b就是Binding对象
eval "@x",b # => 1
eval方法的问题
eval可能会导致代码注入的问题,因为不会检查代码字符串的内容。在Ruby中提供了安全级别的特性,可以创建一个沙盒环境,在不同的级别下提供不同的安全环境。
钩子方法
钩子方法可以捕捉类继承、模块混入类、定义方法等事件,类似一个触发器。
在Ruby中提供了很多钩子方法
module M1
def self.included(othermod)
puts "M1 was included into #{othermod}"
end
end
class C
include M1 # => 'M1 was included into C'
end
水水的结尾
这一章主要是一个利用动态方法、扁平作用域、类宏、钩子方法等完成一个增加了参数检验的attr_accessor关键字。新内容并不多,写完这个笔记后应该将之前所学的东西都回顾一下,巩固一下这些魔法~~