Rails rendering JSON in views - ruby-on-rails

I am having trouble trying to render specific fields in my rails app my structure is like so:
Home_controller.rb
def index
taobao_hash = OpenTaobao.get(
:method => "taobao.tbk.item.get",
:fields => "num_iid,title,nick,pict_url,cid,price,type,delist_time,post_fee,score,volume",
:q => "snus",
:page_size => 1,
:sort => "_des",
)
h = JSON.parse(taobao_hash.to_json)
render json: h["tbk_item_get_response"]
end
How this renders my whole request as json like so
{
"results": {
"n_tbk_item": [
{
"nick": "恶毒对于",
"num_iid": 17707525948,
"pict_url": "http://img4.tbcdn.cn/tfscom/i2/TB1umhOHVXXXXa0aXXXXXXXXXXX_!!0-item_pic.jpg",
"title": "瑞典戒烟产品唇烟嚼烟经典款General Classic White Portion Snus",
"volume": 127
}
]
},
"total_results": 99,
"request_id": "1476rjvn5sc2g"
}
How would I go about only rendering title in my view? I can only seem to render everything.

Related

Issue when rendering a Jbuilder json object as json

I am developing in student tracking website in RoR. In model I have following code to build json
self.as_json
json = Jbuilder.new do |j|
j.courses student_courses do |course|
j.(course, :id, :name)
j.students students, :name
end
end.target!
puts json
return json
end
My controller code is
render json: {
courses: course.as_json,
}
and produces
{"courses":[
"{\"id\": 1,\"name\": \"english\",\"students\": [{\"name\": \"ALison\"},{\"name\": \"Robert\"}]
},{...}... ]"
instead of
"courses" : [
{
"id": 1,
"name": "english",
"students": [
{"name": "ALison"},
{"name": "Robert"}]
}, {..},...
]
It is adding escape character(/) before every double quotes. How can I solve this issue
Hey you can use this to generate as alternative
course.to_json(:include => { :students => { :only => :name } })

Active Model Serializer and Custom JSON Structure

I'm trying to use the Active Model Serializer gem with my API, although I am struggling with something I thought would be pretty simple.
All my JSON responses are in a wrapped format, with every response having a top level message and status property, the data is within the content property. Every JSON response follows this format.
Example
{
'status': statuscode,
'message': message,
'content': { 'object':obj }
}
The contents of the "content" property is where I would like to place the output of the Serializer. My lists of articles, etc.
I cannot figure out how to do this though?
Any help would be greatly appreciated.
IF You dont mind your status and messages hashes being inside a hash you can use a meta key.
(from https://github.com/rails-api/active_model_serializers/tree/0-8-stable)
render :json => #posts, :serializer => CustomArraySerializer, :meta => {:total => 10}
=>
{
"meta": { "total": 10 },
"posts": [
{ "title": "Post 1", "body": "Hello!" },
{ "title": "Post 2", "body": "Goodbye!" }
]
}
Or if you need them to be top level keys you can SubClass ArraySerializer and overwrite as_json to allow it to merge in your keys.
def as_json(*args)
#options[:hash] = hash = {}
#options[:unique_values] = {}
hash.merge!(#options[:top_level_keys]) if #options.key?(:top_level_keys)
root = #options[:root]
if root.present?
hash.merge!(root => serializable_array)
include_meta(hash)
hash
else
serializable_array
end
end
then just
render :json #object, :serializer => YourCustomArraySerializer

Convert active record result into Json object

I have below output from active record query
[{"image_id"=>1, "image_name"=> "image1", action_type"=>"Call", "count"=>2},
`{"image_id"=>1, "image_name"=> "image1","action_type"=>"sms", "count"=>1},
{"image_id"=>2, "image_name"=> "image2","action_type"=>"sms", "count"=>1} ]`
Now I want this to be converted into Json object like below
{ "1": { "counts": { "call": 2, "sms": 1 } , "title":'image1' },
"2": { "counts": {"sms": 1} , 'title':'image2'}}
Please check this code.
#xx = [{"image_id"=>1, "image_name"=>"image1", "action_type"=>"Call", "count"=>2}, {"image_id"=>1, "image_name"=>"image1", "action_type"=>"sms", "count"=>1}, {"image_id"=>1, "image_name"=>"image1", "action_type"=>"sms", "count"=>1}]
#arr = []
#xx.each_with_index do |x, i|
#arr << {(i+1).to_s.to_sym => {"counts" => {x["action_type"].to_sym => x["count"]}}}
end
respond_to do |f|
f.json {render :json => #arr}
end
There are two popular libraries that are both very helpful:
active_model_serializers
jbuilder
I prefer active_model_serializers, personally. Many disagree.

How to Post array of data all at one time?

I have a Rails 3 Application that is trying to post an array of users, all at one time. I am trying to post through the Postman REST client. If I tried to post a single user at a time it works well, but it is not possible to post multiple users at a time.
This is my User model:
class User < ActiveRecord::Base
attr_accessible :name,age,email,mobile,gender
end
And my User controller:
respond_to :html , :json
def create
#user = User.new(params[:user])
if #user.save
render :json => { :status => :ok, :message => "User Created Successfully"}.to_json
end
end
User posting data in JSON format for multiple users:
{
user:[
{
"name":"abc",
"age": 23,
"email": "abc#gmail.com",
"mobile": 9876543210,
"gender":"M"
},
{
"name":"def",
"age": 26,
"email": "def#gmail.com",
"mobile": 9876543210,
"gender":"F"
}
]
}
Is it possible to do this in Rails?
I tried:
def create
#userlist = User.new(params[:user])
#userlist.each do |u|
u.save
end
render :json => { :status => :ok, :message => "User Created Successfully"}.to_json
end
but the data is not saved.
Is there any solution?
Nested attributes saving under User:
{
"users" :[
{
"name":"abc",
"age": 23,
"email": "abc#gmail.com",
"mobile": 9876543210,
"gender":"M",
"projects":
[
{
"projectname":"abc",
"type":"abc"
},
{
"projectname":"def",
"type":"abc"
},
{
"projectname":"ghi",
"type":"abc"
}
]
},
{
"name":"def",
"age": 26,
"email": "def#gmail.com",
"mobile": 9876543210,
"gender":"F",
"projects":
[
{
"projectname":"abc",
"type":"abc"
},
{
"projectname":"def",
"type":"abc"
},
{
"projectname":"ghi",
"type":"abc"
}
]
}
]
}
As seen here, I'd suggest you bulk insert (depending on the likely amount of users that will be passed at a time), using this gem:
def create
users = []
#userlist = params[:users]
#userlist.each do |u|
user = User.new(u)
users << user
end
User.import(users)
render :json => { :status => :ok, :message => "User(s) Created Successfully"}
end
Ok, i see your edit of the posted params. so do it in your controller like this:
def create
#userlist = params[:users]
#userlist.each do |u|
user = User.new(u)
user.save!
end
render :json => { :status => :ok, :message => "User Created Successfully"}.to_json
end

How to paginate Rabl's collections

I have this template:
# app/views/posts/index.rabl
collection #posts => :posts
attributes :id, :title, :subject
child(:user) { attributes :full_name }
node(:read) { |post| post.read_by?(#user) }
Witch returns:
{
"posts": [
{
"post": {
"id": 5,
"title": "...",
"subject": "...",
"user": {
"full_name": "..."
},
"read": true
}
}
]
}
And I would like to add to add some pagination params in order to rendering this:
{
"posts": [
{
"post": {
"id": 5,
"title": "...",
"subject": "...",
"user": {
"full_name": "..."
},
"read": true
}
}
],
"total": 42,
"total_pages": 12
}
Any ideas? Many thanks!
Sorry for my noob question, whitch was answered by the README. Here's an example of pagination:
object false
node(:total) {|m| #posts.total_count }
node(:total_pages) {|m| #posts.num_pages }
child(#posts) do
extends "api/v1/posts/show"
end
Note: I'm using Kaminari for pagination.
When searching for kaminari and rabl this is the first and pretty much only relevant result. As such, I would like to leave here a solution according to the HAL Specification that generates links like this.
So first, start with the view:
# api/v1/posts/index.rabl
object false
child(#posts) do
extends 'api/v1/posts/show'
end
node(:_links) do
paginate #posts
end
Then proceed to define the paginate method:
# app/helpers/api_helper
module ApiHelper
def paginate(collection)
current_page_num = collection.current_page
last_page_num = collection.total_pages
{
:first => first_page,
:previous => previous_page(current_page_num),
:self => current_page(current_page_num),
:next => next_page(current_page_num, last_page_num),
:last => last_page(last_page_num)
}
end
def first_page
{ :href => url_for(:page => 1) }
end
def previous_page(current_page_num)
return nil if current_page_num <= 1
{ :href => url_for(:page => current_page_num-1) }
end
def current_page(current_page_num)
{ :href => url_for(:page => current_page_num) }
end
def next_page(current_page_num, last_page_num)
return nil if current_page_num >= last_page_num
{ :href => url_for(:page => current_page_num+1) }
end
def last_page(last_page_num)
{ :href => url_for(:page => last_page_num) }
end
end
And finally, include the helper in the necessary controllers. The helper could be included in a Api::BaseController, from which all API controllers inherit:
helper :api
I could not have done this without Zag zag..'s solution, so.. Thank you so much!
note, for will_paginate 3.0.0 the following works:
node(:total) {|m| #posts.total_entries }
node(:total_pages) {|m| (#posts.total_entries.to_f / #posts.per_page).ceil }
node(:page_num){|m| #posts.current_page}
This might be what you are looking for ;)
object false
node :comments do
partial('posts/index', object: #posts)
end
node(:pagination) do
{
total:#posts.count,
total_pages: 20
}
end

Resources