Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create complex Json response in ruby in rails

I am working on ruby on rails project and I want to add respond to Json.

One simple way is:--

def index
  @users = User.all
  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @users }
    format.json  { render :json => @users.to_json }
  end
end

But there are some issues with this:-

  1. I don't want to give the whole user object in json response like password hash and cache counter attributes. Facebook, twitter attributes etc.
  2. I want to add more details in the json object (considering stackoverflow model) like Latest question by each user, latest answer given by each user. Instead of image name stored in db via paperclip, I want to pass full url of the image.

So the question is how can code json reponse in index.json.erb file like we do in index.html.erb. Format your own json response as per needs.

EDIT

def index
  @users = User.all
  respond_to do |format|
    format.html # index.html.erb
    format.xml  { render :xml => @users }
    format.json  { render :file => "index.json.erb", :content_type => 'application/json' }
  end
end

index.json.erb file:-

    <% @users.each do |user| %>
    {
      first_name: <%= user.first_name %>,
      last_name: <%= user.last_name %>  
    }

    <% end %>

Error:--

template missing.

PS:-- I am just trying using creating this file. This is just a sample

EDIT

enter image description here

edit

 { { first_name: Mohit , last_name: Jain } { first_name: Sahil Miglani, last_name: } { first_name: Hitesh Bansal, last_name: } { first_name: Sudhanshu, last_name: } { first_name: Saakshi, last_name: } { first_name: Kutta, last_name: } { first_name: bc, last_name: } { first_name: hey, last_name: } { first_name: fewhjfbwfb, last_name: vdsv } } 

EDIT

    [ { first_name: Mohit , last_name: Jain } , { first_name: Sahil Miglani, last_name: } , { first_name: Hitesh Bansal, last_name: } , { first_name: Sudhanshu, last_name: } , { first_name: Saakshi, last_name: } , { first_name: Kutta, last_name: } , { first_name: bc, last_name: } , { first_name: hey, last_name: } , { first_name: fewhjfbwfb, last_name: vdsv } ] 

EDIT, quite close to find out the solution:-

    [
    <% @users.each_with_index do |user,index| %>
    {
        <%= "first_name".to_json.html_safe %>: <%= user.first_name.to_json.html_safe %>,
        <%= "last_name".to_json.html_safe %>: <%= user.last_name.to_json.html_safe %>  
    }
    <% unless index== @users.count - 1%>
    ,
    <% end %>
    <% end %>
    ]

Response:-

    [

       -
       {
           first_name: "Mohit "
           last_name: "Jain"
       }
       -
       {
           first_name: "Sahil Miglani"
           last_name: null
       }
       -
       {
           first_name: "Hitesh Bansal"
           last_name: null
       }
       -
       {
           first_name: "Sudhanshu"
           last_name: null
       }
       -
       {
           first_name: "Saakshi"
           last_name: null
       }
       -
       {
           first_name: "Kutta"
           last_name: null
       }
       -
       {
           first_name: "bc"
           last_name: null
       }
       -
       {
           first_name: "hey"
           last_name: null
       }
       -
       {
           first_name: "fewhjfbwfb"
           last_name: "vdsv"
       }

    ]

Now all i want is to enclose this each response section in user array

like image 877
Radio TukTuk Avatar asked Jun 14 '11 14:06

Radio TukTuk


4 Answers

You can customize the output by implementing the code in your model:

def as_json(options={})
  super(:only => [:name, :email])
end

Then in your controller you can use:

render :json => @user

See "Rails to_json or as_json?" for more info.

like image 187
Devin M Avatar answered Oct 02 '22 18:10

Devin M


You can render a json.erb file and use it like a normal template:

# file: app/views/your_controller/your_action.json.erb
{
  filed1: <%= @some_var %>,
  field2: <%= @another_var %>,
  fieldN: <%= @yet_another_var %>,
  data: <%= @some_data.to_json.html_safe %>
}

in your controller, call the explicit render with content_type:

render :file => "your_file.json.erb", :content_type => 'application/json'
like image 42
Andrea Pavoni Avatar answered Sep 30 '22 18:09

Andrea Pavoni


You can send options for the JSON format for:

  • :only (explicit list of attributes)
  • :except (attribute exclusion list)
  • :methods (list of methods the execute and include their content)
  • :include (relations)

If you want to always use this JSON output formatting, put them in the as_json method (see Devin's answer):

format.json  { render :json => @users.to_json{:only=>[:name, :email, :id], :methods=>[:last_question_answered], :include=>[:profile] }
like image 11
Jesse Wolgamott Avatar answered Sep 29 '22 18:09

Jesse Wolgamott


Take a look to rabl gem, to customize your view:

# app/views/posts/index.rabl
collection @posts
attributes :id, :title, :subject
child(:user) { attributes :full_name }
node(:read) { |post| post.read_by?(@user) }

That will generate:

[{  post :
  {
    id : 5, title: "...", subject: "...",
    user : { full_name : "..." },
    read : true
  }
}]
like image 5
JCorcuera Avatar answered Sep 29 '22 18:09

JCorcuera