Jwan622
Jwan622

Reputation: 11639

What's the difference between using render instead of respond_with/to in a Rails API?

I am building a simple rails tutorial on how to build APIs for some students and I am building it without the respond_to and respond_with because I just want to see if I can build an api without using a gem. This is what I have and my tests pass:

controller:

class Api::V1::SuyasController < ApplicationController
  def index
    render json: Suya.all
  end

  def create
    render json: Suya.create(suyas_params)
  end


  private

  def suyas_params
    params.require(:suya).permit(:meat, :spicy)
  end
end

routes:

Rails.application.routes.draw do
  namespace :api do
    namespace :v1 do
      resources :vendors
      resources :suyas
    end
  end
end

tests:

require 'test_helper'

class Api::V1::SuyasControllerTest < ActionController::TestCase
  test "index can get all the suyas" do
    Suya.create(meat: "beef", spicy: true)
    Suya.create(meat: "kidney", spicy: false)

    get :index
    suyas = JSON.parse(response.body)

    assert_equal "beef", suyas[0]["meat"]
    assert_equal true, suyas[0]["spicy"]
    assert_equal "kidney", suyas[1]["meat"]
    assert_equal false, suyas[1]["spicy"]
  end

  test "create can create a suya" do
    assert_difference("Suya.count", 1) do
      create_params = { suya: { meat: "beefy", spicy: true }, format: :json }

      post :create, create_params
      suya = JSON.parse(response.body)

      assert_equal "beefy", suya["meat"]
      assert_equal true, suya["spicy"]
    end
  end
end

What's the difference between using render vs respond_with? I can't find any answers. Is there even something that I am doing wrong? Why are there two ways to create APIs (respond_to/respond_with AND this way?)

-Jeff

Upvotes: 14

Views: 7195

Answers (3)

Jwan622
Jwan622

Reputation: 11639

I think the answer is that render only allows me to respond with JSON, whereas if I use respond_to and respond_with, I can respond in more than just one manner? Is that all?

Upvotes: 0

D-side
D-side

Reputation: 9485

  • render is part of Rails and it just renders whatever you say in whatever format you say. Typically a view, possibly a string, possibly a file.

    A pretty low-level function that renders whatever you say making a few assumptions per conventions, like where to look for a view.

  • respond_to is a micro-DSL that allows you to respond differently to different formats being requested.

    I. e. in a block with |format| call to format.json requires a block that will be executed on requests for JSON, otherwise will be a no-op (no operation). Also, if respond_to didn't execute any block, it responds with a generic 406 Not Acceptable (server cannot respond in any format acceptable by the client).

    While it is possible to do if request.json?, it's not so readable and needs to explicitly specify when to respond with 406.

  • respond_with, formerly part of Rails, now (since 4.2) in a separate gem responders (for a reason), takes an object and uses it to construct a response (making a lot of assumptions, all of them can be given at controller declaration).

    It makes code much shorter in typical use cases (i. e. some APIs). In not-so-typical use cases it can be customized to suit your needs. In highly unusual use cases it's of no use.

I may be overly simplifying things, it's a general overview.

Upvotes: 21

Milind
Milind

Reputation: 5112

There are two things :)..render and respond_to.

Render is used to create a full response and sends it back to the browser. So render is used in respond_to ,to make your action very responsive for every call whether it can be js/ajax call,full page load(html),json(to show autosearch dropdown,tokens) or xml.So if i want my method to work and respond to every calls from client,i will use the below block in my action.

  respond_to do |format|
      format.html { redirect_to(person_list_url) }
      format.js {render "show_person_details"}
      format.xml { render :xml => @people.to_xml }
      format.json { render json: @people}
    end

above controller will work on every scenario,such as js/html/json and xml without getting 403 Forbidden error which we get usually get when a js call is made to action having only format.html and not format.js

HOPE IT HELPS

Upvotes: 5

Related Questions