To display address profile fields as markers on a google map, the address field objects need to be passed as json objects to javascript.
When calling to_json on an ApplicationRecord object, the database attributes are automatically exposed.
Given a ProfileFields::Address model with label, value, longitude and latitude attributes, address_field.as_json results in a Hash, e.g. representation,
address_field.as_json # =>
{label: "Work address", value: "Willy-Brandt-Straße 1\n10557 Berlin",
longitude: ..., latitude: ...}
which is converted to a json string by to_json:
address_field.to_json # =>
"{\"label\":\"Work address\",\"value\":\"Willy-Brandt-Straße 1\\n
10557 Berlin\",\"longitude\":...,\"latitude\":...}"
This is useful because it allows to use label and value later in javascript, for example to show tool tips for the map markers.
Other virtual attributes can be exposed by overriding the as_json method.
For example, to expose a title attribute, include it in the merged as_json hash:
# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
# ...
# For example: "John Doe, Work address"
def title
"#{self.parent.name}, #{self.label}"
end
def as_json
super.merge {
title: self.title
}
end
end
The above example uses super to call the original as_json method, which returns the original attribute hash of the object, and merges it with the required position hash.
To understand the difference between as_json and to_json, have a look at this blog post by jjulian.
To render markers, the google maps api, by default, requires a position hash which has longitude and latitude stored as lng and lat respectively.
This position hash can be created in javascript, later, or here when defining the json representation of the address field:
To provide this position as json attribute of the address field, just override the as_json method on the model.
# app/models/profile_fields/address.rb
class ProfileFields::Address < ProfileFields::Base
# ...
def as_json
super.merge {
# ...
position: {
lng: self.longitude,
lat: self.latitude
}
}
end
end