Rails: Respond_To JSON and HTML

Rails: respond_to JSON and HTML

As per my knowledge its not necessary to "render show" in format.html it will automatically look for a respective action view for ex : show.html.erb for html request and show,js,erb for JS request.

so this will work

respond_to do |format|

format.html # show.html.erb
format.json { render json: @user }

end

also, you can check the request is ajax or not by checking request.xhr? it returns true if request is a ajax one.

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

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 }

Rails respond_to format HTML Json Not workng with params

GET "/projects/5982a8799f911d0318054997/tickets"

as you can see from your rake routes the route for the tickets#index action is /projects/:project_id/tickets and you are passing parameters[:project_id] as 5982a8799f911d0318054997. If you are passing other parameters, they will be in the request.body

GET "/tickets/index/tickets.json"

this route does not make sense. You need to check your router, as it is taking parameters[:id] = 'tickets', maybe you set your routing incorrectly.

It could look like this right now

GET '/tickets/index/:id'

and when you perform GET request to url /tickets/index/tickets.json, it will take your last input tickets as the id params

How to use respond_to for json?

Append .json at the end of the URL you are trying to hit with. This way, server will know that request is demanding data in JSON format, while the default format is HTML.

If you are using jQuery to do AJAX, and want to receive data back in JSON format without appending .json at the end, you can use then use the function $.getJSON(), or can pass simply the option dataType: "json" in $.jquery() function call:

$.ajax({
dataType: "json", // To receive data back in JSON
url: url,
data: data,
success: success
});

Rails, respond_to blocks and |format|

format is a local variable that respond_to yields. When you do format.html {} you are actually registering a callback block for a format.

Rails goes through the registered formats and tries to find a compatible format to the MIME type in the request. 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). But the analogy is not completely accurate since Rails does a bit of work in matching the request type.

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.

Why does update require the respond_to block while show will handle
/students/1.json or /students/1 without any logic at all?

Rails handles many actions by using a convention over configuration approach and guessing the intent of the action.

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. It also assumes there is a view in app/views/posts/(:action).html.[erb|haml|slim|jbuilder]. This is known as implicit rendering.

The comments show roughly what action rails attempts.

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.

respond_to block always renders html

If you look in the output from rake routes then you'll see all your URIs have this (.format) suffix to them. The parens mean that it's optional. If not provided (and if the Accept header(s) don't disambiguate the request) then Rails defaults to responding with HTML.

So in your cURL command just provide the .json format and Rails will respond with the right thing:

curl localhost:3000/foos.json


Related Topics



Leave a reply



Submit