Rails 作为一个 MVC 框架,其核心包括三个模块:ActiveRecord,ActionController 和
ActionView。今天这篇博文的主角是 ActionView,解开模板系统的魔术。通常情況下,通过 scaffold
已经能够建立简单的、包含CRUD基本功能的页面,完全不需要手动修改 view 的代码。即使不使用 scaffold ,Rails
也提供了众多的辅助方法,创造一个功能丰富的动态页面简直是易如反掌。但是,会用不代表深入理解,最近有朋友问我这些问题:
- 为什么编辑一个对象需要在 Controller 创造一个实例变量
- View 通过什么方式访问这些实例变量的
- 那么多表单辅助方法,都是需要提供 object_name, method 两个参数,怎么就变成实例变量的值了
相信大部分的 Rails 程序员手边的书都是《Agile Web Development with
Rails》,书中提到这一点的时候一笔带过,只是说 Rails 在这里用了一个小魔术。这里,我们就来揭开这个魔术吧!
Part 1. Template Files – 模板文件
当一个 action 需要返回一段 html
片段的时候,我们需要建立一个模板文件。根据不同的版本、请求类型,模板文件的文件名也各不相同,从早期版本的 action_name.rhtml
,到现在的 action_name.text.html.erb ,以及扩展的 rjs,在扩展名中都包含了一个关键字:r / erb。它就是
Rails 模板系统的关键:ERb。
Part 2. ERb – Ruby Templating
ERb – 嵌入式 Ruby (http://ruby-doc.org/stdlib/libdoc/erb/rdoc/index.html
),是 Ruby 语言提供的一个基本扩展。它支持在字符串中嵌入 ruby
代码片段。看上去似乎很神秘,其实我们每天都用到,下面这种形式一定不陌生吧?
<h1><%= @user.name %></h1>
没错,正是因为 ERb 的存在,使得模板中可以动态地引用对象的属性。
Part 3. Instance Variables of Ruby – Ruby 的实例变量
让我们回顾一下 Ruby 语言的基本要素之一:实例变量。通常我们通过
@time = Time.now
的形式创造一个实例变量。这里我们不重新解释对于“实例变量”的定义,但是必须牢记一点,正如字面所见,实例变量的作用域是当前实例内,也就是说,
只有在实例的内部,才可以直接对实例变量进行读写操作(扩展的访问子方法等等不在讨论范围之内)。那么,为什么 Rails Controller
里创建的实例变量能够在 View 里面访问呢,不是自相矛盾吗?
Ruby 作为一种动态语言,因为其“开放”的特点,使很多原本不可能的编程模式变为可能。比如,通过 Open Class
的特性,你可以动态的为对象注入新的方法定义,或者改写方法的逻辑,或者,通过不同的方法可以在对象的外部访问对象的内部的实例变量。经常使用
console 的朋友可能会了解其中的一种方式:Object#instance_variable_get /
Object#instance_variable_set 方法。举个简单的例子:
class User
def initialize( name )
@name = name
end
end
user = User.new( "Jack" )
user.name #=> raise NoMethodError
user.instance_variable_get('@name') #=> "Jack"
user.instance_variable_set('@name', 'Tom')
user.instance_variable_get('@name') #=> "Tom"
可以看到,在没有任何访问子的情况下,我们用这种方式对一个实例变量进行读写操作。
除了这种简单的方式,还有另外一种进阶的方式,也是 ERb 常用的一种方式:Binding
Part 4. Binding
Binding (http://ruby-doc.org/core/classes/Binding.html
) 是 Ruby 语言的自身的一个特性,在任何对象内,self.binding 方法都会返回一个当前对象关联的 binding
实例。不精确的说,binding 对象可以理解成为当前对象的完整的上下文环境。文档中已经包含了一些示例代码,帮助大家理解 Binding
对象的作用。最重要的一点是:既然是当前对象的完整上下文环境,自然就包括了对象的实例变量。
那么 Binding 在 ERb 中扮演一个什么样的角色?是一个运行环境的提供者。
class Demo
def initialize(n)
@secret = n
end
def getBinding
return binding()
end
end
k1 = Demo.new(99)
b1 = k1.getBinding
k2 = Demo.new(-3)
b2 = k2.getBinding
eval("@secret", b1) #=> 99
eval("@secret", b2) #=> -3
eval("@secret") #=> nil
回到我们最初的问题,Rails 在 ActionView 中使用了什么样的魔法?答案就是 ERb 和 Binding。首先,获得当前实例的
binding,自然,binding 内也包括了实例变量;紧接着,ERb 允许将模板的内容动态地,绑定到另一个环境中运行。我们依然用刚才的
User 的例子来说明这一点:
# A simple template string
template = "Hello, "
user = User.new( "Jack" )
# Get binding
binder = user .send( :binding ) # calling a private method# Rendering template
puts ERB.new( "Hello, <%=@name%>").result( binder )
#=> "Helo, Jack"
puts ERB.new( "Hello,<%=@name%>").result
#=> "Helo, "
虽然例子不是非常恰当,但是足以展示 Binding 和 ERB 的用法。我们可以看到,ERB#result
方法将模板字符串绑定在另外一个环境中运行,而这个环境包含了我们创建的 @user 实例变量,因此,模板中的 @user.name
得到了正确的值。
这就是 ERB 的真面目,也是为什么在 ActionView 中能够访问到 Controller
里实例变量的原因。感叹一下动态语言的强大吧!以上只是非常粗糙的讲述ERB的使用,Rails 所做的魔法远不止如此,如果有兴趣,可以查看
Rails 源代码,对于深入学习 Rails 框架也有很大的好处。
最后,补充一下 ERB 的应用场景。虽然在普通的需求中,ActionView
所做的已经足够,但是某些情况还是需要创造独立的模板系统。比如某个场景,客户要求提供一个完全自定义的模板系统,这个时候 ERB
就大显身手了。只需要将数据源载入实例变量中,并且在使用手册里列出可以访问的方法,即使完全不懂 Ruby 语言也可以写出使用这套简单的模板系统了。
来自 http://blog.hozaka.com/?p=20
终于搞明白了 感谢我们的鸡蛋黄大哥(hozaka)的帮助!!!!!!!!!!!
分享到:
相关推荐
藏区特产销售平台--论文.zip
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
该单片机项目可作为课程设计和期末大作业或者毕设,项目完整,有原理图和代码,需要的自行下载即可!
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件太大放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载
文件放服务器下载,请务必到电脑端资源详情查看然后下载