简体   繁体   English

Rails、响应块和 |格式|

[英]Rails, respond_to blocks and |format|

Rails scaffold generated the following: 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

After reading this I understand how the respond_to is working (sort of), but I don't get what format is doing.阅读本文后,我了解了respond_to的工作方式(有点),但我不明白format在做什么。 Shouldn't it be either format.html or format.json and not both ?它不应该是要么format.htmlformat.json ,而不是两者兼而有之 What are these two lines actually doing?这两行实际上在做什么?

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

Is there an implied if in there?有没有暗示if在那里? Is it something like是不是有点像

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

Side note: Why does update require the respond_to block while show will handle /students/1.json or /students/1 without any logic at all?旁注:为什么update需要respond_to块,而show将在没有任何逻辑的情况下处理/students/1.json/students/1

format is a local variable that respond_to yields . format是一个局部变量,其respond_to 产生. When you do format.html {} you are actually registering a callback block for a format.当您执行format.html {}您实际上是在为某种格式注册一个回调块。

Rails goes through the registered formats and tries to find a compatible format to the MIME type in the request . Rails 会检查已注册的格式,并尝试在请求中找到与MIME 类型兼容的格式。 If there is no handler it will raise an error.如果没有处理程序,它将引发错误。

This could be explained as something like using syntactic sugar on top of a case statement (the Ruby equivalent of a switch statement).这可以解释为类似于在case语句(Ruby 相当于 switch 语句)之上使用语法糖。 But the analogy is not completely accurate since Rails does a bit of work in matching the request type.但是这个类比并不完全准确,因为 Rails 在匹配请求类型方面做了一些工作。

Also the code inside your block is not executed when the format.html block is registered (as it would be if it was just a conditional statement) but rather when respond_to finishes or not at all if you are using for example E-Tag caching.此外,当format.html块被注册时(就像它只是一个条件语句一样),块中的代码不会执行,而是在respond_to完成或根本不执行时执行,如果您正在使用例如 E-Tag 缓存。

Why does update require the respond_to block while show will handle /students/1.json or /students/1 without any logic at all?为什么 update 需要 respond_to 块,而 show 会在没有任何逻辑的情况下处理 /students/1.json 或 /students/1 ?

Rails handles many actions by using a convention over configuration approach and guessing the intent of the action. 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 assumes that there is a resource with the same name as the controller and auto-magically fills in the controller action. Rails 假定存在与控制器同名的资源,并自动神奇地填充控制器操作。 It also assumes there is a view in app/views/posts/(:action).html.[erb|haml|slim|jbuilder] .它还假设app/views/posts/(:action).html.[erb|haml|slim|jbuilder]有一个视图。 This is known as implicit rendering .这称为隐式渲染

The comments show roughly what action rails attempts.评论大致显示了 rails 尝试的操作。

It does not fill in actions which operate on data (create, update, destroy) since the actual implementation can vary greatly and it's hard to make useful guesses.它不填写对数据进行操作的操作(创建、更新、销毁),因为实际实现可能会有很大差异,并且很难做出有用的猜测。

Well, it depends on the format of the request.嗯,这取决于请求的格式。 If a request demands HTML from the server, format.html block will be executed, and in the same way, if a request demands JSON format, format.json will be executed.如果请求需要来自服务器的 HTML,则format.html块将被执行,同样,如果请求需要JSON格式,则format.json将被执行。

Rails will automatically(read: magically) handle the if (format == html) part for you. Rails 会自动(读:神奇地)为你处理if (format == html)部分。 All you have to do is fill in the blanks.您所要做的就是填空。 Same way, you can write a block for XML starting with format.xml .同样,您可以为 XML 编写一个以format.xml开头的块。

And for the side note, I think you have said it otherwise.至于旁注,我想你已经说过了。 update method doesn't require respond_to block, while show requires. update方法不需要respond_to块,而show需要。 And the reason is very simple: update method is there to update the Model, and then, redirect you to somewhere, while show will always return you something.原因很简单: update方法用于更新模型,然后将您重定向到某个地方,而show总是会返回给您一些东西。 In your case, /students/1 will return you the first student created in the database, and the response will be HTML, while /students/1.json will return you the same result, but response will be JSON this time.在您的情况下, /students/1将返回您在数据库中创建的第一个学生,并且响应将是 HTML,而/students/1.json将返回相同的结果,但这次响应将是 JSON。

Well you could very well replace 'format' with 'foo' or 'banana' or whatever you want.好吧,您可以很好地将“格式”替换为“foo”或“banana”或您想要的任何内容。 It is just the variable name in this case because the variable that is sent to your block by respond_to is passing along the format as requested by the incoming http request's Accept header.在这种情况下,它只是变量名称,因为 response_to 发送到您的块的变量正在传递传入 http 请求的 Accept 标头所请求的格式。

Sometimes you'll see 422 "Unacceptable" errors in your logs because you are receiving a request with an Accept header that does not request a mime type your app knows about.有时,您会在日志中看到 422 个“不可接受”错误,因为您收到的请求带有 Accept 标头,而该标头并未请求您的应用知道的 mime 类型。

As it is, your callers should be using a browser or be a JSON consumer sending the proper headers to receive responses from the boilerplate.实际上,您的调用者应该使用浏览器或 JSON 消费者发送正确的标头以接收来自样板的响应。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM