Class: AverageMonthlyTemperature

Inherits:
ApplicationRecord show all
Includes:
Models::Auditable
Defined in:
app/models/average_monthly_temperature.rb

Overview

== Schema Information

Table name: average_monthly_temperatures
Database name: primary

id :integer not null, primary key
average_annual_temperature :float
average_temperatures :float is an Array
lat :float
lng :float
postal_code :string(255)
temperature_variations :float is an Array
created_at :datetime not null
updated_at :datetime not null

Indexes

index_average_monthly_temperatures_on_average_annual_temperatur (average_annual_temperature)
index_average_monthly_temperatures_on_left_three_postal_code ("left"((postal_code)::text, 3))
index_average_monthly_temperatures_on_postal_code (postal_code)

Constant Summary

Constants included from Models::Auditable

Models::Auditable::ALWAYS_IGNORED

Instance Attribute Summary collapse

Class Method Summary collapse

Methods included from Models::Auditable

#all_skipped_columns, #audit_reference_data, #creator, #should_not_save_version, #stamp_record, #updater

Methods inherited from ApplicationRecord

ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation

Methods included from Models::EventPublishable

#publish_event

Instance Attribute Details

#average_annual_temperatureObject (readonly)



26
# File 'app/models/average_monthly_temperature.rb', line 26

validates :postal_code, :lat, :lng, :average_temperatures, :temperature_variations, :average_annual_temperature, presence: true

#average_temperaturesObject (readonly)



26
# File 'app/models/average_monthly_temperature.rb', line 26

validates :postal_code, :lat, :lng, :average_temperatures, :temperature_variations, :average_annual_temperature, presence: true

#latObject (readonly)



26
# File 'app/models/average_monthly_temperature.rb', line 26

validates :postal_code, :lat, :lng, :average_temperatures, :temperature_variations, :average_annual_temperature, presence: true

#lngObject (readonly)



26
# File 'app/models/average_monthly_temperature.rb', line 26

validates :postal_code, :lat, :lng, :average_temperatures, :temperature_variations, :average_annual_temperature, presence: true

#postal_codeObject (readonly)



26
# File 'app/models/average_monthly_temperature.rb', line 26

validates :postal_code, :lat, :lng, :average_temperatures, :temperature_variations, :average_annual_temperature, presence: true

#temperature_variationsObject (readonly)



26
# File 'app/models/average_monthly_temperature.rb', line 26

validates :postal_code, :lat, :lng, :average_temperatures, :temperature_variations, :average_annual_temperature, presence: true

Class Method Details

.get_forecast_for(latitude, longitude, datetime) ⇒ Object



96
97
98
99
# File 'app/models/average_monthly_temperature.rb', line 96

def self.get_forecast_for(latitude, longitude, datetime)
  Rails.logger.debug("AverageMonthlyTemperature.get_forecast_for(#{latitude}, #{longitude}, #{datetime})")
  Weather::VisualCrossingClient.new.get_forecast_for(latitude, longitude, datetime)
end

.get_from_postal_code(code) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
# File 'app/models/average_monthly_temperature.rb', line 30

def self.get_from_postal_code(code)
  postal_code = if code.to_s.strip[0..2].to_i.positive?
                  # We want US 5 numbered ZIP code
                  code.to_s.strip.delete(' ').delete('-')[0..4]
                else
                  # We want Canadian 6 letter/number postal code
                  code.to_s.strip.delete(' ').delete('-')[0..5]
                end
  res = AverageMonthlyTemperature.where(postal_code:postal_code).first
  unless res
    temp_data = AverageMonthlyTemperature.get_monthly_temperature_data_for_postal_code(postal_code)
    if temp_data
      res = AverageMonthlyTemperature.create(postal_code:postal_code, average_temperatures: temp_data['average_temperatures'],
                                             temperature_variations: temp_data['temperature_variations'], lat: temp_data['latitude'], lng: temp_data['longitude'], average_annual_temperature: temp_data['average_annual_temperature'] || temp_data['average_temperatures'].average.round(2))
    else
      res = nil
    end
  end
  if res&.valid?
    { average_temperatures: res.average_temperatures, temperature_variations: res.temperature_variations,
      average_annual_temperature: res.average_annual_temperature, status: :ok }
  else
    { status: :error, message: res&.errors&.full_messages&.join(', ') || "Can't find temperature data for postal code: #{postal_code}" }
  end
end

.get_monthly_temperature_data_for_lat_lng(lat, lng) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'app/models/average_monthly_temperature.rb', line 67

def self.get_monthly_temperature_data_for_lat_lng(lat, lng)
  res = {}
  res['average_temperatures'] = []
  res['temperature_variations'] = []
  # here we round to 0 decimal places which gives us ~90 miles resolution, ok for temperature variation, but improves caching
  latitude = lat.round
  longitude = lng.round
  res['latitude'] = latitude
  res['longitude'] = longitude
  Rails.cache.fetch("monthly_temperature_data_for_lat_lng:#{[latitude, longitude].inspect}", expires_in: 3.months) do
    12.times do |i|
      month = i + 1
      t = Time.zone.local(Time.zone.now.year + 5, month, 1)
      # puts "calculate_heat_loss, t: #{t}"
      forecast = AverageMonthlyTemperature.get_forecast_for(latitude, longitude, t)
      if forecast['temp']
        res['average_temperatures'] << forecast['temp']
        res['temperature_variations'] << (forecast['tempmax'] - forecast['tempmin'])
      else
        res['error'] = 'Forecast could not be determined for this location!'
        raise StandardError, res['error']
        break
      end
    end
    res['average_annual_temperature'] = res['average_temperatures'].average.round(2)
    res
  end
end

.get_monthly_temperature_data_for_postal_code(postal_code) ⇒ Object



56
57
58
59
60
61
62
63
64
65
# File 'app/models/average_monthly_temperature.rb', line 56

def self.get_monthly_temperature_data_for_postal_code(postal_code)
  res,lat,lng = nil
  begin
    lat, lng = Address.geocode_address_string("#{postal_code}, North America")
    res = AverageMonthlyTemperature.get_monthly_temperature_data_for_lat_lng(lat, lng) if lat && lng
  rescue StandardError => exc
    ErrorReporting.warning(exc, { postal_code: postal_code, lat: lat, lng: lng })
  end
  res
end