Ruby on Rails Using GoogleMaps with Rails Exposing the model properties as json


Example

To display address profile fields as markers on a google map, the address field objects need to be passed as json objects to javascript.

Regular database attributes

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 attributes

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.

Position

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