Ruby 《Ruby 元编程》读书笔记 (十二)

lazybios · 2015年09月19日 · 最后由 lazybios 回复于 2016年06月26日 · 1961 次阅读

博客地址 :《Ruby 元编程》读书笔记 (十二)

相关文章:

《Ruby 元编程》读书笔记 (一) 《Ruby 元编程》读书笔记 (二) 《Ruby 元编程》读书笔记 (三) 《Ruby 元编程》读书笔记 (四) 《Ruby 元编程》读书笔记 (五) 《Ruby 元编程》读书笔记 (六) 《Ruby 元编程》读书笔记 (七) 《Ruby 元编程》读书笔记 (八) 《Ruby 元编程》读书笔记 (九) 《Ruby 元编程》读书笔记 (十) 《Ruby 元编程》读书笔记 (十一)

传神的头图↓↓↓

Ruby元编程

Kernal#eval 方法

Kernal#eval 方法与之前的 BasicObject#instance_eval 和 Module#class_eval 一样,都属于*eval 家族,都可以赋予程序在运行中进行动态变化的能力。与后两者想比 Kernal#eval 更加直接,不需要代码块、直接就可以执行字符串代码 (String of Code)。

PS:BasicObject#instance_eval 也是可以执行字符串代码的。

示例代码

array = [10, 20]
element = 30
eval(array << element)  #=> [10, 20, 30]
array.instance_eval "self << element"  #=> [10, 20, 30]

Here 文档 (Here documents)

以<<打头,后面跟一个 “结束序列标识”,之后就可以是正式的文档内容了,可以任意换行,直到遇到了独立出现的” 结束序号标识”。

puts <<GROCERY_LIST
Grocery list
------------
1. Salad mix.
2. Strawberries.*
3. Cereal.
4. Milk.*

* Organic
GROCERY_LIST

上面代码的输出格式如下:

Grocery list
------------
1. Salad mix.
2. Strawberries.*
3. Cereal.
4. Milk.*

* Organic
=> nil

绑定对象

Binding 是一个用对象标识的完整作用域 (上下文环境)。可以通过创建 Binding 对象来捕获并带走当前的作用域。之后,通过 eval 方法在这个 Binding 对象所携带的作用域内执行代码。

使用 Kernel#binding 方法可以用来创建 Binding 对象

示例代码

class MyClass
    def my_method
        @x = 1
        binding
    end
end

b = MyClass.new.my_method
eval @x, b #=> 1

上面代码,在 MyClass 类中定义了一个 my_method 方法来返回一个当前的绑定。最后将这个返回的绑定,作为参数传递给 eval 方法。这样 “@x” 就可以在返回的绑定作用域中执行了。

关于绑定还有另外一个知识点,Ruby 还提供了一个名为 TOPLEVEL_BINDING 的预定义常量,表示顶级作用域 Binding 对象。该常量可以在程序的任何位置访问到。言外之意,你可以在程序的任何位置,通过 Kernal#eval 方法在顶级作用域中执行代码。

示例代码

class AnotherClass
    def my_method
        eval self, TOPLEVEL_BINDING
    end
end

AnotherClass.new.my_method  #=> main

代码注入

Kernal#eval 执行这样可以灵活执行字符串代码的特性,给编程带来了灵活性之外,也带来了潜在的风险,如果字符串代码来源于不可信的用户输入,如果不做安全检查,保不齐什么时候就会是一段破坏性的恶意代码。

面对这样的风险,可以选择规避 eval 的使用,换用其它相对安全的方式代替,例如动态方法动态派发。此外,还可以通过在 Ruby 中通过修改 $SAFE 全局变量值,来控制程序的安全性级别,具体就是在你要执行可信的字符串代码前,将安全级别降低,可以使用 Object#untaint 方法,执行完之后在切换安全级别。这有点像操作系统中使用临界资源的步骤 (请求锁,释放锁)

通过 Object#tainted?方法可以判断一个对象是不是被污染了(是否来自一个不可信的输入源)。

-待续-

=============== 最后贴一下自己的公众账号

可以十日不将军,不可一日不拱卒,日拱一卒 (rigongyizu365)

lazybios 《Ruby 元编程》读书笔记 (十六)[连载完结] 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十三) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十四) 中提及了此贴 06月26日 10:50
lazybios 《Ruby 元编程》读书笔记 (十五) 中提及了此贴 06月26日 10:50
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册