我正在阅读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

其他回答

据我所知,respond_to是一个附加到ActionController的方法,所以你可以在每个单独的控制器中使用它,因为它们都继承自ActionController。下面是Rails的respond_to方法:

def respond_to(&block)
  responder = Responder.new(self)
  block.call(responder)
  responder.respond
end

你给它传递一个block,就像我在这里展示的:

respond_to <<**BEGINNING OF THE BLOCK**>> do |format|
  format.html
  format.xml  { render :xml => @whatever }
end <<**END OF THE BLOCK**>>

|格式|部分是块期望的参数,所以在respond_to方法中我们可以使用它。如何?

好吧,如果你注意到我们在respond_to方法中传递了一个带前缀的&块,我们这样做是为了将该块作为Proc处理。由于参数有“.xml”,“.html”,我们可以使用它们作为要调用的方法。

我们在respond_to类中所做的基本上是调用Responder类实例的方法“.html, .xml, .json”。

格式是什么类型的变量?

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

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

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

这有点过时了,Ryan Bigg在这里做了很好的解释:

http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to

事实上,它可能比你想要的更详细一些。事实证明,在幕后有很多事情要做,包括需要理解MIME类型是如何加载的。

这是一段利用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

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

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

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

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