Ruby 中的上下文绑定 ( Context Binding )

yufei       6 年, 3 月 前       2483

不管怎么样。今天介绍完 Ruby 的知识后,可能有一段时间不能继续介绍了。真的是...快腻烦了...

这周,发生了很多重大的事情,比如滴滴...一下子心情就不好了...

算了,我们还是继续了技术吧。

本章节我们将要介绍的是 Ruby 中的上下文绑定 ( Context Binding ) 。我们将会介绍以下几个知识点

  1. Binding
  2. TOPLEVEL_BINDING 全局常量
  3. ERB 模板

Binding 类

Binding 类的实例一般用于封装接收器对象的 「 执行上下文 」 ( execution context )

执行上下文是指 「 给定代码段执行所需的整个环境 」。没有执行上下文的代码无法正确执行

执行上下文包括给定作用域范围内的变量、方法和 self 关键字

实际上,执行上下文比这还更复杂一点。无论如何,让我们保持简单,因为它不是本文的主题。

如果有空,我们将在额外的其它章节中详述这个关键概念

Binding 类不能公开实例化,因为它的 new 方法在 Binding 类初始化时是未定义状态。

因此,只能通过 Kernel#binding 方法在内部实例化此类

class Context

  def get_binding
    binding
  end

end

Binding.new         # => NoMethodError: (undefined method `new' for Binding)
Context.new.get_binding # => #<Binding:0x00007f7fda063130>

因为 Kernel#binding 方法是私有的,我们只能再定义一个方法 Context#get_binding,并通过该方法从外部作用域访问 Context 类的内部 binding 方法

而我们的 Context 类的真正目的是: 封装执行上下文并能够从另一个执行上下文访问它

这段话可能有点让人难以理解,不管怎样,我们将在接下来的两节中详细介绍两个具体的例子。

TOPLEVEL_BINDING 全局常量

main 对象是最顶级范围。 Ruby 中的任何对象都至少需要在此作用域范围内被实例化

为了随时随地地访问 main 对象的上下文,Ruby 提供了一个名为 TOPLEVEL_BINDING 的全局常量

@a = 1

class Addition
  def add
    TOPLEVEL_BINDING.eval("@a += 1")
  end
end

Addition.new.add

p TOPLEVEL_BINDING.receiver # => main
p @a                        # => 2

上面这段代码中,Binding#receiver 方法返回 Kernel#binding 消息的接收者。为此,则保存了调用执行上下文 - 在我们的示例中,是 main 对象。

然后我们在 Addition 类的实例中使用 TOPLEVEL_BINDING 全局常量访问全局的 @a 变量

ERB 模板

我们通过你可能熟悉的 Ruby on Rails 中的 ERB 模板来分析 Binding 的用法

app/controllers/users_controller.rb 文件中

class UsersController < ApplicationController
  def show
    @user = "Mickael"
  end
end

而在 app/views/users/show.html.erb

Hi <%= @user %>!

在上面这两个 Ruby on Rails 文件中,show.html.erb 模板可以访问 UsersController 类中的 @user 实例变量

这是如何做到的 ? 这背后的机制又是什么 ?

真相就是,ERB 类提供了一个 result 方法,该方法使用 Binding 类的实例作为参数

下面,让我们以更加手动的方式重新实现上一个示例,以使你了解背后发生的事情

class UsersController < ApplicationController
  def show
    @user = "Mickael"
    erb = ERB.new "Hi <%= @user %>!"

    puts erb.result(binding) # => Hi Mickael!
  end
end

是不是很简单 ?

在这个示例中,ERB 实例可以通过 ERB#result 方法的参数传递的 Bind 类的实例访问UsersController 实例中定义的 @user 变量

目前尚无回复
简单教程 = 简单教程,简单编程
简单教程 是一个关于技术和学习的地方
现在注册
已注册用户请 登入
关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.