-
Notifications
You must be signed in to change notification settings - Fork 0
22 API Jbuilder Views
Let's look again at our new controller.
app/controllers/api/v1/notes_controller.rb
class API::V1::NotesController < ApplicationController
def index
@notes = Note.all
respond_to do |format|
format.json do
render json: @notes.to_json
end
end
end
end
@notes.to_json
will take all attributes of the note and render them out in the response as JSON objects. What if we added a migration to add, remove, or rename a column? Then the JSON output could change, which may break applications that are consuming that API.
Rails now ships with a gem named jbuilder
that makes it easier to map Ruby objects to JSON structures in a way that, even if we update the model, the JSON "views" won't change.
Let's add a jbuilder
view for api/v1/notes#index
in app/views/api/v1/notes/index.json.jbuilder
:
json.array!(@notes) do |note|
# json.extract! note, :id, :title, :body_text, :body_html, :created_at, :updated_at
# is equivalent to this, but I like this better.
json.id note.id
json.title note.title
json.body_text note.body_text
json.body_html note.body_html
json.created_at note.created_at
json.updated_at note.updated_at
json.url api_v1_note_url(note, format: :json)
end
Note the json.extract!
takes the note
object, and an array of symbols that correspond to the columns we want to display. If those columns do change, then the json may not have a value for that anymore, but it will still include the JSON key in the response with that name. We've commented this line out, as we are going to specify our JSON keys and values one-at-a-time.
In addition to the normal attributes, note the custom attribute json.url
that we've included to link to the URL for the object. This is a technique used for "disoverable" API's (sometimes called HyperMedia). This makes it apparent to an API consumer where it can go to get more information.
Now that the view is in place, we can remove the render json: @notes.to_json
block from the controller action. Without a render
or redirect_to
, Rails will simply look for the appropriate view to render.
app/controllers/api/v1/notes_controller.rb
def index
@notes = Note.all
respond_to do |format|
format.json
end
end
Since we're responding only to .json
, we can also pass respond_to
a symbol instead of a block:
app/controllers/api/v1/notes_controller.rb
def index
@notes = Note.all
respond_to :json
end
Now our JSON should look really nice.
Make a show
method for api/v1/notes_controller
with a reasonable .jbuilder
template, much like the index
action.