master
 1class Location < ApplicationRecord
 2  belongs_to :locatable, polymorphic: true, optional: true
 3  before_save :assign_coordinates
 4  acts_as_mappable default_units: :kms,
 5    distance_field_name: :distance,
 6    lat_column_name: :latitude,
 7    lng_column_name: :longitude
 8
 9  def full_address
10    [
11      try(:address),
12      try(:city),
13      try(:region),
14      try(:country)
15    ].join(", ")
16  end
17
18  def coordinates
19    latitude == 0.0 && longitude == 0.0 ? [] : [latitude, longitude]
20  end
21
22  def url
23    "https://maps.google.com/?q=#{latitude},#{longitude}"
24  end
25
26  class << self
27    def build_from_ip(ip)
28      result = search(ip)
29      return nil if result.nil?
30      new(
31        address: result.address,
32        city: result.city,
33        region: result.state_code,
34        country: result.country_code,
35        postal_code: result.postal_code,
36        latitude: result.latitude,
37        longitude: result.longitude,
38      )
39    end
40
41    def from(address, city, region, country)
42      result = search("#{address}, #{city}, #{region}, #{country}")
43      result.present? ? result.coordinates : [nil, nil]
44    end
45
46    def search(query)
47      results = Geocoder.search(query)
48      results.any? ? results.first : nil
49    end
50  end
51
52  private
53
54  def assign_coordinates
55    return if latitude.present? || longitude.present?
56    self.latitude, self.longitude =
57      Location.from(address, city, region, country)
58  end
59end