简体   繁体   中英

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

在此处输入图像描述

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

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.

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'

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] }

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
  }
}]

Formatting is the easy part, but I believe what you are asking for, should be achieved within the controller rather than in your view.

Refer to http://ar.rubyonrails.org/classes/ActiveRecord/Serialization.html#M000049 and see how you can use to_json better to actually output just what you need rather than have the entire object serialized.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM