我是Ruby的新手,在同样的代码上被卡住了。我纠结的部分比我在这里找到的一些答案更基本。这可能会也可能不会帮助到某些人。
respond_to是超类ActionController上的一个方法。
它需要一个block,就像一个委托。块从do到end,以|格式|作为块的参数。
respond_to执行你的块,将Responder传递到format参数中。
http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html
Responder不包含.html或.json的方法,但我们无论如何都会调用这些方法!这部分让我大吃一惊。
Ruby有一个叫做method_missing的特性。如果你调用一个不存在的方法(如json或html), Ruby会转而调用method_missing方法。
http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html
Responder类使用method_missing作为一种注册。当我们调用'json'时,我们告诉它通过序列化到json来响应带有.json扩展名的请求。我们需要不带参数地调用html,告诉它以默认方式(使用约定和视图)处理.html请求。
它可以这样写(使用类似js的伪代码):
// get an instance to a responder from the base class
var format = get_responder()
// register html to render in the default way
// (by way of the views and conventions)
format.register('html')
// register json as well. the argument to .json is the second
// argument to method_missing ('json' is the first), which contains
// optional ways to configure the response. In this case, serialize as json.
format.register('json', renderOptions)
This part confused the heck out of me. I still find it unintuitive. Ruby seems to use this technique quite a bit. The entire class (responder) becomes the method implementation. In order to leverage method_missing, we need an instance of the class, so we're obliged to pass a callback into which they pass the method-like object. For someone who has coded in C-like languages for 20 some years, this is very backwards and unintuitive to me. Not that it's bad! But it's something a lot of people with that kind of background need to get their head around, and I think might be what the OP was after.
附注:在RoR 4.2中respond_to被提取到responders gem中。