Change variable name in jbuilder - ruby-on-rails

I'm trying to get a JSON output using jbuilder that looks like this:
[{"correct_response": 0,
"section_id": 1,
"image_url": "https://850.s3.amazonaws.com/uploads/question/3/PreguntaWeb.png?AWSAccessKeyId=AKIAJSKXBBJ4URBWSPUQ&Signature=r8COJLWNWABfwlm6BQ4ZpPlvFGw%3D&Expires=1401509509",
"responses": [{
"responseA": "https://850.s3.amazonaws.com/uploads/response/1/alternativaA.png?AWSAccessKeyId=AKIAJSKXBBJ4URBWSPUQ&Signature=MkUUT7NuoHDH/BjiJdMiHV5f%2BB4%3D&Expires=1401509509"},
{"responseB": "https://850.s3.amazonaws.com/uploads/response/2/alternativaB.png?AWSAccessKeyId=AKIAJSKXBBJ4URBWSPUQ&Signature=EZ6KeqhzlwPGX1PAetvqR/GPH2M%3D&Expires=1401509509"},
{"responseC": "https://850.s3.amazonaws.com/uploads/response/3/alternativaC.png?AWSAccessKeyId=AKIAJSKXBBJ4URBWSPUQ&Signature=/Ntt6y4JrfVjjw0zpOKgIXtihvI%3D&Expires=1401509509"},
{"responseD": "https://850.s3.amazonaws.com/uploads/response/4/alternativaD.png?AWSAccessKeyId=AKIAJSKXBBJ4URBWSPUQ&Signature=Exrr0WTsSx2n3FixjwADiiwwPjM%3D&Expires=1401509509"},
{"responseAE": "https://850.s3.amazonaws.com/uploads/response/5/alternativaE.png?AWSAccessKeyId=AKIAJSKXBBJ4URBWSPUQ&Signature=udJ5jK/zG9ug8A6WwsnhYZRcsPk%3D&Expires=1401509509"}
]
}]
I think I'm close, but I don't know what is wrong with my code:
json.array!(#questions) do |json, question|
json.extract! question, :correct_response, :section_id, :image_url
json.responses question.responses do |response|
[ 'responseA', 'responseB', 'responseC', 'responseD', 'responseE' ].each { |letter|
response.set!(letter, response.image_url )
}
end
end
end
Someone has any suggestions?

Related

jbuilder empty array removes key

My Controller Returns the #quotes, which can be an empty array.
I then render the following view.
json.set! :quotes do
#quotes.each do |quote|
json.set! quote.id do
json.id quote.id
json.symbol quote.symbol
json.price quote.price
json.datetime quote.datetime
end
end
end
This typically results in
"quotes": {
"123": {
"id": 123,
"symbol": "AAPL",
"price": 100,
"datetime": "2019-12-31T16:00:00.000Z"
},
However if #quotes is an empty array the response is
{}
When I want
{
"quotes": {}
}
Is there a way to achieve my goal without an explicit check if the object is empty?
I Do Not want todo
if #quotes.empty?
json.quotes({})
else
-- I am using Jbuilder 2.7
I advice you to use jb gem. It is simple to move from jbuilder to jb (i was doing it on production project). Jb few time faster than jbuilder and do not have ugly jbuilder syntax, it is just plain ruby.
Your problem can be solved in jb
json = { quotes: {} }
#quotes.each do |quote|
json[:quotes][quote.id] = {
...
}
end
json

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

Rails 4: Parsing JSONAPI using representable gem

I have the following working representer working for flat JSON:
# song_representer_spec.rb
require 'rails_helper'
require "representable/json"
require "representable/json/collection"
class Song < OpenStruct
end
class SongRepresenter < Representable::Decorator
include Representable::JSON
include Representable::JSON::Collection
items class: Song do
property :id
nested :attributes do
property :title
end
end
end
RSpec.describe "SongRepresenter" do
it "does work like charm" do
songs = SongRepresenter.new([]).from_json(simple_json)
expect(songs.first.title).to eq("Linoleum")
end
def simple_json
[{
id: 1,
attributes: {
title: "Linoleum"
}
}].to_json
end
end
We are now implementing the specifications of JSONAPI 1.0 and I cannot figure out how to implement a representer able to parse the following json:
{
"data": [
"type": "song",
"id": "1",
"attributes":{
"title": "Linoleum"
}
]
}
Thank you in advance for hints and suggestions
Update:
Gist containing a working solution
require 'representable/json'
class SongRepresenter < OpenStruct
include Representable::JSON
property :id
property :type
nested :attributes do
property :title
end
end
class AlbumRepresenter < Representable::Decorator
include Representable::JSON
collection :data, class: SongRepresenter
end
hash = {
"test": 1,
"data": [
"type": "song",
"id": "1",
"attributes":{
"title": "Linoleum"
}
]
}
decorator = AlbumRepresenter.new(OpenStruct.new).from_json(hash.to_json)
You can now iterate your data array and access to SongRepresenter properties:
2.2.1 :046 > decorator = AlbumRepresenter.new(OpenStruct.new).from_json(hash.to_json)
=> #<OpenStruct data=[#<SongRepresenter id="1", type="song", title="Linoleum">]>
2.2.1 :047 > decorator.data
=> [#<SongRepresenter id="1", type="song", title="Linoleum">]
Please note the difference using hash or JSON.parse(hash.to_json)
2.2.1 :049 > JSON.parse(hash.to_json)
=> {"test"=>1, "data"=>[{"type"=>"song", "id"=>"1", "attributes"=>{"title"=>"Linoleum"}}]}
2.2.1 :050 > hash
=> {:test=>1, :data=>[{:type=>"song", :id=>"1", :attributes=>{:title=>"Linoleum"}}]}
So, using AlbumRepresenter.new(OpenStruct.new).from_hash(hash) doesn't works, because symbolized keys.

Rails jbuilder: how to build a JSON from an array with the key equals to the array values

I'm a pretty new Rails developer, I'm using Jbuilder to build my view in the following way:
[:aaa, :bbb, :ccc].each do |value|
json.value do |json| #<------ Here is my error!
json.partial! foo.send(value)
end
end
Everything works BUT the json.value, my response is the following (obviously):
[{
"value" => {...}
"value" => {...}
"value" => {...}
}]
I'd like to have this one instead:
[{
"aaa" => {...}
"bbb" => {...}
"ccc" => {...}
}]
Any ideas?
From the guide:
To define attribute and structure names dynamically, use the set!
method:
json.set! :author do
json.set! :name, 'David'
end
# => "author": { "name": "David" }
The solution is so:
[:aaa, :bbb, :ccc].each do |value|
json.set! value do |json|
json.partial! foo.send(value)
end
end

Ruby map JSON multiple but not all attributes with RABL

I have the following Rabl in my views:
node(:relations) do |p|
related = p.relations.pluck(:related_to_id)
Spree::Product.find(related)
end
This renders the following:
"relations": [
{
"product": {
"id": 2,
"name": "T-SHIRT",
"description": "Awesome T shirts"
"created_at": "..."
"updated_at: "..."
.
.
.
bunch of other columns that I don't need.
My question is how do I only grab :name and :description, so that the JSON output looks like:
"relations": [
{
"product": {
"name": "T-SHIRT",
"description": "Awesome T shirts"
}
]
I've tried mapping it, Spree::Product.find(related).map { |r| [r.name, r.description] }
But that returns only the values, like so:
"relations": [
"T-SHIRT",
"Awesome T shirts"
]
Thank you for your help!
UPDATE:
When I write:
child :related_products do
attributes :name, :description
end
I get:
"spree_relations": [
{}
]
Link to model:
https://github.com/spree-contrib/spree_related_products/blob/master/app/models/spree/relation.rb
Well, there probably multiple ways to do it.
You can use rails #as_json method.
node(:relations) do |p|
related = p.relations.pluck(:related_to_id)
Spree::Product.find(related).as_json(only: [:name, :description])
end
Or you can try to do it the rabl way.
child :related_products do
attributes :name, :description
end
But for this you might need to change your model a bit.

Resources