新手问题 一个 sinatra 源码中遇到的语法

biaobiaoqi · 2014年01月04日 · 最后由 biaobiaoqi 回复于 2014年01月07日 · 2845 次阅读

刚开始学 Ruby,找了 sinatra 源码在读(原因是觉得它比较短-,-) 在它的 module Helpers 中又一个方法,按照它的注释,大概能知道它的内容,不过没读懂其中的一句语法。

# Set or retrieve the response body. When a block is given,
# evaluation is deferred until the body is read with #each.
def body(value = nil, &block)
  if block_given?
    def block.each; yield(call) end
    response.body = block
  elsif value
    headers.delete 'Content-Length' unless request.head? || value.is_a?(Rack::File) || value.is_a?(Stream)
    response.body = value
  else
    response.body
  end
end

请教其中 的 block.each 如何理解?

刚又仔细想了一下整理下现在的思路是:

1.是不是给 block 这个 Proc 中定义一个叫 each 的方法? 2.如果 1 成立,那么方法中的 yield(call) 代表着需要向 each 这个方法传入一个 block 而且在调用这个 block 的时候有 call?

再继续看代码。。

看过 rack 没,由于需要 each 方法,给 block 加一个 engine 方法,可以这么认为,each == block call

#1 楼 @hhuai 谢谢~

真的好面向对象,原来 Proc 也可以由方法!不过还是没太明白你的意思。有不少疑问,我列一下吧

1.engine 方法是指?另外 each ==block call 也不太理解额。

2.源代码里 def block.each; yield(call) end 这个 yield 的参数 call 哪里来的呢?

3.这里将 body 赋值为一个 block,是在哪种情况下出现的啊?body 不是数据么?

看了下 response.rb 的代码,相关的应该是这一块了:

def each(&callback)
  @body.each(&callback)
  @writer = callback
  @block.call(self)  if @block
end

evaluation is deferred until the body is read with #each.

指的就是这个 each 调用吧?

在源码里面跟踪这几个方法的调用真的很麻烦啊,方法名这么普通常见的 each body……。><... 不知道这个 each 的调用参数里的 &callback 是些什么东西。好头大

  1. 在 rack 中 body 需要有 each 方法

2.

def block.each; yield(call) end

你要知道作用域是啥

  1. 参考 1

#2 楼 @biaobiaoqi 看了一下你的问题,你需要补一下基础,再来看源码,不然很累。

#4 楼 @hhuai 恩啦,之前是边看源码,不懂再查的。 先扫一遍语法再说啦。

#3 楼 @Ddl1st 多谢各位啦

  • &将 block 块转换成 proc 对象
  • def block.each 定义了一个单件方法,接收者是上一步的 proc 对象
  • yield(call) 中 call,接收者 self 是 proc 对象,proc 对象中的 call 方法返回这个可执行对象的结果
  • yield 将这个结果传递给外部块的第一个参数

* response.body=block 这句指明了上一步的外部块是 rack 中间件或服务器中传入的,因为 rack 标准中规定 body 要响应 body.each{外部块}

综上,sinatra 的 body 扩展了 rack 的 body,不仅能 each 静态编码,还能 each 动态内容,通过的代码块的延后执行 @biaobiaoqi,新手不建议先看 sinatra

#6 楼 @chq 多谢指导!!! 确实看得有点云里雾里的,咬牙看了一半,慢慢查各种语法。。 最近已经回归到先看完 the ruby programming language 了。 请教下,做 sinatra 的开发有什么比较好的范例可以看看源码的么?我在 github 以及 ruby-china 搜了下,没太多斩获。

多谢=)

需要 登录 后方可回复, 如果你还没有账号请 注册新账号