How can I create this JSON structure with JBuilder and Rails? - ruby-on-rails

TL;DR:
How can i use jbuilder to create JSON that looks like this?
[
{}, // Your new pagination state
[{}, ...] // An array of JSON objects
]
Longer version:
I am trying get pagination working with Backbone.js and backbone-pageable https://github.com/wyuenho/backbone-pageable .
Backbone-pageable requires that the JSON returned be formatted such that it's an array of two objects. The first object is a regular object containing pagination control information. The second object should be an array of your actual data formatted as Backbone would normally expect. These expectations are hard coded into backbone-pageable's parse methods (source)
It seems weird to have an array of un-like items but for this use case it seems acceptable.
For json i've used rabl in the past but for science I'm trying to use jbuilder and I've gotten this far...
JSON structure (wrong):
{
"current_page": 1,
"total_pages": 6,
...,
"entries": [
{ "id": 131 },
...
]
}
Using this code:
json.current_page #posts.current_page
...
json.entries #posts do |post|
json.extract! post, :id...
end
Closer, but still very wrong :/
Thank you

Can you try this:
json.array! [0,1] do |index|
if index == 0
json.current_page #posts.current_page
...
else
json.entries #posts do |post|
json.extract! post, :id...
end
end
end

Related

How can I add an element/field/column when rendering JSON in Rails?

Let's say you have a model called Widget which includes :id and :name.
In your Widget#index endpoint, you want to render all widgets in json, however... you also want to include another value for each record that isn't apart of the model called foobar. So you want the end result to look like this...
{
"widgets": [
{
"id":, 1,
"name": "widgy",
"foobar": true
},
{
"id":, 2,
"name": "gadgy",
"foobar": false
}
]
}
How can you edit the following code to allow for something like this?
widgets = Widget.all
render json: widgets
Depending on the version of Rails you're running, you could choose to use active_model_serializers or a simple jbuilder view.
Rails 4 already includes the jbuilder gem, so you don't need to include anything special in your Gemfile.
Cheers!

Iterating through JSON data from external API in Rails

I have a function return_summoner_champion_list(name) that will return the following JSON data when called
[
{
"id"=>"1",
"name"=>"A"
},
{
"id"=>"2",
"name"=>"B"
},
and so on...
]
How do I iterate through the JSON array and print out all ids?
I tried
return_summoner_champion_list(name).each do |list|
puts list["id"]
end
but it still returns the same JSON data as above without any changes.
I think you're looking for Array#collect not Array#each:
return_summoner_champion_list(name).collect{|l| l['id']}
=> [1,2, ...]
Is your method returning JSON or an Ruby array? If it is indeed returning JSON, first convert that to an array with JSON.parse(), and then work with the array that is returned.

Constructing a nested JSON request with Jbuilder

Currently my JSON request is returning the below, where each person/lender has many inventories.
#output of /test.json
[
{"id":13, "email":"johndoe#example.com", "inventories":
[
{"id":10,"name":"2-Person Tent","category":"Camping"},
{"id":11,"name":"Sleeping bag","category":"Camping"},
{"id":27,"name":"6-Person Tent","category":"Camping"}
]
},
{"id":14, "email":"janedoe#example.com", "inventories":
[
{"id":30,"name":"Electric drill","category":"Tools"},
{"id":1,"name":"Hammer","category":"Tools"},
{"id":37,"name":"Plane","category":"Tools"}
]
}
]
I need to nest in one more thing and am having trouble doing so. For context, each inventory item is referenced via it's id as a foreign key in a borrow record. Each borrow record belongs to a request parent that stores returndate and pickupdate. What I need now, is for each inventory item, to nest an array of all the request records, with information on pickupdate and returndate. In other words, desired output:
[
{"id":13, "email":"johndoe#example.com", "inventories":
[
{"id":10,"name":"2-Person Tent","category":"Camping", "requests":
[
{"id":1, "pickupdate":"2014-07-07","returndate":"2014-07-10"},
{"id":2, "pickupdate":"2014-06-02","returndate":"2014-06-05"},
{"id":3, "pickupdate":"2014-08-14","returndate":"2014-08-20"}
]
},
{"id":11,"name":"Sleeping bag","category":"Camping", "requests":
[
{"id":4, "pickupdate":"2014-05-27","returndate":"2014-05-30"},
{"id":5, "pickupdate":"2014-04-22","returndate":"2014-04-25"}
]
},
{"id":27,"name":"6-Person Tent","category":"Camping", "requests":
[
{"id":6, "pickupdate":"2014-07-10","returndate":"2014-07-12"}
]
}
]
},
{"id":14, "email":"janedoe#example.com", "inventories":
...
I have written the following code:
json.array!(#lenders) do |json, lender|
json.(lender, :id, :email)
json.inventories lender.inventories do |json, inventory|
json.id inventory.id
json.name Itemlist.find_by_id(inventory.itemlist_id).name
#code below says, json.requests should equal all the Requests where there is a Borrows within that Request that is using the Inventory in question
json.requests Request.select { |r| r.borrows.select { |b| b.inventory_id == inventory.id }.present? } do |json, request|
json.pickupdate request.pickupdate
json.returndate request.returndate
end
end
end
When I refresh the page, I get wrong number of arguments (0 for 2..5)
I feel like the issue is that the Request.select... is returning an Array which isn't what needs to go here... but in the earlier nested function lender.inventories is an Inventory::ActiveRecord_Associations_CollectionProxy though I'm not sure how to correct for this.
NOTE: Someone said the problem could be that unlike with the nesting between inventories and lender, there's not an explicit association between inventory and request, but then again the line json.name Itemlist.find_by_id(inventory.itemlist_id).name worked so I'm not sure this is right. (Also if this is the case, I'm not sure how to bypass this limitation... I currently don't want to create a relationship between the two.)
Thanks!
ARG. Ok so this code is perfectly right. The issue was that I"m using the Gon gem in conjunction with Jbuilder, and Request is a predefined class in Gon.
So just changed code to
#requestrecords.select....
And in the controller:
#requestrecords = Request.all
-__-

Rails JSON Response Issue

I'm trying to build a simple API using Ruby on Rails which returns some statistics about tickets from an OTRS database.
Currently when I call my API for the following call, it is returning the below response.
API Call
http://localhost:3000/api/openvsclosed
Current Response
[[1,1,1],[2,2,2]]
I was wondering how I could get this to appear in the correct format of:
Desired Response
[
{
"Id":1,
"Opened":1,
"Closed":1
},
{
"Id":2,
"Opened":2,
"Closed":2
}
]
Current Controller
def openvsclosed
sql = "SELECT
#ROW := #ROW + 1 AS Id,
COUNT(t.tn) AS Opened,
COUNT(t.tn) AS Closed
FROM
ticket t
CROSS JOIN (SELECT #ROW := 0) AS Row
WHERE
t.create_time > DATE_SUB(CURDATE(), INTERVAL 7 DAY)
GROUP by
DAY(t.create_time)
ORDER by
t.create_time;"
records = ActiveRecord::Base.connection.execute(sql)
render json: records
end
I'm quite new to using Ruby on Rails so I am most likely missing something obvious / big here.
I would recommend checking out jbuilder - you can customize a json template with whatever format you wish for the records you're returning from the controller to the json view.
In this case, you could do something like:
json.array! #records do |json, record|
json.id record.id
json.opened record.opened
json.closed record.closed
end
Alternative is https://github.com/nesquena/rabl, simple to set up, and easy to use

How to create a grouped select from a flat hash of values?

I am pulling a flat hash of parameters from an external API into my Rails app. I need to present these parameters to the user in a select field.
The hash is formatted as follows:
[["Name", "ID", "Category"]]
I'd like to present this as a grouped select. But I believe the grouped_select tag takes a hierarchical hash, not a flat hash?
Is there an easy way to restructure this hash into a structured hash? i.e.,
['CategoryA', [['Name-A1','ID-A1'],['Name-A2', 'ID-A2']]
For reference, I'm currently handling the hash in my controller like this
#hash = session["hash"].map { |h| [ h["name"], h["id"], h["category"] ] }
and in the view
<%= f.select :hash_id, #hash %>
This gives me an unordered list of options. How can I group on h["category"]?
Thanks for any pointers.
EDIT
By the way, I;ve already tried group_by as it seemed the obvious way to go. But I'm getting can't convert String into Integer. Perhaps I'm not using it correctly?
hash.group_by {|h| h["category"] }.map { |h| [ h["name"], h["id"], h["category"] ] }
hash.group_by {|h| h["category"] }.map { |h| [ h[0], h[1].map{|e| [e["name"],e["id"]]} ] }

Resources