Reputation: 1845
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.
I'm doing an AJAX request by using form_with in the client side. In the controller, my action looks like this:
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. Is that correct?
In this case, it always answers back by using format.html. I've checked that If I put format.json first (above format.html) It indeed answer back by using json.
What's wrong or what am I missing?
Thanks!
Upvotes: 2
Views: 1553
Reputation: 102036
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. 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. An AJAX request request can actually request any possible content type - JSON is just the most commonly used and arguably the most useful type.
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:
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. 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:
<%= 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
.
xhr.setRequestHeader("Content-Type", "application/json");
With jQuery you use the type:
option for the ajax funtions or jQuery.getJSON
.
Also the correct way to respond is to a successful POST request is with 201 Created.
201 Created. 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.
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 }
Upvotes: 1
Reputation: 310
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.
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:
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.
for more information this is a good post to read.
Upvotes: 1