Rabl showing an empty json block - ruby-on-rails

I am trying Rabl, however, I seem to receive a practically empty json block.
require_dependency "api/application_controller"
module Api
class RentablePropertiesController < ApplicationController
respond_to :json
def index
#r = Core::RentableProperty.all
# render :text => #r.to_json --> note: this renders the json correctly
render "api/rentable_properties/index" #note: rabl here does not
end
end
end
index.json.rabl
collection #r
Output
[{"rentable_property":{}}]
Note: with a simply #r.to_json, it renders correctly:
[{"id":1,"description":"description","property_type_id":1,"created_at":"2013-08-22T19:04:35.000Z","updated_at":"2013-08-22T19:04:35.000Z","title":"Some Title","rooms":null,"amount":2000.0,"tenure":null}]
Any idea why rabl doesn't work?

The documentation of RABL (https://github.com/nesquena/rabl#overview) says that you need to precise what attributes you want to show in your JSON.
Their example:
# app/views/posts/index.rabl
collection #posts
attributes :id, :title, :subject
child(:user) { attributes :full_name }
node(:read) { |post| post.read_by?(#user) }
Which would output the following JSON or XML when visiting /posts.json:
[{ "post" :
{
"id" : 5, title: "...", subject: "...",
"user" : { full_name : "..." },
"read" : true
}
}]

Related

Rails-React: passing a rendered jbuilder template to component props from controller

Right now I have my index action set up like this, and I when the games component is rendered it basically receives games.to_json, I would like to reuse the template I have for GET /games.json which is specified in views/games/index.json.builder
I tried passing render(template: 'games/index.json') but I get this error:
Render and/or redirect were called multiple times in this action
def index
#games = Game.all
respond_to do |format|
format.html { render component: 'games', props: { games: #games } }
format.json { render :index }
end
end
On views/games/index.json.jbuilder
json.array! #games do |game|
json.extract! game, :id, :title, :cover_thumbnail
json.url game_url(game, format: :json)
end
If I call GET /games.json I get something like this:
[
{
"id": 133,
"title": "Final Fantasy VII: Remake",
"coverThumbnail": "url",
"url": "http://localhost:3000/games/133.json"
},
...
]
But when I call GET /games, the games component receives every single attribute, I want to send only the attributes specified on the jbuilder template

Rendering json data fields from mysql db in rails response object

I have a rails 4.2 app that uses mysql db 5.7 which supports json fields. So my user model has a field called display_pic which is a json object.
class User < ActiveRecord::Base
serialize :display_pic, JSON
....
In the action get_user I render user as follows
def get_user
#u = User.where(...)
render json: { user: #u }
end
The problem is that the json field display_pic doesn't come out as a nested json object, rather it is rendered as a string. I would like to have a response like the following
{
"user": {
"name": "some name",
"email": "some email",
"display_pic": {
"url": "http://someurl.com",
"width": "400px",
}
}
}
Probably a better way to do this, but you can format it as json in the serializer.
class UserSerializer < ActiveModel::Serializer
attribute :name
attribute :email
attribute :display_pic
def display_pic
JSON.parse(object.display_pic)
end
end
Use the following code it will solve your problem:
def get_user
#u = User.where(...)
render json: { user: JSON.parse(#u)}
end
Have you tried to use the method .as_json ?
def get_user
#u = User.where(...)
render json: #u.as_json
end
You should have not need to set serialize :display_pic, :JSON, but you can overload the method in your user.rb class in order to get on response references or methods results authomatically loaded on your front end:
class PlayerCharacter < ApplicationRecord
[...]
def as_json(options = {})
super(options.merge(include: [ :reference1, :reference2]).merge(methods: [:method_name1, :method_name2])
end
end
EDIT:
you could add display_pic as follow:
class PlayerCharacter < ApplicationRecord
[...]
def as_json(options = {})
super(options.merge(include: [ :display_pic])
end
end

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!!!

Rails ActiveRecord relation to JSON

I'm using Rails to query data and put it into a hash like so...
class AssignmentsController < ApplicationController
respond_to :json
def index
student = Student.find(current_user.student_id)
#assignments = Hash.new
#assignments["individual"] = Assignment.where(:student_id => student.id)
unless student.group_lesson_ids.nil?
student.group_lesson_ids.each do |g|
group_lesson = GroupLesson.find(g)
#assignments[group_lesson.name] = Assignment.where(:group_lesson_id => g)
end
end
end
end
Then I want Rabl to turn this into JSON to be used by a Marionette app.
Here's the Rabl file
object #assignments
attributes :id, :title, :student_id, :assigned
But when I inspect the JSON in the browser, it just shows me the ActiveRecord relation.
{
"#<ActiveRecord::Relation::ActiveRecord_Relation_Assignment:0x007fa2956b43a8>": [
{ },
{ },
{ }
]
}
I understand this is because of the concept of lazy loading, but what should I do in this situation to make the JSON available to Marionette?
How about this, provided you have relationships between models specified (not tested since I'm not currently using RABL):
class AssignmentsController < ApplicationController
respond_to :json
def index
#student = current_user.student
end
end
RABL template:
object false
node :assignments do
child #student.assignments => :individual
#student.group_lessons.each do |gl|
node(gl.name) { gl.assignments }
end
end

How to Include additional field in Rails 3 Application JSON Response

I have a Rails application which displays nested form in json format.
In the JSON Response i am also displaying an id field which represent another table.
How to display name corresponding to that id what i am getting so that i can display both name and id in my json format.
My controller
show method
def show
#maintemplate = Maintemplate.find(params[:id])
respond_with (#maintemplate) do |format|
format.json { render :json => #maintemplate }
end
end
Thanks in advance....
Try this:
render :json => #maintemplate.to_json(:include => { :user => { :only => :name } } )
This will replace the user_id key with a user key and a value with only the name attribute of user, like this:
{
"user_id": "12"
"user": { "name": "..." }
...
}
You can then access the username in the json response with ["user"]["name"]. You can also access the user id with ["user_id"].
For more see the documentation on as_json.
Update:
Using the info provided in the comments, I think this is what you actually want:
render :json => #maintemplate.to_json(:include => { :routine => { :include => :user, :user => { :only => :name } } } )
Add to as_json method with the additional method-attributes you desire to the class in which you are calling.
class MainTemplate
...
def name
User.find(self.user_id).name
end
def as_json(options = {})
options[:methods] = :name
super(options)
end
end

Resources