Rails,respond_to块和|格式|

Rails scaffold生成以下内容:

 respond_to do |format| if @student.save format.html { redirect_to @student, notice => 'Student was successfully created.' } format.json { render :show, status: :created, location: @student } else format.html { render :new } format.json { render json: @student.errors, status: :unprocessable_entity } end end 

阅读本文之后,我理解了respond_to是如何工作的(有点),但我不知道format正在做什么。 不应该 format.jsonformat.json而不是两者兼而有之 ? 这两条线实际上在做什么?

 format.html { render :new } format.json { render json: @student.errors, status: :unprocessable_entity } 

if在那里有暗示吗? 是这样的吗?

 if (format == html) {} if (format == json) {} 

旁注:为什么update需要respond_to块,而show会处理/students/1.json/students/1而没有任何逻辑?

formatrespond_to yield的局部变量。 当你执行format.html {}你实际上正在为一种格式注册一个回调块。

Rails遍历已注册的格式,并尝试在请求中找到与MIME类型兼容的格式。 如果没有处理程序,则会引发错误。

这可以解释为在case语句之上使用语法糖(Ruby等价于switch语句)。 但这种类比并不完全准确,因为Rails在匹配请求类型方面做了一些工作。

注册format.html块时,块内的代码也不会执行(如果它只是一个条件语句),而是当respond_to完成或者根本没有完成时,如果你使用的是E-Tag缓存。

为什么更新需要respond_to块,而show会处理/students/1.json或/ students / 1而没有任何逻辑?

Rails通过使用约定优于配置方法并猜测操作的意图来处理许多操作。

 def PostsController < ApplicationController def index # rails auto-magically fills in the controller with something # like this @posts = Post.all respond_to do |format| format.html { render :index } format.json { render json: @posts } end end def show # convention over configuration is awesome! @post = Post.find(params[:id]) respond_to do |format| format.html { render :show } format.json { render json: @post } end end def new @post = Post.new render :new end def edit @post = Post.find(params[:id]) render :edit end end 

Rails假定有一个与控制器同名的资源,并自动神奇地填充控制器操作。 它还假设在app/views/posts/(:action).html.[erb|haml|slim|jbuilder]有一个视图app/views/posts/(:action).html.[erb|haml|slim|jbuilder]

评论大致显示了rails尝试的操作。

它不会填充对数据进行操作的操作(创建,更新,销毁),因为实际实现可能会有很大差异,并且很难做出有用的猜测。

嗯,这取决于请求的格式。 如果请求从服务器请求HTML,则将执行format.html块,并且以相同的方式,如果请求需要JSON格式,则将执行format.json

Rails将自动(读取:神奇地)为您处理if (format == html)部分。 你所要做的就是填空。 同样,您可以从format.xml开始编写XML块。

而对于附注,我认为你已经说过了。 update方法不需要respond_to块,而show需要。 原因很简单: update方法是更新模型,然后,将您重定向到某个地方,而show将始终返回一些东西。 在你的情况下, /students/1将返回你在数据库中创建的第一个学生,响应将是HTML,而/students/1.json将返回相同的结果,但这次响应将是JSON。

那么你可以用’foo’或’banana’或任何你想要的东西取代’format’。 在这种情况下,它只是变量名称,因为response_to发送到您的块的变量正在传入传入的http请求的Accept标头所请求的格式。

有时您会在日志中看到422个“不可接受”错误,因为您收到的请求带有一个不会请求您的应用知道的mime类型的Accept标头。

实际上,您的调用者应该使用浏览器或者是JSON使用者,发送正确的标头以接收来自样板的响应。