forecast 0.0.7 → 0.0.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -13
- data/.gitignore +11 -1
- data/CHANGELOG.md +27 -0
- data/README.md +196 -8
- data/bin/forecast +94 -0
- data/forecast.gemspec +4 -3
- data/lib/forecast/adapter.rb +126 -123
- data/lib/forecast/adapters/forecast_io_adapter.rb +57 -0
- data/lib/forecast/adapters/open_weather_map_adapter.rb +41 -58
- data/lib/forecast/adapters/wunderground_adapter.rb +53 -29
- data/lib/forecast/adapters/yahoo_adapter.rb +21 -29
- data/lib/forecast/collection.rb +4 -4
- data/lib/forecast/conditions.yml +2 -2
- data/lib/forecast/config.rb +4 -5
- data/lib/forecast/config.yml +2 -4
- data/lib/forecast/http.rb +80 -0
- data/lib/forecast/synonyms.yml +32 -0
- data/lib/forecast/themes/weather_icons.yml +10 -8
- data/lib/forecast/utils.rb +101 -6
- data/lib/forecast/version.rb +1 -1
- data/lib/forecast.rb +39 -107
- data/spec/fixtures/locations.yml +21 -0
- data/spec/forecast_spec.rb +58 -27
- data/spec/spec_helper.rb +16 -0
- metadata +28 -22
- data/.README.md.html +0 -480
- data/lib/forecast/adapters/open_weather_map_adapter.yml +0 -18
- data/lib/forecast/cache.rb +0 -7
- data/lib/forecast/model.rb +0 -71
@@ -11,21 +11,13 @@ class Forecast
|
|
11
11
|
forecast = nil
|
12
12
|
doc = get_rss(latitude, longitude)
|
13
13
|
if doc
|
14
|
-
|
14
|
+
hash = {}
|
15
15
|
doc.elements.each('rss/channel/item/yweather:condition') do |elem|
|
16
16
|
elem.attributes.each() do |attr|
|
17
|
-
|
18
|
-
value = attr[1]
|
19
|
-
case name
|
20
|
-
when 'date'
|
21
|
-
forecast.date = DateTime.parse(value)
|
22
|
-
when 'temp'
|
23
|
-
forecast.temp = value.to_i
|
24
|
-
when 'text'
|
25
|
-
forecast.condition = get_condition(value)
|
26
|
-
end
|
17
|
+
hash[attr[0].to_sym] = attr[1]
|
27
18
|
end
|
28
19
|
end
|
20
|
+
forecast = get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
29
21
|
end
|
30
22
|
return forecast
|
31
23
|
end
|
@@ -40,24 +32,11 @@ class Forecast
|
|
40
32
|
forecasts = Forecast::Collection.new
|
41
33
|
if doc
|
42
34
|
doc.elements.each('rss/channel/item/yweather:forecast') do |elem|
|
43
|
-
|
35
|
+
hash = {}
|
44
36
|
elem.attributes.each() do |attr|
|
45
|
-
|
46
|
-
name = attr[0]
|
47
|
-
value = attr[1]
|
48
|
-
case name
|
49
|
-
when 'date'
|
50
|
-
forecast.date = DateTime.parse(value)
|
51
|
-
when 'low'
|
52
|
-
forecast.temp_min = get_temp(value)
|
53
|
-
when 'high'
|
54
|
-
forecast.temp_max = get_temp(value)
|
55
|
-
when 'text'
|
56
|
-
forecast.condition = get_condition(value)
|
57
|
-
end
|
37
|
+
hash[attr[0].to_sym] = attr[1]
|
58
38
|
end
|
59
|
-
|
60
|
-
forecasts << forecast
|
39
|
+
forecasts << get_forecast({latitude: latitude, longitude: longitude}.merge(hash))
|
61
40
|
end
|
62
41
|
end
|
63
42
|
return forecasts
|
@@ -69,7 +48,7 @@ class Forecast
|
|
69
48
|
woeid = nil
|
70
49
|
query = "SELECT * FROM geo.placefinder WHERE text='#{latitude}, #{longitude}' and gflags='R'"
|
71
50
|
url = URL_YQL + "?q=" + URI::encode(query)
|
72
|
-
doc =
|
51
|
+
doc = get_dom(url)
|
73
52
|
doc.elements.each('query/results/Result/woeid') do |elem|
|
74
53
|
woeid = elem.text
|
75
54
|
end
|
@@ -79,12 +58,25 @@ class Forecast
|
|
79
58
|
def get_rss(latitude, longitude)
|
80
59
|
woeid = get_woeid(latitude, longitude)
|
81
60
|
if woeid
|
82
|
-
doc = get_doc(URL_RSS, {w: woeid})
|
61
|
+
doc = Forecast::Utils.get_doc(URL_RSS, {w: woeid})
|
83
62
|
return doc
|
84
63
|
end
|
85
64
|
return nil
|
86
65
|
end
|
87
66
|
|
67
|
+
def get_forecast(hash)
|
68
|
+
forecast = Forecast.new
|
69
|
+
forecast.latitude = hash[:latitude]
|
70
|
+
forecast.longitude = hash[:longitude]
|
71
|
+
forecast.time = get_time(hash[:date])
|
72
|
+
forecast.condition = get_condition(hash[:text])
|
73
|
+
forecast.text = get_text(hash[:text])
|
74
|
+
forecast.temperature_min = get_temperature(hash[:low])
|
75
|
+
forecast.temperature_max = get_temperature(hash[:high])
|
76
|
+
forecast.temperature = get_temperature(hash.has_key?(:temp) ? hash[:temp] : [hash[:low], hash[:high]])
|
77
|
+
return forecast
|
78
|
+
end
|
79
|
+
|
88
80
|
end
|
89
81
|
end
|
90
82
|
end
|
data/lib/forecast/collection.rb
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
class Forecast
|
2
2
|
class Collection < Array
|
3
|
-
def
|
3
|
+
def select_time(time)
|
4
4
|
result = nil
|
5
5
|
date_forecasts = self.select do |obj|
|
6
|
-
obj.
|
6
|
+
obj.time.to_date == time.to_date
|
7
7
|
end
|
8
8
|
if date_forecasts.length == 0
|
9
9
|
return nil
|
10
10
|
else
|
11
11
|
hour_forecasts = date_forecasts.select do |obj|
|
12
|
-
obj.
|
12
|
+
obj.time.hour == obj.time.hour
|
13
13
|
end
|
14
14
|
if hour_forecasts.length > 0
|
15
15
|
return hour_forecasts.first
|
@@ -17,10 +17,10 @@ class Forecast
|
|
17
17
|
return date_forecasts.first
|
18
18
|
end
|
19
19
|
return nil
|
20
|
-
|
21
20
|
end
|
22
21
|
|
23
22
|
private
|
23
|
+
# Unused
|
24
24
|
def seconds_between(date1, date2)
|
25
25
|
((Time.parse(date1.to_s) - Time.parse(date2.to_s)) / 3600).abs
|
26
26
|
end
|
data/lib/forecast/conditions.yml
CHANGED
data/lib/forecast/config.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
|
+
require "yaml"
|
1
2
|
class Forecast
|
2
3
|
class Config
|
3
4
|
|
4
|
-
attr_accessor :adapters, :provider, :
|
5
|
+
attr_accessor :adapters, :provider, :scale, :conditions, :synonyms, :cache, :themes, :theme, :config_file
|
5
6
|
|
6
7
|
def initialize
|
7
8
|
|
8
9
|
@config_file = nil
|
9
|
-
|
10
|
-
|
10
|
+
@provider||= :open_weather_map
|
11
11
|
self.load(File.dirname(__FILE__) + '/**/*.yml')
|
12
12
|
|
13
13
|
def theme
|
@@ -21,11 +21,10 @@ class Forecast
|
|
21
21
|
end
|
22
22
|
return @theme
|
23
23
|
end
|
24
|
-
|
25
24
|
end
|
26
25
|
|
26
|
+
|
27
27
|
def load(pattern)
|
28
|
-
# puts 'load forecast pattern ' + pattern.to_s
|
29
28
|
Dir.glob(pattern).sort{ |a, b| a.split(/\//).length <=> b.split(/\//).length}.reverse.each do |f|
|
30
29
|
obj = YAML.load_file(f)
|
31
30
|
# puts 'load forecast config ' + f.to_s
|
data/lib/forecast/config.yml
CHANGED
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'rexml/document'
|
3
|
+
require 'open-uri'
|
4
|
+
require 'json'
|
5
|
+
require "redis"
|
6
|
+
|
7
|
+
class Forecast
|
8
|
+
|
9
|
+
class Http
|
10
|
+
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = {cache: nil}.merge options
|
13
|
+
if @options[:cache]
|
14
|
+
cache_options = @options[:cache].merge({
|
15
|
+
host: "127.0.0.1",
|
16
|
+
port: "6379"
|
17
|
+
})
|
18
|
+
if cache_options.has_key?(:url)
|
19
|
+
url = cache_options[:url]
|
20
|
+
uri = URI.parse(url)
|
21
|
+
#puts "Connecting to redis with url #{url}..."
|
22
|
+
@cache = Redis.new(host: uri.host, port: uri.port, password: uri.password)
|
23
|
+
elsif host != nil && port != nil
|
24
|
+
#puts "Connecting to redis on host #{host} at port #{port}..."
|
25
|
+
@cache = Redis.new(host: cache_options[:host], port: cache_options[:port])
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def get(url, params = {})
|
31
|
+
if @cache && (!@options[:cache].has_key?(:invalidate) || !@options[:cache][:invalidate])
|
32
|
+
key = get_key(url)
|
33
|
+
data = @cache.get(key)
|
34
|
+
if data
|
35
|
+
#puts 'Read from cache... ' + url
|
36
|
+
return data
|
37
|
+
end
|
38
|
+
end
|
39
|
+
if params.keys.count > 0
|
40
|
+
query_string = URI.encode_www_form(params)
|
41
|
+
url = url + "?" + query_string
|
42
|
+
end
|
43
|
+
#puts 'Get url... ' + url
|
44
|
+
resp = Net::HTTP.get_response(URI.parse(url))
|
45
|
+
data = resp.body
|
46
|
+
if data
|
47
|
+
if @cache
|
48
|
+
#puts 'Write to cache... ' + url
|
49
|
+
key = get_key(url)
|
50
|
+
@cache.set(key, data)
|
51
|
+
if @options[:cache] && @options[:cache].has_key?(:expire)
|
52
|
+
@cache.expire(key, @options[:cache][:expire])
|
53
|
+
end
|
54
|
+
end
|
55
|
+
return data
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def get_json(url, params = {})
|
60
|
+
data = get(url, params)
|
61
|
+
if data != nil
|
62
|
+
return JSON.parse(data)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def get_dom(url, params = {})
|
67
|
+
data = get(url, params)
|
68
|
+
if data != nil
|
69
|
+
return REXML::Document.new(data)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
private
|
75
|
+
def get_key(url)
|
76
|
+
"Forecast::Http::" + url
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
forecast:
|
2
|
+
synonyms:
|
3
|
+
-
|
4
|
+
- 'Clear'
|
5
|
+
- 'Sunny'
|
6
|
+
- 'Sunshine'
|
7
|
+
- 'No Clouds'
|
8
|
+
- 'Fair'
|
9
|
+
- 'Breezy'
|
10
|
+
-
|
11
|
+
- 'Light Rain'
|
12
|
+
- 'Drizzle'
|
13
|
+
- 'Light showers'
|
14
|
+
-
|
15
|
+
- 'Rain'
|
16
|
+
- 'Showers'
|
17
|
+
-
|
18
|
+
- 'Heavy Rain'
|
19
|
+
- 'Thundershowers'
|
20
|
+
-
|
21
|
+
- 'Partly Cloudy'
|
22
|
+
- 'Clouds Sun'
|
23
|
+
- 'Fog Sun'
|
24
|
+
- 'Few Clouds'
|
25
|
+
-
|
26
|
+
- 'Overcast'
|
27
|
+
- 'Cloudy'
|
28
|
+
- 'Clouds'
|
29
|
+
-
|
30
|
+
- 'Storm'
|
31
|
+
- 'Thunderstorm'
|
32
|
+
- 'Blizzard'
|
@@ -1,10 +1,12 @@
|
|
1
1
|
forecast:
|
2
2
|
themes:
|
3
|
-
weather_icons:
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
3
|
+
weather_icons:
|
4
|
+
prefix: 'wi wi-'
|
5
|
+
conditions:
|
6
|
+
Clear: "day-sunny"
|
7
|
+
Partly Cloudy: "sunny-overcast"
|
8
|
+
Cloudy: "day-cloudy"
|
9
|
+
Mostly Cloudy: "cloudy"
|
10
|
+
Light Rain: "showers"
|
11
|
+
Rain: "rain"
|
12
|
+
Heavy Rain: "rain"
|
data/lib/forecast/utils.rb
CHANGED
@@ -7,9 +7,50 @@ class Forecast
|
|
7
7
|
module Utils
|
8
8
|
class << self
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
|
11
|
+
def underscore(string)
|
12
|
+
if string.is_a?(String)
|
13
|
+
return string.gsub(/::/, '/').
|
14
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
15
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
16
|
+
tr("-", "_").
|
17
|
+
downcase
|
18
|
+
elsif string.is_a?(Hash)
|
19
|
+
return Hash[string.map { |k, v| [Forecast::Utils.underscore(k.to_s).to_sym, v.is_a?(Hash) ? Forecast::Utils.underscore(v) : v] }]
|
20
|
+
else
|
21
|
+
string
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def fahrenheit_to_kelvin(fahrenheit)
|
26
|
+
((fahrenheit - 32) / 1.8) - 273.15
|
27
|
+
end
|
28
|
+
|
29
|
+
def fahrenheit_to_celsius(fahrenheit)
|
30
|
+
((fahrenheit - 32) / 1.8)
|
31
|
+
end
|
32
|
+
|
33
|
+
def kelvin_to_fahrenheit(kelvin)
|
34
|
+
return ((kelvin - 273.15) * 1.8 + 32)
|
35
|
+
end
|
36
|
+
|
37
|
+
def kelvin_to_celsius(kelvin)
|
38
|
+
kelvin - 273.15
|
39
|
+
end
|
40
|
+
|
41
|
+
def celsius_to_fahrenheit(celsius)
|
42
|
+
celsius * 1.8 + 32
|
43
|
+
end
|
44
|
+
|
45
|
+
def celsius_to_kelvin(celsius)
|
46
|
+
celsius + 273.15
|
47
|
+
end
|
48
|
+
|
49
|
+
def get_json(url, params = {})
|
50
|
+
if params.keys.count > 0
|
51
|
+
query_string = URI.encode_www_form(params)
|
52
|
+
url = url + "?" + query_string
|
53
|
+
end
|
13
54
|
resp = Net::HTTP.get_response(URI.parse(url))
|
14
55
|
data = resp.body
|
15
56
|
result = JSON.parse(data)
|
@@ -19,14 +60,68 @@ class Forecast
|
|
19
60
|
return nil
|
20
61
|
end
|
21
62
|
|
22
|
-
def get_doc(url, params)
|
23
|
-
|
24
|
-
|
63
|
+
def get_doc(url, params = {})
|
64
|
+
if params.keys.count > 0
|
65
|
+
query_string = URI.encode_www_form(params)
|
66
|
+
url = url + "?" + query_string
|
67
|
+
end
|
25
68
|
xml_data = Net::HTTP.get_response(URI.parse(url)).body
|
26
69
|
doc = REXML::Document.new(xml_data)
|
27
70
|
return doc
|
28
71
|
end
|
29
72
|
|
73
|
+
def word_similarity(first, second)
|
74
|
+
|
75
|
+
if !first.is_a?(String) || !second.is_a?(String)
|
76
|
+
return 0
|
77
|
+
end
|
78
|
+
similar_words = 0.0
|
79
|
+
first_words = first.downcase.split(/\W+/)
|
80
|
+
second_words = second.downcase.split(/\W+/)
|
81
|
+
|
82
|
+
first_words.each do |first_word|
|
83
|
+
second_words.each do |second_word|
|
84
|
+
similar = 0.0
|
85
|
+
if first_word == second_word
|
86
|
+
similar = 1.0
|
87
|
+
else
|
88
|
+
l1 = levenshtein(first_word, second_word)
|
89
|
+
l = 1 - (l1.to_f / ([first_word.length, second_word.length].max))
|
90
|
+
l = [0, similar].max
|
91
|
+
l = [similar, 1].min
|
92
|
+
if l1 > 0.6
|
93
|
+
similar = 0.1
|
94
|
+
end
|
95
|
+
end
|
96
|
+
similar_words+= similar
|
97
|
+
end
|
98
|
+
end
|
99
|
+
count = first_words.concat(second_words).uniq.length
|
100
|
+
similarity = similar_words / count
|
101
|
+
return similarity
|
102
|
+
end
|
103
|
+
|
104
|
+
def levenshtein(first, second)
|
105
|
+
matrix = [(0..first.length).to_a]
|
106
|
+
(1..second.length).each do |j|
|
107
|
+
matrix << [j] + [0] * (first.length)
|
108
|
+
end
|
109
|
+
(1..second.length).each do |i|
|
110
|
+
(1..first.length).each do |j|
|
111
|
+
if first[j-1] == second[i-1]
|
112
|
+
matrix[i][j] = matrix[i-1][j-1]
|
113
|
+
else
|
114
|
+
matrix[i][j] = [
|
115
|
+
matrix[i-1][j],
|
116
|
+
matrix[i][j-1],
|
117
|
+
matrix[i-1][j-1],
|
118
|
+
].min + 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
return matrix.last.last
|
123
|
+
end
|
124
|
+
|
30
125
|
end
|
31
126
|
end
|
32
127
|
end
|
data/lib/forecast/version.rb
CHANGED
data/lib/forecast.rb
CHANGED
@@ -1,141 +1,73 @@
|
|
1
|
+
require 'ostruct'
|
1
2
|
require "forecast/version"
|
2
3
|
require "forecast/config"
|
3
|
-
require "forecast/
|
4
|
+
require "forecast/utils"
|
4
5
|
require "forecast/collection"
|
5
6
|
require "forecast/adapter"
|
6
7
|
require "forecast/adapters/yahoo_adapter"
|
7
8
|
require "forecast/adapters/open_weather_map_adapter"
|
8
9
|
require "forecast/adapters/wunderground_adapter"
|
9
|
-
require "
|
10
|
-
require "
|
10
|
+
require "forecast/adapters/forecast_io_adapter"
|
11
|
+
require "forecast/http"
|
11
12
|
|
12
13
|
class Forecast
|
13
14
|
|
14
|
-
|
15
|
+
PROVIDERS = Dir.glob(File.expand_path(File.dirname(__FILE__) + '/forecast/adapters/*.*')).map{ |f| File.basename(f, '_adapter.rb') };
|
15
16
|
|
16
|
-
|
17
|
+
def method_missing(method, *args, &block)
|
18
|
+
@source.send(method, *args, &block)
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(attrs = {})
|
22
|
+
@source = OpenStruct.new(attrs)
|
23
|
+
end
|
17
24
|
|
18
|
-
|
25
|
+
def as_json(options = nil)
|
26
|
+
@source.table.as_json(options)
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_json *a
|
30
|
+
self.marshal_dump.to_json a
|
31
|
+
end
|
32
|
+
|
33
|
+
def icon
|
34
|
+
# Pick icon from theme
|
35
|
+
if self.condition != nil && Forecast.config.theme.is_a?(Hash)
|
36
|
+
icon_prefix = Forecast.config.theme.has_key?('prefix') ? Forecast.config.theme['prefix'] : ''
|
37
|
+
icon_suffix = Forecast.config.theme.has_key?('suffix') ? Forecast.config.theme['suffix'] : ''
|
38
|
+
icon_name = Forecast.config.theme['conditions'].has_key?(self.condition) ? Forecast.config.theme['conditions'][self.condition] : self.condition
|
39
|
+
# Dasherize
|
40
|
+
icon_name = icon_name.to_s.gsub(/(.)([A-Z])/,'\1-\2').gsub(/\s*/, '').downcase
|
41
|
+
icon = icon_prefix + icon_name + icon_suffix
|
42
|
+
return icon != nil ? icon : self.icon
|
43
|
+
end
|
44
|
+
# Slugified condition as icon name
|
45
|
+
self.condition.is_a?(String) && self.condition.downcase.strip.gsub(' ', '-').gsub(/[^\w-]/, '')
|
46
|
+
end
|
19
47
|
|
20
48
|
# class
|
21
49
|
class << self
|
22
50
|
|
23
51
|
def current(latitude, longitude)
|
24
|
-
|
25
|
-
forecast = read_cache(cache_key)
|
26
|
-
if forecast == nil
|
27
|
-
forecast = adapter.current(latitude, longitude)
|
28
|
-
write_cache(cache_key, forecast)
|
29
|
-
end
|
30
|
-
return forecast
|
52
|
+
return adapter.current(latitude, longitude)
|
31
53
|
end
|
32
54
|
|
33
55
|
def hourly(latitude, longitude)
|
34
|
-
|
35
|
-
forecasts = read_cache(cache_key)
|
36
|
-
if forecasts == nil
|
37
|
-
forecasts = adapter.hourly(latitude, longitude)
|
38
|
-
write_cache(cache_key, forecasts)
|
39
|
-
end
|
40
|
-
return forecasts
|
56
|
+
return adapter.hourly(latitude, longitude)
|
41
57
|
end
|
42
58
|
|
43
59
|
def daily(latitude, longitude)
|
44
|
-
|
45
|
-
forecasts = read_cache(cache_key)
|
46
|
-
if forecasts == nil
|
47
|
-
forecasts = adapter.daily(latitude, longitude)
|
48
|
-
write_cache(cache_key, forecasts)
|
49
|
-
end
|
50
|
-
return forecasts
|
60
|
+
return adapter.daily(latitude, longitude)
|
51
61
|
end
|
52
62
|
|
53
|
-
private
|
54
|
-
|
55
|
-
@adapter = nil
|
56
|
-
|
63
|
+
private
|
64
|
+
|
57
65
|
def adapter
|
58
66
|
if @adapter == nil
|
59
67
|
@adapter = Forecast::Adapter.instance
|
60
68
|
end
|
61
69
|
return @adapter
|
62
70
|
end
|
63
|
-
|
64
|
-
|
65
|
-
@cache = nil
|
66
|
-
|
67
|
-
def cache
|
68
|
-
cache = Forecast.config.cache
|
69
|
-
if @cache == nil && ( cache != nil || (!!cache == cache) && cache == true )
|
70
|
-
if !!cache == cache
|
71
|
-
Forecast.config.cache = {
|
72
|
-
expire: 5,
|
73
|
-
prefix: :forecast,
|
74
|
-
host: "127.0.0.1",
|
75
|
-
port: "6379",
|
76
|
-
url: nil
|
77
|
-
}
|
78
|
-
end
|
79
|
-
cache_config = Forecast.config.cache
|
80
|
-
begin
|
81
|
-
if cache_config['url'] != nil
|
82
|
-
redis_url = cache_config['url']
|
83
|
-
uri = URI.parse(redis_url)
|
84
|
-
@cache = Redis.new(host: uri.host, port: uri.port, password: uri.password)
|
85
|
-
else
|
86
|
-
@cache = Redis.new(host: cache_config['host'], port: cache_config['port'])
|
87
|
-
end
|
88
|
-
@cache.ping
|
89
|
-
rescue
|
90
|
-
puts "error connecting to redis"
|
91
|
-
end
|
92
|
-
end
|
93
|
-
return @cache
|
94
|
-
end
|
95
|
-
|
96
|
-
def cache_key(key)
|
97
|
-
cache_prefix = Forecast.config.cache[:prefix]
|
98
|
-
return "#{cache_prefix.to_s}:#{key}"
|
99
|
-
end
|
100
|
-
|
101
|
-
def cache_expire
|
102
|
-
cache_expire = Forecast.config.cache[:expire]
|
103
|
-
end
|
104
|
-
|
105
|
-
def write_cache(key, data)
|
106
|
-
if cache == nil
|
107
|
-
return;
|
108
|
-
end
|
109
|
-
puts "WRITE TO CACHE... " + cache_key(key).to_s + ", cache_expire: " + cache_expire.to_s
|
110
|
-
cache.set(cache_key(key), data.to_json)
|
111
|
-
cache.expire(cache_key(key), cache_expire)
|
112
|
-
end
|
113
|
-
|
114
|
-
def read_cache(key)
|
115
|
-
if cache == nil
|
116
|
-
return nil;
|
117
|
-
end
|
118
|
-
cached_result = cache.get(cache_key(key))
|
119
|
-
result = nil
|
120
|
-
if cached_result != nil
|
121
|
-
puts "READ FROM CACHE: " + cache_key(key).to_s + ", cache_expire: " + cache_expire.to_s
|
122
|
-
json = JSON.parse(cached_result)
|
123
|
-
if json.is_a?(Array)
|
124
|
-
result = Forecast::Collection.new
|
125
|
-
json.each do |obj|
|
126
|
-
forecast = Forecast.new
|
127
|
-
forecast.from_json(obj)
|
128
|
-
result << forecast
|
129
|
-
end
|
130
|
-
elsif json.is_a?(Object)
|
131
|
-
result = Forecast.new
|
132
|
-
result.from_json(json)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
return result
|
136
|
-
end
|
137
|
-
|
138
|
-
|
139
71
|
|
140
72
|
end
|
141
73
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
New York:
|
2
|
+
latitude: 41.145495
|
3
|
+
longitude: -73.994901
|
4
|
+
Miami:
|
5
|
+
latitude: 25.775278
|
6
|
+
longitude: -80.208889
|
7
|
+
San Francisco:
|
8
|
+
latitude: 37.783333
|
9
|
+
longitude: -122.416667
|
10
|
+
London:
|
11
|
+
latitude: 51.50939
|
12
|
+
longitude: -0.11832
|
13
|
+
Johannesburg:
|
14
|
+
latitude: -26.204444
|
15
|
+
longitude: 28.045556
|
16
|
+
Sidney:
|
17
|
+
latitude: -33.865
|
18
|
+
longitude: 151.209444
|
19
|
+
Hamburg:
|
20
|
+
latitude: 53.55075
|
21
|
+
longitude: 9.93026
|