owmo 0.1.0 → 0.2.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6ac6a3db29e87019c86229bcfe4d0e3b7a001080
4
- data.tar.gz: 067bec01b6055748a4844d8aa380fd06b0c37324
3
+ metadata.gz: e14ca9d0e7400dc1e9acd4d318c1f223837eae89
4
+ data.tar.gz: ab5302d6ef868d2723d10a8d24d4f9a1e0b4d8be
5
5
  SHA512:
6
- metadata.gz: 4f4d0980495978f29e7b4b93ffe6ea9904c82382b6e3325a88a7c401f7f971fed8148071029e1be68479515f273a5f12b6bd6b6ce514f679749dcfa9b7a825f4
7
- data.tar.gz: db1d47014dd4d26e646826a1b7708a0c62542fd71d480377eac568cc4992b2bb0f7c3ba02bf3d2203d96bf2d56470e560f2d050a57d4fc70f41a0b623a1348fc
6
+ metadata.gz: 2f82d1d1e265163514a0b24d0f1dd5e8e318b3905375d3eef8399df26eef91c1101b72f8836065b822d05360978414586d80e886f00cb510f5e60f54baef7b5b
7
+ data.tar.gz: a798ccfdc3f3482c244c5e8a474ba26d6a653831d85580d6ef652f7476c2a30353af2a6324b4594cbd3417c789fe55a444ff1bbbc308a0202828a4fade0651c2
data/.gitignore CHANGED
@@ -14,3 +14,4 @@
14
14
 
15
15
  *.gem
16
16
  test.rb
17
+ scratch.rb
data/README.md CHANGED
@@ -1,8 +1,8 @@
1
- # Owmo
1
+ # OWMO - OpenWeatherMap.Org Client API
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/owmo`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ Ruby client for openweathermap.org client API. Currently only for current and forecast information.
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ [![Gem Version](https://badge.fury.io/rb/owmo.svg)](https://badge.fury.io/rb/owmo)
6
6
 
7
7
  ## Installation
8
8
 
@@ -24,25 +24,28 @@ Or install it yourself as:
24
24
 
25
25
  You'll need and API key from OpenWeatherMap.org (http://openweathermap.org/appid).
26
26
 
27
- Either instanciate the OWMO::Weather class:
27
+ Compelete examples can be found under owmo/examples.
28
+
29
+ ----
30
+ ### Quick Start
31
+
28
32
  ```ruby
29
33
  require 'owmo'
30
- api_key = ""
31
-
34
+ api_key = "<api key here>"
32
35
  weather = OWMO::Weather.new api_key: api_key
36
+ puts weather.get :current, zip: 52402
33
37
  ```
34
38
 
35
- or through the OWMO::weather method block:
36
39
  ```ruby
37
40
  require 'owmo'
38
- api_key = ""
39
-
41
+ api_key = "<api key here>"
40
42
  OWMO::weather api_key: api_key do |weather|
41
- puts weather.get :current, city_name: "London,uk"
43
+ puts weather.get :forecast, zip: 52402
42
44
  end
43
45
  ```
46
+ ----
44
47
 
45
- **Current weather data** (http://openweathermap.org/current)
48
+ ### Current weather data (http://openweathermap.org/current)
46
49
  ```ruby
47
50
  params = {
48
51
  city_name: "London,uk", # [city_name, city_id, zip, lat/lon]
@@ -54,7 +57,7 @@ end
54
57
  puts weather.get :current, params
55
58
 
56
59
  ```
57
- **5 day weather forecast** (http://openweathermap.org/forecast5)
60
+ ### 5 day weather forecast (http://openweathermap.org/forecast5)
58
61
  ```ruby
59
62
  params = {
60
63
  zip: "90210", # [city_name, city_id, zip, lat/lon]
@@ -66,7 +69,7 @@ end
66
69
  puts weather.get :forecast, params
67
70
  ```
68
71
 
69
- **16 day weather forecast** (http://openweathermap.org/forecast16)
72
+ ### 16 day weather forecast (http://openweathermap.org/forecast16)
70
73
  ```ruby
71
74
  params = {
72
75
  lat: "40.7128", lon: "74.0059", # [city_name, city_id, zip, lat/lon]
data/_config.yml ADDED
@@ -0,0 +1 @@
1
+ theme: jekyll-theme-hacker
@@ -1,18 +1,21 @@
1
1
  require 'owmo'
2
2
 
3
+ =begin rdoc
4
+ An example on how to get current conditions and use the different parameters.
5
+ =end
3
6
  api_key = ""
4
7
 
5
8
  OWMO::weather api_key: api_key do |weather|
6
9
 
7
10
  # http://openweathermap.org/current#data
8
- params = {
11
+ query = {
9
12
  city_name: "London,uk", # [city_name, city_id, zip, lat/lon]
10
13
  mode: 'json', # [json, xml, html] Not required, but an option
11
14
  units: 'imperial', # [imperial, metric] Not required, but an option
12
15
  lang: 'en_US' # Not required, but an option
13
16
  }
14
17
 
15
- current_condition = weather.get :current, params
18
+ current_condition = weather.get :current, query
16
19
 
17
20
  puts current_condition
18
21
  end
data/examples/extended.rb CHANGED
@@ -1,18 +1,22 @@
1
1
  require 'owmo'
2
2
 
3
+
4
+ =begin rdoc
5
+ An example on how to get the weather forcast and use the different parameters.
6
+ =end
3
7
  api_key = ""
4
8
 
5
9
  OWMO::weather api_key: api_key do |weather|
6
10
 
7
11
  # http://openweathermap.org/forecast16
8
- params = {
12
+ query = {
9
13
  lat: "40.7128", lon: "74.0059", # [city_name, city_id, zip, lat/lon]
10
14
  mode: 'json', # [json, xml, html] Not required, but an option
11
15
  units: 'imperial', # [imperial, metric] Not required, but an option
12
16
  lang: 'en_US' # Not required, but an option
13
17
  }
14
18
 
15
- extended = weather.get :extended, params
19
+ extended = weather.get :extended, query
16
20
 
17
21
  puts extended
18
22
  end
data/examples/forecast.rb CHANGED
@@ -1,18 +1,22 @@
1
1
  require 'owmo'
2
2
 
3
+
4
+ =begin rdoc
5
+ An example on how to get the extended forcast and use the different parameters.
6
+ =end
3
7
  api_key = ""
4
8
 
5
9
  OWMO::weather api_key: api_key do |weather|
6
10
 
7
11
  # http://openweathermap.org/forecast5
8
- params = {
12
+ query = {
9
13
  zip: "90210", # [city_name, city_id, zip, lat/lon]
10
14
  mode: 'json', # [json, xml, html] Not required, but an option
11
15
  units: 'imperial', # [imperial, metric] Not required, but an option
12
16
  lang: 'en_US' # Not required, but an option
13
17
  }
14
18
 
15
- forecast = weather.get :forecast, params
19
+ forecast = weather.get :forecast, query
16
20
 
17
21
  puts forecast
18
22
  end
@@ -0,0 +1,4 @@
1
+ require 'core_extensions/string/uri'
2
+
3
+ module CoreExtensions
4
+ end # CoreExtensions
@@ -0,0 +1,58 @@
1
+ require 'json'
2
+
3
+
4
+ module CoreExtensions
5
+ module Net
6
+ module HTTPResponse
7
+ module WeatherResponse
8
+ =begin rdoc
9
+ Contains the weather data. If it's JSON, then it'll be a hash, other forms (XML, HTML)
10
+ will be raw format. The raw JSON is also available using the self.body.
11
+ =end
12
+ attr_reader :weather
13
+
14
+ =begin rdoc
15
+ Returns the weather
16
+ =end
17
+ def weather
18
+ parse_weather
19
+ @weather
20
+ end # weather
21
+
22
+ =begin rdoc
23
+ Returns the response code
24
+ =end
25
+ public
26
+ def weather_code
27
+ parse_weather
28
+ return @weather['cod'].to_i if @weather.is_a? Hash
29
+ 200
30
+ end # weather_error
31
+
32
+ =begin rdoc
33
+ Returns the response message
34
+ =end
35
+ public
36
+ def weather_message
37
+ parse_weather
38
+ return @weather['message'] if @weather.is_a? Hash
39
+ ""
40
+ end # weather_message
41
+
42
+ =begin rdoc
43
+ Attempts to parse the body to JSON. This is so we don't have to continually
44
+ parse the raw JSON.
45
+ =end
46
+ private
47
+ def parse_weather
48
+ begin
49
+ @weather = JSON.parse(self.body)
50
+ rescue
51
+ @weather = self.body
52
+ end if @weather.nil?
53
+ end # parse_weather
54
+
55
+ end # WeatherResponse
56
+ end # HTTPResponse
57
+ end # Net
58
+ end # CoreExtensions
data/lib/owmo/api.rb ADDED
@@ -0,0 +1,49 @@
1
+ require 'core_extensions/net/http_response/weather_response'
2
+ require 'net/http'
3
+ require 'uri'
4
+
5
+
6
+ =begin rdoc
7
+ Include some weather response info into Net::HTTPResponse
8
+ =end
9
+ Net::HTTPResponse.include CoreExtensions::Net::HTTPResponse::WeatherResponse
10
+
11
+ module OWMO
12
+ =begin rdoc
13
+ Net module Mixins
14
+ =end
15
+ module API
16
+
17
+ =begin rdoc
18
+ Weather response error to handle errors received from OpenWeatherMap.orgs API
19
+ =end
20
+ class WeatherResponseError < StandardError
21
+ def initialize(response)
22
+ @response = response
23
+ super("ERROR #{@response.weather_code}: #{@response.weather_message}")
24
+ end # initialize
25
+ end # WeatherResponseError
26
+
27
+ =begin rdoc
28
+ Sends the GET request to OpenWeatherMap.org, and returns the response
29
+ =end
30
+ def self.get(uri)
31
+
32
+ raise "Invalid URI: Expected URI, got #{uri.class}" unless uri.is_a? URI
33
+
34
+ # Send the request
35
+ request = Net::HTTP::Get.new(uri)
36
+
37
+ response = Net::HTTP.start(uri.hostname, uri.port) do |http|
38
+ http.request(request)
39
+ end # response
40
+
41
+ # Check the response
42
+ raise OWMO::API::WeatherResponseError.new(response) unless response.weather_code == 200
43
+
44
+ return response.weather
45
+
46
+ end # get
47
+ end # Net
48
+
49
+ end # OWMO
data/lib/owmo/version.rb CHANGED
@@ -1,3 +1,8 @@
1
- module Owmo
2
- VERSION = "0.1.0"
3
- end
1
+ module OWMO
2
+
3
+ =begin rdoc
4
+ Gem Version
5
+ =end
6
+ VERSION = "0.2.0"
7
+
8
+ end # OWMO
@@ -0,0 +1,116 @@
1
+ require 'set'
2
+ require 'uri'
3
+
4
+
5
+ module OWMO
6
+
7
+ =begin rdoc
8
+ A weather class for retrieving current and forecasted weather conditions.
9
+ ==== Attributes
10
+ * +api_key+ - {OpenWeatherMap.org API key}[http://openweathermap.org/appid]
11
+ ==== Examples
12
+ api_key = "<My API Key>"
13
+ weather = OWMO::Weather.new api_key: api_key
14
+ puts weather.get :current, city_name: "London,uk"
15
+
16
+ =end
17
+ class Weather
18
+
19
+ =begin rdoc
20
+ Raised when missing OpenWeatherMap.org API key
21
+ =end
22
+ class MissingApiKey < StandardError
23
+ def initialize()
24
+ super("Missing OpenWeatherMap.org API key, please register for one here -> http://openweathermap.org/appid")
25
+ end # initialize
26
+ end # MissingApiKey
27
+
28
+ =begin rdoc
29
+ Invalid path specified
30
+ =end
31
+ class InvalidPathSpecified < StandardError
32
+ def initialize(path=nil)
33
+ @path = path
34
+ super("Invalid path specified: Got: '#{@path}', expected one of: #{OWMO::PATHS.keys}")
35
+ end # initialize
36
+ end # NoGeocodeSpecified
37
+
38
+ =begin rdoc
39
+ Missing Geocode from query
40
+ =end
41
+ class MissingGeocodes < StandardError
42
+ end # MissingGeocodes
43
+
44
+ =begin rdoc
45
+ {OpenWeatherMap.org API key}[http://openweathermap.org/appid]
46
+ =end
47
+ attr_reader :api_key
48
+
49
+ def initialize(**kwargs) #:notnew:
50
+ raise MissingApiKey if kwargs[:api_key].nil?
51
+ @api_key = kwargs[:api_key]
52
+ end # initialize
53
+
54
+ =begin rdoc
55
+ A weather class for retrieving current and forecasted weather conditions.
56
+ ==== Attributes
57
+ * +path+ - OWMO::PATH parameter
58
+ * +query+ - Hash of query options (Geocode, response format, units, etc.)
59
+ ==== Examples
60
+ api_key = "<My API Key>"
61
+ weather = OWMO::Weather.new api_key: api_key
62
+ puts weather.get :current, city_name: "London,uk"
63
+ =end
64
+ public
65
+ def get(path, **query)
66
+ # Format Geocode info
67
+ query = check_geocodes query
68
+
69
+ # Add the api key
70
+ query[:APPID] = @api_key if query[:APPID].nil?
71
+
72
+ # Create the uri
73
+ raise InvalidPathSpecified.new(path) if OWMO::PATHS[path].nil?
74
+ uri = URI "#{OWMO::URL}/#{OWMO::PATHS[path]}?#{URI.encode_www_form(query)}"
75
+
76
+ # Get the weather data
77
+ OWMO::API.get(uri)
78
+
79
+ end # get
80
+
81
+ =begin rdoc
82
+ Ensure appropriate query options are applied to the final URI
83
+ =end
84
+ def check_geocodes(**query)
85
+
86
+ # May never be called since query is required
87
+ raise MissingGeocodes if query.size == 0
88
+
89
+ GEOCODES.each do |name, geocodes|
90
+
91
+ # Get the common keys
92
+ intersect = geocodes[:options].flatten & query.keys
93
+
94
+ # If there are common keys
95
+ if intersect.size > 0 then
96
+
97
+ # Remap any keys if they are not the same as the query
98
+ case geocodes[:query]
99
+ when Array then
100
+ intersect.zip(geocodes[:query]).each do |old_key, new_key|
101
+ query[new_key] = query.delete(old_key) unless new_key == old_key
102
+ end # intersect
103
+ else
104
+ query[geocodes[:query]] = query.delete(intersect[0]) unless geocodes[:query] == intersect[0]
105
+ end # case
106
+
107
+ return query
108
+ end # if
109
+
110
+ end # GEOCODES
111
+
112
+ raise MissingGeocodes
113
+ end # check_geocodes
114
+
115
+ end # Weather
116
+ end # OWMO
data/lib/owmo.rb CHANGED
@@ -1,14 +1,78 @@
1
+ require "owmo/api"
1
2
  require "owmo/version"
2
- require "owmo/Weather"
3
+ require "owmo/weather"
3
4
 
4
5
 
6
+ =begin rdoc
7
+ OMWO = OpenWeatherMap.org client for current and forecasted weather conditions.
8
+ =end
5
9
  module OWMO
10
+
11
+ =begin rdoc
12
+ Openweathermap.org URL
13
+ =end
6
14
  URL = 'http://api.openweathermap.org/data/2.5'
7
15
 
16
+ =begin rdoc
17
+ Access current or forecasted conditions by (required):
18
+ * +:current+ - {Current weather data}[http://openweathermap.org/current]
19
+ * +:forecast+ - {5 day / 3 hour forecast}[http://openweathermap.org/forecast5]
20
+ * +:extended+ - {16 day / daily forecast}[http://openweathermap.org/forecast16]
21
+ =end
22
+ PATHS = {
23
+ current: 'weather', # Current weather data
24
+ forecast: 'forecast', # 5 day / 3 hour forecast
25
+ extended: 'forecast/daily' # 16 day / daily forecast
26
+ }
27
+
28
+ =begin rdoc
29
+ {Geocode options (required):}[http://openweathermap.org/current#one]
30
+ * +q:+ or +city_name:+ - By city name
31
+ * +id:+ or +city_id:+ - By city ID
32
+ * +zip:+ or +zip_code:+ - By zip code
33
+ * +lat:+, +lon:+ or +latitude:+, +longitude:+ - By geographic coordinates
34
+ =end
35
+ GEOCODES = {
36
+ "City Name" => {
37
+ query: :q,
38
+ options: [:q, :city_name]
39
+ },
40
+ "City ID" => {
41
+ query: :id,
42
+ options: [:id, :city_id]
43
+ },
44
+ "Zip Code" => {
45
+ query: :zip,
46
+ options: [:zip, :zip_code]
47
+ },
48
+ "Coordinance" => {
49
+ query: [:lat, :lon],
50
+ options: [[:lat, :lon], [:lattitude, :longitude]]
51
+ },
52
+ "Cities Within a Rectangle Zone" => {
53
+ query: :bbox,
54
+ options: [:bbox]
55
+ },
56
+ "Cities Within a Circle" => {
57
+ query: [:lat, :lon, :cnt],
58
+ options: [[:lat, :lon, :cnt],[:lattitude, :longitude, :cnt]]
59
+ }
60
+ }
61
+
62
+ =begin rdoc
63
+ Yield a weather object for querying weather data
64
+ ==== Attributes
65
+ * +api_key:+ - {OpenWeatherMap.org API key}[http://openweathermap.org/appid]
66
+ ==== Examples
67
+ api_key = "<My API Key>"
68
+ OWMO::weather api_key do |weather|
69
+ puts weather.get :current, city_name: "London,uk"
70
+ end
71
+ =end
8
72
  public
9
73
  def self.weather(**params)
10
74
  w = Weather.new params
11
75
  yield w
12
76
  end # weather
13
77
 
14
- end
78
+ end # OWMO
data/owmo.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'owmo/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "owmo"
8
- spec.version = Owmo::VERSION
8
+ spec.version = OWMO::VERSION
9
9
  spec.authors = ["Robb"]
10
10
  spec.email = ["robb.randall@gmail.com"]
11
11
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: owmo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Robb
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-05 00:00:00.000000000 Z
11
+ date: 2017-06-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -66,14 +66,18 @@ files:
66
66
  - LICENSE.txt
67
67
  - README.md
68
68
  - Rakefile
69
+ - _config.yml
69
70
  - bin/console
70
71
  - bin/setup
71
72
  - examples/current_conditions.rb
72
73
  - examples/extended.rb
73
74
  - examples/forecast.rb
75
+ - lib/core_extensions/core_extensions.rb
76
+ - lib/core_extensions/net/http_response/weather_response.rb
74
77
  - lib/owmo.rb
75
- - lib/owmo/Weather.rb
78
+ - lib/owmo/api.rb
76
79
  - lib/owmo/version.rb
80
+ - lib/owmo/weather.rb
77
81
  - owmo.gemspec
78
82
  homepage: https://github.com/robb-randall/owmo
79
83
  licenses:
data/lib/owmo/Weather.rb DELETED
@@ -1,96 +0,0 @@
1
- require 'net/http'
2
-
3
- module OWMO
4
- class Weather
5
-
6
- attr_reader :url, :api_key
7
-
8
- def initialize(**kwargs)
9
- raise "Missing required api_key" if kwargs[:api_key].nil?
10
- @url = kwargs[:url] || OWMO::URL
11
- @api_key = kwargs[:api_key]
12
- end # initialize
13
-
14
- public
15
- def get(path, **params)
16
- # Parse the path
17
- path = parse_path(path)
18
-
19
- # Parse the params
20
- params = parse_params(params)
21
-
22
- # Format the URI
23
- uri = build_uri(path, params)
24
-
25
- # Get the weather data
26
- get_weather(uri)
27
- end # get
28
-
29
- private
30
- def parse_path(path)
31
- case path
32
- # Current weather data
33
- when :current then 'weather'
34
-
35
- # 5 day / 3 hour forecast
36
- when :forecast then 'forecast'
37
-
38
- # 16 day / daily forecast
39
- when :extended then 'forecast/daily'
40
-
41
- # Raise an error
42
- else raise "Unknown path: '#{path}'"
43
-
44
- end # case
45
- end # path
46
-
47
- private
48
- def parse_params(**params)
49
- case
50
- # Search by city name
51
- when params.key?(:city_name) then
52
- params[:q] = params.delete :city_name
53
-
54
- # Search by city ID
55
- when params.key?(:city_id) then
56
- params[:id] = params.delete :city_id
57
-
58
- # Search by Zip
59
- when params.key?(:zip) then
60
-
61
- # Search by geo location
62
- when params.key?(:lat) && params.key?(:lon) then
63
-
64
- # Nothing is specified, raise an error
65
- else raise "Missing location parameter: #{params}"
66
- end # case
67
-
68
- params
69
- end # parse_params
70
-
71
- private
72
- def build_uri(path, **params)
73
- URI "#{@url}/#{path}?#{format_parameters(params)}"
74
- end # format_uri
75
-
76
- private
77
- def format_parameters(**params)
78
- params[:APPID] = @api_key if params[:APPID].nil?
79
- params.map {|k,v| "#{k}=#{v}"}.join('&')
80
- end # format_params
81
-
82
- private
83
- def get_weather(uri)
84
- Net::HTTP.start(uri.host, uri.port) do |http|
85
- req = Net::HTTP::Get.new uri
86
- resp = http.request req
87
-
88
- # Error if the request was unsuccessful
89
- raise "ERROR #{resp.code}: #{res.message} (#{res.class.name})" unless Net::HTTPSuccess
90
-
91
- resp.body
92
- end # http
93
- end # get_weather
94
-
95
- end # Weather
96
- end # OWMO