-
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)
endNote 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
endSince 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
endNow 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.
app/controllers/api/v1/notes_controller.rb
class API::V1::NotesController < ApplicationController
def index
@notes = Note.all
respond_to :json
end
def show
@note = Note.find params[:id]
respond_to :json
end
end