Rails - How to remove the last comma in a hash - ruby-on-rails

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

Related

Is there a way to select just one attribute of an outer object by using the Fast JSON API in Rails?

I am creating a travel app which uses a backend Rails API. I've decided to use the Fast JSON API to serialize my data. I have a list of countries; each country has many cities, and each city has many attractions.
These are a list of my associations between my models.
Country.rb
has_many :cities
has_many :attractions, through: :locality
Localities.rb
has_many :attractions
belongs_to :country
Attraction.rb
belongs_to :locality
When I serialize my data for an individual attraction, I would like to include only the name attribute of the city and the name attribute of the country it belongs to. I am currently doing this by adding the optional parameter to include the locality and country name.
def show
attraction = Attraction.find_by(slug: params[:slug])
options = {}
options[:include] = [:locality, :'locality.country.name']
render json: AttractionSerializer.new(attraction, options).serialized_json
end
However, this gives all the attributes and relationships of the country, including a list of all unrelated localities nested within the country, which will become really inefficient when my dataset becomes larger. See below:
{
"data": {
"id": "1",
"type": "attraction",
"attributes": {
"name": "Plaza de España",
"description": "Site of the World Exposition in 1929",
"types": null,
"latitude": 40.4232824,
"longitude": -3.7107257,
"slug": "plaza-de-espana",
"locality": {
"id": 1,
"name": "Seville",
"country_id": 168,
"created_at": "2020-06-10T05:43:47.474Z",
"updated_at": "2020-06-10T05:43:47.474Z",
"slug": "seville",
"latitude": 37.3886303,
"longitude": -5.9953403
}
},
"relationships": {
"locality": {
"data": {
"id": "1",
"type": "locality"
}
}
}
},
"included": [
{
"id": "1",
"type": "locality",
"attributes": {
"name": "Seville",
"latitude": 37.3886303,
"longitude": -5.9953403,
"slug": "seville"
},
"relationships": {
"country": {
"data": {
"id": "168",
"type": "country"
}
}
}
},
{
"id": "168",
"type": "country",
"attributes": {
"name": "Spain",
"slug": "spain",
"iso_3166_1_alpha2": "ES",
"iso_3166_1_alpha3": "ESP",
"iso_3166_1_numeric": "724"
},
"relationships": {
"localities": {
"data": [
{
"id": "1",
"type": "locality"
},
{
"id": "2",
"type": "locality"
},
{
"id": "3",
"type": "locality"
},
{
"id": "4",
"type": "locality"
},
{
"id": "5",
"type": "locality"
},
{
"id": "6",
"type": "locality"
}
]
},
"attractions": {
"data": [
{
"id": "1",
"type": "attraction"
}
]
}
}
}
]
}
Is there a way to only include just one attribute (i.e. name of Country) in the Attraction JSON, instead of the whole object? (Attraction is nested two levels below Country)
Thank you very much.
You need to create multiple serializers that work together to achieve this.
class AttractionSerializer
include FastJsonapi::ObjectSerializer
attributes :attraction_attr_1, :attraction_attr_2, etc.
belongs_to :locality, serializer: AttractionLocalitySerializer
end
class AttractionLocalitySerializer
include FastJsonapi::ObjectSerializer
attributes :name
belongs_to :country, serializer: AttractionCountrySerializer
end
class AttractionCountrySerializer
include FastJsonapi::ObjectSerializer
attributes :name
end

Defining Array of Objects in Swagger Documentation

I'm using swagger for quite a bit now, we have started documenting our code using it, in one place there's an API response which returns multiple objects in the included block.
Example:
{
"data": {
"id": "1",
"type": "schoolPositions",
"attributes": {
"description": "teases the students",
"mustHaves": "principle"
},
"relationships": {
"schoolLocation": {
"data": {
"id": "72",
"type": "schoolLocations"
}
},
"schoolCompensation": {
"data": {
"id": "75",
"type": "schoolCompensations"
}
},
"jobSpecs": {
"data": [
{
"id": "82",
"type": "schoolAttachments"
}
]
}
}
},
"included": [
{
"id": "72",
"type": "schoolLocations",
"attributes": {
"city": "Berhampore",
"state": "West Bengal",
"postalCode": "742101",
"country": "India",
"globalRegionId": 30,
"regionId": 683
}
},
{
"id": "75",
"type": "schoolCompensations",
"attributes": {
"salary": "",
"bonus": "",
"equity": "",
"currencyId": null,
"equityType": "percent",
"salaryDescription": null
}
},
{
"id": "82",
"type": "schoolAttachments",
"attributes": {
"attachmentType": "JobSpecificationAttachmentType",
"fileFileName": "vs.jpg",
"fileContentType": "image/jpeg",
"fileFileSize": 2410039,
"fileUpdatedAt": "2018-12-12T07:06:38Z",
"downloadUrl": "001-vs.jpg?1544598398",
"klass": "SchoolAttachments"
}
}
]
I have wasted an entire day on the internet and documentation trying to document the included part, but I'm going wrong somewhere
response 200 do
key :description, 'School Data'
schema do
property :data do
key :type, :array
items do
key :'$ref', :School
end
end
property :included do
key :type, :array
items do
key :'$ref', :SchoolLocations
key :'$ref', :SchoolCompensations
key :'$ref', :SchoolAttachments
end
end
end
end
This shows only the SchoolAttachments in the included part.
I have tried using allOff but it doesn't work.

How to parse GeoJSON with Ruby and save coordinates to .csv file?

I want to parse a GeoJSON file (Point type) and save the coordinates (lat/lng) to .CSV file. How to do this with Ruby? Following is a GeoJSON file. Thanks in advance!
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"id": 1,
"properties": {
"cluster": {
"x": -0.229559,
"y": 0.270089
}
},
"geometry": {
"type": "Point",
"coordinates": [
-74.1518294,
40.5793043
]
}
},
{
"type": "Feature",
"id": 2,
"properties": {
"cluster": {
"x": 0.00379515,
"y": 0.121912
}
},
"geometry": {
"type": "Point",
"coordinates": [
-74.0818064,
40.9278118
]
}
}, ]}
You may use rgeo-geojson gem to do it:
require 'rgeo/geo_json'
require 'csv'
points = RGeo::GeoJSON.decode(json, json_parser: :json) # json must be a string here
CSV.open("points.csv", "w") do |csv|
csv << ["x", "y"]
points.each do |point|
csv << [point.geometry.x, point.geometry.y]
end
end
If you just want storing lat and lng in csv file,
$ cat geo.json
{ "type": "FeatureCollection",
"features": [
{
"type": "Feature",
"id": 1,
"properties": {
"cluster": {
"x": -0.229559,
"y": 0.270089
}
},
"geometry": {
"type": "Point",
"coordinates": [
-74.1518294,
40.5793043
]
}
},
{
"type": "Feature",
"id": 2,
"properties": {
"cluster": {
"x": 0.00379515,
"y": 0.121912
}
},
"geometry": {
"type": "Point",
"coordinates": [
-74.0818064,
40.9278118
]
}
}
]
}
ruby script
require 'json'
require 'csv'
q = h['features'].map {|e| e['geometry']['coordinates'] }
#=> [[-74.1518294, 40.5793043], [-74.0818064, 40.9278118]]
CSV.open('coords.csv', 'wb') {|csv| q.each {|e|csv << e }}
contents of csv file.
$ cat coords.csv
-74.1518294,40.5793043
-74.0818064,40.9278118
If you also want to store ids, change
q = h["features"].map {|e| [e['id'], e['geometry']['coordinates']].flatten }
if you want to write headers,
CSV.open('coords.csv', "wb") do |csv|
csv << ['ID', 'LAT', 'LNG']
q.each {|e|csv << e }
end
contents of coords
$ cat coords.csv
ID,LAT,LNG
1,-74.1518294,40.5793043
2,-74.0818064,40.9278118

Adding Hash to Array in Rails

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.

Rails - better flow control - loop

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

Resources