简体   繁体   English

为什么在使用 AJAX 时,respond_to 执行的是 format.html 而不是 format.json?

[英]Why is respond_to executing format.html instead of format.json when using AJAX?

I've been looking for similar topics but although I've read a lot I'm still a bit confused about the respond_to block usage.我一直在寻找类似的主题,但虽然我读了很多书,但我仍然对 respond_to 块的使用感到有些困惑。

I'm doing an AJAX request by using form_with in the client side.我正在通过在客户端使用 form_with 来执行 AJAX 请求。 In the controller, my action looks like this:在 controller 中,我的操作如下所示:

  def create
    @role = Role.new(role_params)

    respond_to do |format|
      if @role.save
        format.html { redirect_to url_for(controller: 'roles', action: 'index') }
        format.json { render json: { :location => url_for(controller: 'roles', action: 'index') }, status: 302 }
      else
        format.html { render action: 'new' }
        format.json { render json: { :errors => @role.errors }, status: 422 }
      end
    end
  end

The way I understand respond_to bock is that when you make an AJAX request it should answer back by using json, and If you make a regular request it should answer back by using html.我理解 respond_to bock 的方式是,当您发出 AJAX 请求时,它应该使用 json 回复,如果您发出常规请求,它应该使用 html 回复。 Is that correct?那是对的吗?

In this case, it always answers back by using format.html.在这种情况下,它总是使用 format.html 进行回复。 I've checked that If I put format.json first (above format.html) It indeed answer back by using json.我已经检查过,如果我先放 format.json(在 format.html 上方),它确实通过使用 json 回复。

What's wrong or what am I missing?有什么问题或我错过了什么?

Thanks!谢谢!

form_with by default sends XHR (ajax) request requiring you to have a java-script template for the response and then use format.js inside the respond method. form_with默认发送XHR (ajax)请求,要求您有一个用于响应的java-script template ,然后在响应方法中使用format.js

however if you want to make a json or any other request formats such as xml you can pass the format as a parameter to the path helper method like this:但是,如果您想制作json或任何其他请求格式,例如xml ,您可以将格式作为参数传递给路径辅助方法,如下所示:

admin_roles_path(format: :json)

or use the format option directly in the form_with call but since you are already using the url option the format option will be omitted.或直接在form_with调用中使用格式选项,但由于您已经在使用url选项, format选项将被省略。

for more information this is a good post to read.有关更多信息, 是一篇很好的文章。

The way I understand respond_to bock is that when you make an AJAX request it should answer back by using json, and If you make a regular request it should answer back by using html.我理解 respond_to bock 的方式是,当您发出 AJAX 请求时,它应该使用 json 回复,如果您发出常规请求,它应该使用 html 回复。 Is that correct?那是对的吗?

Not quite.不完全的。 An AJAX request is just an asynchronous request and the response type should depend on the Content-Type and Accept-Type headers. AJAX 请求只是一个异步请求,响应类型应取决于 Content-Type 和 Accept-Type 标头。 An AJAX request request can actually request any possible content type - JSON is just the most commonly used and arguably the most useful type. AJAX 请求请求实际上可以请求任何可能的内容类型 - JSON 只是最常用的并且可以说是最有用的类型。

If the request does not contain a specific content type or accept type Rails will default to html unless you override it in the routes:如果请求不包含特定的内容类型或接受类型,Rails 将默认为 html,除非您在路由中覆盖它:

namespace :api, defaults: { format: :json } do
  namespace :v1 do
    resources :things
  end
end

Rails UJS which is built into rails and powers the remote: true option on forms and links actually uses application/javascript as the default content-type as it lets you write js.erb views and reuse rails templating without writing ajax handlers. Rails UJS 内置在 rails 中并为remote: true选项和链接实际上使用application/javascript作为默认内容类型,因为它允许您编写js.erb视图并重用 rails 模板,而无需编写 ajax 处理程序。 If this is really a good idea though is debatable as it leads to some very questionable design decisions.如果这真的是一个好主意,虽然是有争议的,因为它会导致一些非常有问题的设计决策。

With Rails UJS the easiest way to set the content type is through the data-type attribute:使用 Rails UJS 设置内容类型的最简单方法是通过data-type属性:

<%= link_to "Click Me!", "/foo", remote: true, data: { type: :json } %>
<%= form_with(model, html: { data: { type: "json" }}) %>

If you are sending an Ajax request "manually" with XMLHttpRequest you can set the content type with setRequestHeader .如果您使用 XMLHttpRequest “手动”发送 Ajax 请求,则可以使用setRequestHeader设置内容类型。

xhr.setRequestHeader("Content-Type", "application/json"); 

With jQuery you use the type: option for the ajax funtions or jQuery.getJSON .使用 jQuery,您可以使用type:选项用于 ajax 功能或jQuery.getJSON

Also the correct way to respond is to a successful POST request is with 201 Created.此外,正确的响应方式是使用 201 Created 来响应成功的 POST 请求。

201 Created. 201 已创建。 The request has been fulfilled and has resulted in one or more new resources being created.请求已被满足并导致创建一个或多个新资源。 The primary resource created by the request is identified by either a Location header field in the response or, if no Location field is received, by the effective request URI.请求创建的主要资源由响应中的 Location header 字段标识,如果没有收到 Location 字段,则由有效请求 URI 标识。

format.json { head :created, location: @role }

You can also optionally include the created resource in the response body.您还可以选择在响应正文中包含创建的资源。

format.json { render json: @role, location: @role, status: :created }

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

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