Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 692
Jwan622 Avatar asked Jul 13 '15 08:07

Jwan622


2 Answers

  • 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.

like image 135
D-side Avatar answered Oct 19 '22 14:10

D-side


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

like image 4
Milind Avatar answered Oct 19 '22 14:10

Milind