In my ruby on rails application am getting below data from API service, the data format is array of hashes like below.
data = [
{"category": "Population.Behaviors.Commute", "tag": "away", "description": "Work Outside the Home"},
{"category": "Population.Behaviors.Commute.Vehicle", "tag": "mbike", "description": "Bike to Work"}
]
The above code format I have to convert to the below format for generating the form elements.
response_format = [
{
"label": "Population",
"options": [
{
"label": "Behaviors",
"options": [
{
"label": "Commute",
"options": [
{
"label": "Vehicle",
"options": [
{
"tag": "mbike",
"description": "Bike to Work"
}
]
},
{
"tag": "away",
"description": "Work Outside the Home"
}
]
}
]
}
]
}
]
Anyone kindly help to achieve the solution.
All you need is to recursively build an inner hash:
data.
each_with_object(Hash.new { |h, k| h[k] = h.dup.clear }) do |h, acc|
(h[:category].split('.').
reduce(acc) do |inner, cat|
inner["label"] = cat
inner["options"] ||= {}
end || {}).
merge!("tag" => h[:tag], "description" => h[:description])
end
#⇒ {
# "label" => "Population",
# "options" => {
# "label" => "Behaviors",
# "options" => {
# "label" => "Commute",
# "options" => {
# "description" => "Work Outside the Home",
# "label" => "Vehicle",
# "options" => {
# "description" => "Bike to Work",
# "tag" => "mbike"
# },
# "tag" => "away"
# }
# }
# }
# }
Related
I am trying to load data from redis db. I have a api only rails app and trying to render the json data as per requirement.
Currently I am able to get the data from redis in the following format.
[
{
"id": 1,
"name": "Stephenie Meyer",
"created_at": "2018-04-17T07:40:50.417Z",
"updated_at": "2018-04-17T07:40:50.417Z"
},
{
"id": 2,
"name": "V.C. Andrews",
"created_at": "2018-04-17T07:40:50.613Z",
"updated_at": "2018-04-17T07:40:50.613Z"
},
{
"id": 3,
"name": "Sophie Kinsella",
"created_at": "2018-04-17T07:40:50.646Z",
"updated_at": "2018-04-17T07:40:50.646Z"
}
]
How can convert this in a way such that the key value pairs of name,created and updated will be hash to a id key-value pair.
Into this
{"id": 1,
{
"name": "Stephenie Meyer",
"created_at": "2018-04-17T07:40:50.417Z",
"updated_at": "2018-04-17T07:40:50.417Z"
}
}
helper method for getting redis data.
def fetch_authors
authors = $redis.get('authors')
if authors.nil?
authors = Author.all.to_json
$redis.set("authors", authors).to_json
$redis.expire("authors", 5.hour.to_i)
end
JSON.load authors
end
And displaying on index page using
def index
#authors = fetch_authors
render json: #authors
end
The closest to what you want would probably be:
input = ...
input.map { |hash| [hash.delete(:id) || hash.delete('id'), hash] }.to_h
#⇒ {{1=>{:name=>...},
# {2=>{:name=>...},
# {3=>{:name=>...}}
Not exactly what you want because that's not correct syntax but you can achieve something similar with group_by
arr = [
{
"id": 1,
"name": "Stephenie Meyer",
"created_at": "2018-04-17T07:40:50.417Z",
"updated_at": "2018-04-17T07:40:50.417Z"
},
{
"id": 2,
"name": "V.C. Andrews",
"created_at": "2018-04-17T07:40:50.613Z",
"updated_at": "2018-04-17T07:40:50.613Z"
},
{
"id": 3,
"name": "Sophie Kinsella",
"created_at": "2018-04-17T07:40:50.646Z",
"updated_at": "2018-04-17T07:40:50.646Z"
}
]
arr.group_by { |e| e[:id] }
This will return
{
1 => [
{
:id => 1,
:name => "Stephenie Meyer",
:created_at => "2018-04-17T07:40:50.417Z",
:updated_at => "2018-04-17T07:40:50.417Z"
}
],
2 => [
{
:id => 2,
:name => "V.C. Andrews",
:created_at => "2018-04-17T07:40:50.613Z",
:updated_at => "2018-04-17T07:40:50.613Z"
}
],
3 => [
{
:id => 3,
:name => "Sophie Kinsella",
:created_at => "2018-04-17T07:40:50.646Z",
:updated_at => "2018-04-17T07:40:50.646Z"
}
]
}
I have a each :
{
"type": "FeatureCollection",
"features": [
<% #pois.each do |poi| %>
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [<%= poi.longitude %>, <%= poi.latitude %> ]
},
<% end %>
]
}
I want to delete the last comma for the last iteration. How can I do ?
It's not a json, but a Geojson.
I would have something like this :
{
"type": "FeatureCollection",
"features": [
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.484957, 44.6044089 ]
},
"properties": {}
},
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [2.3749903, 44.5656783 ]
},
"properties": {}
}
]
}
All it's ok, I just want delete the last comma ;)
As you are probably interested in transforming an array into another array, you can use map instead of each, i.e.,
{
"type": "FeatureCollection",
"features":
<% #pois.map do |poi| %>
{
"type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [<%= poi.longitude %>, <%= poi.latitude %> ]
}
}
<% end %>
}
I presume you're trying to create/edit a JSON object of some sort.
You should not handle JSON objects in this manner.
Instead use the ActiveModel::Serializers
From ActiveModel::Serializers
user = User.find(1)
user.as_json
# => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
# "created_at" => "2006/08/01", "awesome" => true}
ActiveRecord::Base.include_root_in_json = true
user.as_json
# => { "user" => { "id" => 1, "name" => "Konata Izumi", "age" => 16,
# "created_at" => "2006/08/01", "awesome" => true } }
I have a little problem. Can you tell me why permit method cannot return data_set_users_attributes and data_set_synch_agents_attributes in second example from code below? This is weird. All data looks fine, permit arguments too. Both parameters_hash are send from this same form and both permit data are created by this same function.
EDIT: I use Ruby 2.3.0 and rails 4.2.4
require 'rails/all'
# Params passes
_permit = [
"configuration_id",
"max_packages_on_server",
"reports_synch_interval_min",
{
"data_set_users_attributes" => [
{
"0" => [
"user_id",
"send_alerts",
"_destroy"
]
},
{
"2015_09_09_15_21_50" => [
"user_id",
"send_alerts",
"_destroy"
]
}
]
},
{
"data_set_synch_agents_attributes" => [
{
"0" => [
"synch_agent_id",
"max_idle_on_data_set",
"_destroy"
]
},
{
"2015_09_09_15_21_51" => [
"synch_agent_id",
"max_idle_on_data_set",
"_destroy"
]
}
]
}
]
parameters_hash = {
"action" => "create",
"commit" => "Save",
"controller" => "data_sets",
"data_set" => {
"configuration_id" => "",
"data_set_synch_agents_attributes" => {
"0" => {
"_destroy" => "false",
"max_idle_on_data_set" => "-1",
"synch_agent_id" => "1"
},
"2015_09_09_15_21_51" => {
"_destroy" => "",
"max_idle_on_data_set" => "-1",
"synch_agent_id" => "2"
}
},
"data_set_users_attributes" => {
"0" => {
"_destroy" => "false",
"send_alerts" => "1",
"user_id" => "1"
},
"2015_09_09_15_21_50" => {
"_destroy" => "",
"send_alerts" => "1",
"user_id" => "2"
}
},
"max_packages_on_server" => "",
"reports_synch_interval_min" => ""
}
}
params = ActionController::Parameters.new(parameters_hash)
p params.require(:data_set).permit(_permit)
# Params not passes
_permit = [
"configuration_id",
"max_packages_on_server",
"reports_synch_interval_min",
{
"data_set_users_attributes" => [
{
"0" => [
"user_id",
"send_alerts",
"_destroy"
]
},
{
"1" => [
"user_id",
"send_alerts",
"_destroy"
]
}
]
},
{
"data_set_synch_agents_attributes" => [
{
"0" => [
"synch_agent_id",
"max_idle_on_data_set",
"_destroy"
]
},
{
"1" => [
"synch_agent_id",
"max_idle_on_data_set",
"_destroy"
]
}
]
}
]
parameters_hash = {
"action" => "create",
"commit" => "Save",
"controller" => "data_sets",
"data_set" => {
"configuration_id" => "",
"data_set_synch_agents_attributes" => {
"0" => {
"_destroy" => "false",
"max_idle_on_data_set" => "-1",
"synch_agent_id" => "1"
},
"1" => {
"_destroy" => "false",
"max_idle_on_data_set" => "-1",
"synch_agent_id" => "2"
}
},
"data_set_users_attributes" => {
"0" => {
"_destroy" => "false",
"send_alerts" => "1",
"user_id" => "1"
},
"1" => {
"_destroy" => "false",
"send_alerts" => "1",
"user_id" => "2"
}
},
"max_packages_on_server" => "",
"reports_synch_interval_min" => ""
}
}
params = ActionController::Parameters.new(parameters_hash)
p params.require(:data_set).permit(_permit)
Any help will be appreciated.
Best regards
If I get it right, you need to try this:
params.require(:data_set).permit(
:max_packages_on_server,
:reports_synch_interval_min,
data_set_synch_agents_attributes: [:synch_agent_id, :max_idle_on_data_set, :_destroy],
data_set_users_attributes: [:send_alerts, :user_id, :_destroy])
to get parameters for updating your model.
I have the following code which is taking results from an api call and providing it to my front-end as json:
notes = { :notes => [] }
json['Response']['OperationResponse']['Notes']['Note'].each do |note|
notes[:notes] << [:user => note['User'], :time_stamp => note['TimeStamp'], :text => note['Text']]
end
render :json => notes.to_json
but I'm getting this format:
{
"notes": [
[
{
"time_stamp": "test",
"user": "test",
"text": "test"
}
],
[
{
"time_stamp": "test",
"user": "test",
"text": "test"
}
],
....
Instead of this desired format:
{
"notes": [
[
{
"time_stamp": "test",
"user": "test",
"text": "test"
},
{
"time_stamp": "test",
"user": "test",
"text": "test"
},
....
Try with
json['Response']['OperationResponse']['Notes']['Note'].each do |note|
notes[:notes] << {:user => note['User'], :time_stamp => note['TimeStamp'], :text => note['Text']}
end
You are pushing the element as an array [], use {} instead.
I am grabbing value data: name, uid, highschool_name, graduateschool_name like this:
def add_friends
facebook.get_connections("me", "friends", :fields => "name, id, education").each do |hash|
self.friends.where(:name => hash['name'],
:uid => hash['id'],
:highschool_name => hash['education']['school']['name'] unless hash["education"].blank?,
:graduateschool_name => hash['education']['school']['name'] unless hash["education"].blank?).
first_or_create
end
end
From an array of hash:
"education": [
{
"school": {
"id": "110703012290674",
"name": "Kunskapsgymnasiet Malmö"
},
"year": {
"id": "136328419721520",
"name": "2009"
},
"type": "High School"
},
{
"school": {
"id": "112812485399398",
"name": "Malmö University"
},
"year": {
"id": "118118634930920",
"name": "2012"
},
"concentration": [
{
"id": "104076956295773",
"name": "Computer Science"
}
],
"type": "Graduate School",
"classes": [
{
"id": "165093923542525",
"name": "Programmering",
"description": "Kursen fokuserar på metoder och tekniker vid utveckling av webbapplikationer med hjälp av HTML5."
}
]
}
],
EDIT:
This code dosent work. I would like to pick every hichschool and Graduate School from this array of hash and save it.
high_schools = response['education'].collect{|ed| ed['school']['name'] if ed['type'] == "High School" }
grad_schools = response['education'].collect{|ed| ed['school']['name'] if ed['type'] == "Graduate School" }