我正在阅读Rails入门指南,并对第6.7节感到困惑。在生成一个脚手架之后,我在我的控制器中发现了以下自动生成的块:

def index
  @posts = Post.all

  respond_to do |format|
    format.html  # index.html.erb
    format.json  { render :json => @posts }
  end
end

我想了解respond_to块实际上是如何工作的。格式是什么类型的变量?是.html和.json方法的格式对象?的文档

ActionController:: MimeResponds::类方法::respond_to

没有回答问题。


当前回答

这是一段利用Rails helper方法的Ruby代码。如果你还不熟悉block,你会在Ruby中看到很多。

respond_to是一个附加到Controller类(或者更确切地说,它的超类)的Rails助手方法。它引用将发送到视图(将发送到浏览器)的响应。

示例中的块正在格式化数据——通过在块中传入一个“format”参数——当浏览器请求html或json数据时,这些数据将从控制器发送到视图。

如果你在你的本地机器上,你已经设置了Post脚手架,你可以访问http://localhost:3000/posts,你会看到你所有的文章都是html格式的。但是,如果你输入这个:http://localhost:3000/posts.json,那么你会看到你所有的帖子在一个json对象中从服务器发送。

This is very handy for making javascript heavy applications that need to pass json back and forth from the server. If you wanted, you could easily create a json api on your rails back-end, and only pass one view - like the index view of your Post controller. Then you could use a javascript library like Jquery or Backbone (or both) to manipulate data and create your own interface. These are called asynchronous UIs and they are becomming really popular (Gmail is one). They are very fast and give the end-user a more desktop-like experience on the web. Of course, this is just one advantage of formatting your data.

Rails 3的写法如下:

    class PostsController < ApplicationController
      # GET /posts
      # GET /posts.xml


      respond_to :html, :xml, :json

      def index
        @posts = Post.all

        respond_with(@posts)
      end

#
# All your other REST methods
#

end

通过将respond_to:html,:xml,:json放在类的顶部,你可以声明所有你想要控制器发送到视图的格式。

然后,在控制器方法中,你所要做的就是respond_with(@whatever_object_you_have)

它只是比Rails自动生成的代码简化了一点。

如果你想知道它的内部工作原理…

据我所知,Rails内省对象以确定实际的格式。“format”变量的值就是基于这种自省。Rails可以用一点点信息做很多事情。你会惊讶于一个简单的@post或:post能走多远。

例如,如果我有一个_user.html。Erb的部分文件是这样的:

_user.html.erb

<li>    
    <%= link_to user.name, user %>
</li>

然后,在我的索引视图中,这将让Rails知道它需要找到'users'部分,并遍历所有'users'对象:

index.html.erb

 <ul class="users">
   <%= render @users %>     
 </ul>

会让Rails知道它需要找到'user'部分并遍历所有'users'对象:

你可能会发现这篇博客文章很有用:http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with

你也可以阅读原文:https://github.com/rails/rails

其他回答

这是一段利用Rails helper方法的Ruby代码。如果你还不熟悉block,你会在Ruby中看到很多。

respond_to是一个附加到Controller类(或者更确切地说,它的超类)的Rails助手方法。它引用将发送到视图(将发送到浏览器)的响应。

示例中的块正在格式化数据——通过在块中传入一个“format”参数——当浏览器请求html或json数据时,这些数据将从控制器发送到视图。

如果你在你的本地机器上,你已经设置了Post脚手架,你可以访问http://localhost:3000/posts,你会看到你所有的文章都是html格式的。但是,如果你输入这个:http://localhost:3000/posts.json,那么你会看到你所有的帖子在一个json对象中从服务器发送。

This is very handy for making javascript heavy applications that need to pass json back and forth from the server. If you wanted, you could easily create a json api on your rails back-end, and only pass one view - like the index view of your Post controller. Then you could use a javascript library like Jquery or Backbone (or both) to manipulate data and create your own interface. These are called asynchronous UIs and they are becomming really popular (Gmail is one). They are very fast and give the end-user a more desktop-like experience on the web. Of course, this is just one advantage of formatting your data.

Rails 3的写法如下:

    class PostsController < ApplicationController
      # GET /posts
      # GET /posts.xml


      respond_to :html, :xml, :json

      def index
        @posts = Post.all

        respond_with(@posts)
      end

#
# All your other REST methods
#

end

通过将respond_to:html,:xml,:json放在类的顶部,你可以声明所有你想要控制器发送到视图的格式。

然后,在控制器方法中,你所要做的就是respond_with(@whatever_object_you_have)

它只是比Rails自动生成的代码简化了一点。

如果你想知道它的内部工作原理…

据我所知,Rails内省对象以确定实际的格式。“format”变量的值就是基于这种自省。Rails可以用一点点信息做很多事情。你会惊讶于一个简单的@post或:post能走多远。

例如,如果我有一个_user.html。Erb的部分文件是这样的:

_user.html.erb

<li>    
    <%= link_to user.name, user %>
</li>

然后,在我的索引视图中,这将让Rails知道它需要找到'users'部分,并遍历所有'users'对象:

index.html.erb

 <ul class="users">
   <%= render @users %>     
 </ul>

会让Rails知道它需要找到'user'部分并遍历所有'users'对象:

你可能会发现这篇博客文章很有用:http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with

你也可以阅读原文:https://github.com/rails/rails

响应器注册背后的元编程(参见Parched Squid的回答)也允许你做这样漂亮的事情:

def index
  @posts = Post.all

  respond_to do |format|
    format.html  # index.html.erb
    format.json  { render :json => @posts }
    format.csv   { render :csv => @posts }
    format.js
  end
end

当您访问/posts.csv时,csv行将导致在每个帖子上调用to_csv。这使得从rails站点导出数据为CSV(或任何其他格式)变得很容易。

js行将导致javascript文件/posts.js(或/posts.js.coffee)被呈现/执行。我发现这是一个轻量级的方式来创建一个Ajax支持的网站使用jQuery UI弹出窗口。

格式是什么类型的变量?

从java POV来看,format是一种匿名接口的实现。这个接口有一个为每种mime类型命名的方法。当您调用其中一个方法(传递一个块)时,如果rails认为用户需要该内容类型,那么它将调用您的块。

当然,这个匿名胶水对象实际上并没有实现接口——它动态地捕获方法调用,并计算出它所知道的mime类型的名称。

就我个人而言,我认为这看起来很奇怪:你传入的块被执行了。对我来说,传递格式标签和块的散列更有意义。但是——这似乎就是RoR的做法。

我想了解respond_to块实际上是如何工作的。什么 变量的类型是格式?是.html和.json方法的格式 对象?

为了理解什么是格式,您可以首先查看respond_to的源代码,但很快您就会发现真正需要查看的是retrieve_response_from_mimes的代码。

从这里,您将看到传递给respond_to(在您的代码中)的块实际上被调用并与Collector的实例一起传递(在块中引用为format)。Collector基本上根据Rails所知道的mime类型生成方法(我相信是在Rails启动时)。

所以,是的,.html和.json是在Collector(又名format)类上定义的方法(在运行时)。

“格式”是响应类型。例如,可以是json或html。它是访问者将收到的输出的格式。