Include specific columns in Rails API/JSON - ruby-on-rails

This:
def index
render json: Slide.all.to_json(include: :user)
end
Is rendering this:
[
{
id: 1,
title: 'Hello',
user: {
first_name: 'Guilherme',
last_name: 'Oderdenge',
email: 'guilhermeoderdenge#gmail.com'
}
}
]
Ok. But I just want the first_name from user. There's a way to do this?

Yes, you can do this:
render json: Slide.all.to_json(include: { user: { only: :first_name} )
See the rails api for more information.

Change it like
render json: Slide.all.to_json(:include=>{:user=>{:only=>[:first_name]}})

Related

Rails - format Time in API response

i have a model places in relationship with the model opening_times.
In my places_controller i have this:
def index
places = Place.all
if places
render json: {
status: :ok,
result: places.as_json(
only: [
:id,
:name,
],
include: [
{ opening_times: {only: [:dayWeek, :open, :close]}},
]
)
}
else
render json: { errors: 'invalid request' }, status: 422
end
end
private
def place_params
params.require(:place).permit(:user_id, :name)
end
The open and close columns in DB are time.
How can i force to return a format time as %H:%M?
I'm not developing on RoR 3+ years... fill free to fix if there is any problem
So can You try this:
places = Place.all.map {|place|
place.opening_times.map! {|opening_time|
opening_time[:open].strftime! "%H:%M"
opening_time[:close].strftime! "%H:%M"
}
}

Rails: Prevent JSON hash from being re-ordered

I have the following method in my ContactsController:
def index
#contacts = {}
company = current_employer.company
groups = company.groups.pluck(:name)
contacts = company.contacts.order(last_name: :asc)
contacts.each do |contact|
#contacts[contact.id] = contact.as_json
#contacts[contact.id][:groups] = {}
contact_groups = contact.groups.pluck(:name)
groups.each do |name|
#contacts[contact.id][:groups][name] = contact_groups.include?(name)
end
end
binding.pry
respond_to do |format|
format.json { render json: { contacts: #contacts } }
end
end
This generates a #contacts hash where the keys are the contact IDs, but the hash is ordered by the contact's last name. If I put in a binding.pry I can see that the hash is in the right order that my client expects, however once it's rendered, the hash is reordered by contact IDs.
Here is a sample of what #contacts looks like:
{
contacts: {
24: {
id: 24,
first_name: "Foo",
last_name: "Bar",
email: "foo#foo.co",
groups: {
Test: true,
Random: false,
Example: false
}
},
31: {
id: 31,
first_name: "Jackie",
last_name: "Chan",
email: "chan#example.com",
groups: {
Test: false,
Random: true,
Example: false
}
},
28: {
id: 28,
first_name: "Jason",
last_name: "Rebourne",
email: "jason.rebourne#example.com",
groups: {
Test: false,
Random: false,
Example: true
}
}
}
}
Normally this is desirable behavior, however in this case I'd like to disable it so as to avoid additional iteration through the response on the client side. How can I prevent the hash from being reordered?
Note: I don't have a custom serializer for my Contact or Group classes.
Edit
This is not a duplicate question. I want to return a custom JSON structure, not a standard serialized structure, which is what the linked "duplicate" question is about.

Rails render json object with camelCase

I have the following controller code in a simple Rails API:
class Api::V1::AccountsController < ApplicationController
def index
render json: Account.all
end
def show
begin
render json: Account.includes(:cash_flows).find(params[:id]), include: :cash_flows
rescue ActiveRecord::RecordNotFound => e
head :not_found
end
end
end
The problem with this is that, the generated json have the format:
{
id:2,
name: 'Simple account',
cash_flows: [
{
id: 1,
amount: 34.3,
description: 'simple description'
},
{
id: 2,
amount: 1.12,
description: 'other description'
}
]
}
I need that my generated json is camelCase('cashFlows' instead of 'cash_flows')
Thanks in advance!!!
Following the recommended by #TomHert, I used JBuilder and the available config:
Keys can be auto formatted using key_format!, this can be used to convert keynames from the standard ruby_format to camelCase:
json.key_format! camelize: :lower
json.first_name 'David'
# => { "firstName": "David" }
You can set this globally with the class method key_format (from inside your environment.rb for example):
Jbuilder.key_format camelize: :lower
Thanks!!!

Can't pass spec test because of created_at

I'm testing 'get' method and getting error:
expected:
[{\"user_id\":11,\"user_first_name\":\"bob\",\"user_last_name\":\"marley\",\"user_picture\":\"/images/missing.png\",\"id\":2,\"text\":\"my
third review\",\"date\":\"2013-12-27T09:08:06.364Z\"}]
got:
[{\"user_id\":11,\"user_first_name\":\"bob\",\"user_last_name\":\"marley\",\"user_picture\":\"/images/missing.png\",\"id\":2,\"text\":\"my
third review\",\"date\":\"2013-12-27T09:08:06.000Z\"}]
what the hell? Why last numbers are different while all other fields are equal?
it "should return reviews for user" do
review = Review.create(reviewer_id: #user.id, user_id: #user2.id, text: 'my third review')
get 'get_reviews_for_user', user_id: #user2.id
expect(response).to be_success
json = JSON.parse(response.body)
expect(json['reviews'].to_json).to eq([{user_id: #user.id,
user_first_name: #user.first_name,
user_last_name: #user.last_name,
user_picture: #user.picture.url(:thumb),
id: review.id,
text: review.text,
date: review.created_at
}].to_json)
end
In controller:
def get_reviews_for_user
user = User.where(id: params[:user_id]).first
return render json: {success: false} if user.nil?
reviews = []
Review.where(user_id: user.id).each do |review|
reviewer = review.reviewer
reviews << {user_id: reviewer.id,
user_first_name: reviewer.first_name,
user_last_name: reviewer.last_name,
user_picture: reviewer.picture.url(:thumb),
id: review.id,
text: review.text,
date: review.created_at}
end
render json: { success: true, reviews: reviews }
end
The times are different because the milliseconds are truncated when the time is translated into JSON.
You can use Timecop to freeze the time to a give value like this : Timecop.freeze(Time.now).
You can also use a stub like this (in you test) :
allow(Review).to receive(:where).with(user_id: #user.id).and_return([review])
allow(review).to receive(:created_at).and_return(Time.now)

Problem building JSON file

want to get all db entries by a specific hash and return it as json. I use the following code:
#tasks = Task.find_all_by_hash(params[:hash])
respond_to do |format|
format.json { render :json => #tasks }
end
now i have the problem that my json file isn't correct. it has the following output:
[
{
task: {
hash: "9dfca619f00f5488785f6b74ad1b590beefaee7a88c04884bf197e7679f3"
id: 4
created_at: "2010-12-16T09:09:51Z"
updated_at: "2010-12-16T09:14:10Z"
done: true
name: "Hallo"
}
},
{
task: {
hash: "9dfca619f00f5488785f6b74ad1b590beefaee7a88c04884bf197e7679f3"
id: 5
created_at: "2010-12-16T09:12:37Z"
updated_at: "2010-12-16T09:12:37Z"
done: true
name: "Test"
}
},
...
]
but actually i want it like this:
{ tasks: [
{"id":"1","date_added":"0001-02-22 00:00:00","post_content":"Check out my content, this is loaded via ajax and parsed with JSON","author":"Ryan Coughlin"},
{"id":"2","date_added":"0000-00-00 00:00:00","post_content":"More content, loaded. Lets try to add a form in and post via ajax and append the new data","author":"Billy Bob"}
]}
any advice? thank you!
Try collecting the task alone to an array and create a json object using that. Some thing like
#tasks = Task.find_all_by_hash(params[:hash])
a = []
#tasks.each do |t|
a << t[:task]
end
b = {:tasks => a}
respond_to do |format|
format.json { render :json => b }
end

Resources