open-weather-ruby-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 317dd6924aee3127f7a350a47ad0d4873db645af7d307d07a2f7f5102a058c03
4
+ data.tar.gz: cd4a8bd78a0170ada43260fd0897ba388c54ddff5f9233ea79477c292affd5e4
5
+ SHA512:
6
+ metadata.gz: df44462ca143dcd462d45ba7cb2cfc38ba1c951a705709e4b4b59d80b1b1d78057fff3cfa8aedc2d9f9c26fce1cf2b9c4a5c66178ed939055c0b4afca5083c15
7
+ data.tar.gz: 256c0bac00841ba60a5ce65e10e3b66103c8756e5c619bf93479b74660d092e22973b6e8e07eaac4cdd370be243eb6382ea7f33829fd2db9d65bbe675b61d736
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ### 0.1.0 (5/1/2020)
2
+
3
+ * Initial public release - [@dblock](https://github.com/dblock).
data/LICENSE.md ADDED
@@ -0,0 +1,22 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2020 Daniel Doubrovkine
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,231 @@
1
+ OpenWeather Ruby Client
2
+ =======================
3
+
4
+ [![Gem Version](https://badge.fury.io/rb/open-weather-ruby-client.svg)](https://badge.fury.io/rb/open-weather-ruby-client)
5
+ [![Build Status](https://travis-ci.org/dblock/open-weather-ruby-client.svg?branch=master)](https://travis-ci.org/dblock/open-weather-ruby-client)
6
+
7
+ A Ruby client for the [OpenWeather API v3](https://openweathermap.org/api).
8
+
9
+ Unlike other clients, including [open-weather](https://github.com/coderhs/ruby_open_weather_map), provides a rich first class interface to OpenWeather models, implements more consistent error handling, and is built with thorough test coverage using actual OpenWeather data.
10
+
11
+ ## Table of Contents
12
+
13
+ - [Installation](#installation)
14
+ - [Usage](#usage)
15
+ - [Current Weather](#current-weather)
16
+ - [Current Weather for Several Cities](#current-weather-for-several-cities)
17
+ - [Cities Within a Rectangle Zone](#cities-within-a-rectangle-zone)
18
+ - [Cities Within a Circle](#cities-within-a-circle)
19
+ - [Multiple Cities by Id](#multiple-cities-by-id)
20
+ - [Configuration](#configuration)
21
+ - [Units](#units)
22
+ - [Language](#language)
23
+ - [Errors](#errors)
24
+ - [Resources](#resources)
25
+ - [Contributing](#contributing)
26
+ - [Copyright and License](#copyright-and-license)
27
+
28
+ ## Installation
29
+
30
+ Add to Gemfile.
31
+
32
+ ```
33
+ gem 'open-weather-ruby-client'
34
+ ```
35
+
36
+ Run `bundle install`.
37
+
38
+ ## Usage
39
+
40
+ Use an access token obtained from [API Keys](https://home.openweathermap.org/api_keys) on the OpenWeather website after registration.
41
+
42
+ ```ruby
43
+ client = OpenWeather::Client.new(
44
+ api_key: "1a2b3c4d5a6b7c8d9a8b7c6d5a4b3c2d1"
45
+ )
46
+ ```
47
+
48
+ ### Current Weather
49
+
50
+ Returns [current weather](https://openweathermap.org/current).
51
+
52
+ ```ruby
53
+ data = client.current_weather(city: 'London') # => OpenWeather::Models::CityWeather
54
+
55
+ data.name # => 'London'
56
+ data.main.feels_like # => 277.73
57
+ data.main.humidity # => 81
58
+ data.main.pressure # => 1005
59
+ data.main.temp # => 282.57
60
+ data.main.temp_max # => 283.15
61
+ data.main.temp_min # => 281.48
62
+ ```
63
+
64
+ Returns the current weather in metric units and Russian metadata.
65
+
66
+ ```ruby
67
+ data = client.current_weather(city: 'Moscow', units: 'metric', lang: 'ru') # => OpenWeather::Models::CityWeather
68
+
69
+ data.name # => 'Москва'
70
+ data.main.temp # => 12
71
+ ```
72
+
73
+ Returns weather by city, optional state (in the US) and optional ISO 3166 country code.
74
+
75
+ ```ruby
76
+ client.current_city('New York', 'NY', 'US')
77
+ client.current_weather(city: 'New York', state: 'NY', country: 'US')
78
+ ```
79
+
80
+ Returns weather by city ID.
81
+
82
+ ```ruby
83
+ client.current_city_id(2643743) # => weather in London
84
+ client.current_weather(id: 2643743) # => weather in London
85
+ ```
86
+
87
+ Returns weather by latitude and longitude.
88
+
89
+ ```ruby
90
+ client.current_geo(51.51, -0.13) # => weather in London
91
+ client.current_weather(lat: 51.51, lon: -0.13) # => weather in London
92
+ ```
93
+
94
+ Returns weather by zip code with an optional country code (defaults to US).
95
+
96
+ ```ruby
97
+ client.current_zip(10018, 'US') # => weather in New York, 10018
98
+ client.current_weather(zip: 10018, country: 'US') # => weather in New York, 10018
99
+ ```
100
+
101
+ See [OpenWeather::Models::CityWeather](lib/open_weather/models/data.rb) for all available properties.
102
+
103
+ ### Current Weather for Several Cities
104
+
105
+ #### Cities Within a Rectangle Zone
106
+
107
+ ```ruby
108
+ data = client.current_cities_geo_box(12, 32, 15, 37, 10) # => OpenWeather::Models::List
109
+
110
+ data.first.name # 'Birkirkara'
111
+ data.main.temp # => 16.23
112
+ ```
113
+
114
+ You can optionally name parameters.
115
+
116
+ ```ruby
117
+ client.current_cities_geo_box(lon_left: 12, lat_bottom: 32, lon_right: 15, lat_top: 37, zoom: 10) # => OpenWeather::Models::List
118
+ ```
119
+
120
+ You can use server clustering of points with `cluster: true`.
121
+
122
+ ```ruby
123
+ client.current_cities_geo_box(12, 32, 15, 37, 10, cluster: true) # => OpenWeather::Models::List
124
+ ```
125
+
126
+ #### Cities Within a Circle
127
+
128
+ ```ruby
129
+ data = client.current_cities_geo_circle(55.5, 37.5, 10) # => OpenWeather::Models::List
130
+
131
+ data.first.name # 'Shcherbinka'
132
+ data.main.temp # => 276.86
133
+ ```
134
+
135
+ You can optionally name parameters.
136
+
137
+ ```ruby
138
+ client.current_cities_geo_circle(lat: 55.5, lon: 37.5, cnt: 7) # => OpenWeather::Models::List
139
+ ```
140
+
141
+ #### Multiple Cities by Id
142
+
143
+ ```ruby
144
+ data = client.current_cities_id(524901, 703448, 2643743) # => OpenWeather::Models::List
145
+
146
+ data.first.name # 'Moscow'
147
+ data.main.temp # => 285.15
148
+ ```
149
+
150
+ ## Configuration
151
+
152
+ You can configure client options, globally.
153
+
154
+ ```ruby
155
+ OpenWeather::Client.configure do |config|
156
+ config.api_key = '1a2b3c4d5a6b7c8d9a8b7c6d5a4b3c2d1'
157
+ config.user_agent = 'OpenWeather Ruby Client/1.0'
158
+ end
159
+ ```
160
+
161
+ The following settings are supported.
162
+
163
+ setting | description
164
+ --------------------|------------
165
+ api_key | Required API key.
166
+ lang | Default language in API responses.
167
+ units | Default units in API responses.
168
+ endpoint | Defaults to `https://api.openweathermap.org/data/2.5/`.
169
+ user_agent | User-agent, defaults to _OpenWeather Ruby Client/version_.
170
+ proxy | Optional HTTP proxy.
171
+ ca_path | Optional SSL certificates path.
172
+ ca_file | Optional SSL certificates file.
173
+ logger | Optional `Logger` instance that logs HTTP requests.
174
+ timeout | Optional open/read timeout in seconds.
175
+ open_timeout | Optional connection open timeout in seconds.
176
+
177
+ ### Units
178
+
179
+ The OpenWeather API returns responses in `standard`, `metric`, and `imperial` units. You can pass `units` into API requests or configure the desired units globally.
180
+
181
+ ```ruby
182
+ data = client.weather(id: 2643743, units: 'metric')
183
+ data.name # => 'London'
184
+ data.main.temp # => 12 (degrees Celsius)
185
+ ```
186
+
187
+ ```ruby
188
+ OpenWeather.configure do |config|
189
+ config.units = 'metric'
190
+ end
191
+
192
+ data = client.weather(id: 2643743)
193
+ data.name # => 'London'
194
+ data.main.temp # => 12 (degrees Celsius)
195
+ ```
196
+
197
+ ### Language
198
+
199
+ The OpenWeather API returns responses in English and supports many other languages. You can pass `lang` into API requests or configure the desired language globally.
200
+
201
+ ```ruby
202
+ data = client.weather(id: 2643743, lang: 'ru')
203
+ data.name # => 'Лондон'
204
+ ```
205
+
206
+ ```ruby
207
+ OpenWeather.configure do |config|
208
+ config.lang = 'ru'
209
+ end
210
+
211
+ data = client.weather(id: 2643743)
212
+ data.name # => 'Лондон'
213
+ ```
214
+
215
+ ## Errors
216
+
217
+ All errors that return HTTP codes 400-600 result in either `Faraday::Error::ResourceNotFound`, `Faraday::Error::ConnectionFailed` or [OpenWeather::Errors::Fault](lib/open_weather/errors/fault.rb) exceptions.
218
+
219
+ ## Resources
220
+
221
+ * [OpenWeather API Documentation](https://openweathermap.org/api)
222
+
223
+ ## Contributing
224
+
225
+ See [CONTRIBUTING](CONTRIBUTING.md).
226
+
227
+ ## Copyright and License
228
+
229
+ Copyright (c) 2020, [Daniel Doubrovkine](https://twitter.com/dblockdotorg)
230
+
231
+ This project is licensed under the [MIT License](LICENSE.md).
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'faraday'
4
+ require 'faraday_middleware'
5
+ require 'json'
6
+ require 'logger'
7
+ require 'hashie'
8
+ require 'time'
9
+
10
+ require 'active_support/core_ext/object/to_query'
11
+ require 'active_support/core_ext/hash'
12
+ require 'active_support/concern'
13
+
14
+ require_relative 'open_weather/version'
15
+ require_relative 'open_weather/logger'
16
+
17
+ require_relative 'open_weather/errors/fault'
18
+
19
+ require_relative 'open_weather/models/model'
20
+
21
+ require_relative 'open_weather/raise_error'
22
+ require_relative 'open_weather/connection'
23
+ require_relative 'open_weather/request'
24
+ require_relative 'open_weather/config'
25
+ require_relative 'open_weather/errors'
26
+ require_relative 'open_weather/models'
27
+ require_relative 'open_weather/endpoints'
28
+ require_relative 'open_weather/client'
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ class Client
5
+ include Connection
6
+ include Request
7
+ include Endpoints::Current
8
+
9
+ attr_accessor(*Config::ATTRIBUTES)
10
+
11
+ def initialize(options = {})
12
+ OpenWeather::Config::ATTRIBUTES.each do |key|
13
+ send("#{key}=", options[key] || OpenWeather.config.send(key))
14
+ end
15
+ @logger ||= OpenWeather::Logger.logger
16
+ end
17
+
18
+ class << self
19
+ def configure
20
+ block_given? ? yield(Config) : Config
21
+ end
22
+
23
+ def config
24
+ Config
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,49 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Config
5
+ extend self
6
+
7
+ ATTRIBUTES = %i[
8
+ endpoint
9
+ api_key
10
+ proxy
11
+ user_agent
12
+ ca_path
13
+ ca_file
14
+ logger
15
+ timeout
16
+ open_timeout
17
+ lang
18
+ units
19
+ ].freeze
20
+
21
+ attr_accessor(*Config::ATTRIBUTES)
22
+
23
+ def reset
24
+ self.endpoint = 'https://api.openweathermap.org/data/2.5'
25
+ self.api_key = nil
26
+ self.user_agent = "OpenWeather Ruby Client/#{OpenWeather::VERSION}"
27
+ self.ca_path = defined?(OpenSSL) ? OpenSSL::X509::DEFAULT_CERT_DIR : nil
28
+ self.ca_file = defined?(OpenSSL) ? OpenSSL::X509::DEFAULT_CERT_FILE : nil
29
+ self.proxy = nil
30
+ self.logger = nil
31
+ self.timeout = nil
32
+ self.open_timeout = nil
33
+ self.lang = nil
34
+ self.units = nil
35
+ end
36
+ end
37
+
38
+ class << self
39
+ def configure
40
+ block_given? ? yield(Config) : Config
41
+ end
42
+
43
+ def config
44
+ Config
45
+ end
46
+ end
47
+ end
48
+
49
+ OpenWeather::Config.reset
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Connection
5
+ private
6
+
7
+ def headers
8
+ {}
9
+ end
10
+
11
+ def connection
12
+ options = {
13
+ headers: headers.merge('Accept' => 'application/json; charset=utf-8')
14
+ }
15
+
16
+ options[:headers]['User-Agent'] = user_agent if user_agent
17
+ options[:proxy] = proxy if proxy
18
+ options[:ssl] = { ca_path: ca_path, ca_file: ca_file } if ca_path || ca_file
19
+
20
+ request_options = {}
21
+ request_options[:timeout] = timeout if timeout
22
+ request_options[:open_timeout] = open_timeout if open_timeout
23
+ options[:request] = request_options if request_options.any?
24
+
25
+ ::Faraday::Connection.new(endpoint, options) do |connection|
26
+ connection.use ::Faraday::Request::Multipart
27
+ connection.use ::Faraday::Request::UrlEncoded
28
+ connection.use ::OpenWeather::Response::RaiseError
29
+ connection.use ::FaradayMiddleware::ParseJson, content_type: /\bjson$/
30
+ connection.response :logger, logger if logger
31
+ connection.adapter ::Faraday.default_adapter
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,78 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Endpoints
5
+ module Current
6
+ def current_zip(code, country = nil, options = {})
7
+ options = code.is_a?(Hash) ? options.merge(code) : options.merge(zip: code, country: country)
8
+ current_weather(options)
9
+ end
10
+
11
+ def current_geo(lat, lon = nil, options = {})
12
+ options = lat.is_a?(Hash) ? options.merge(lat) : options.merge(lat: lat, lon: lon)
13
+ current_weather(options)
14
+ end
15
+
16
+ def current_city(name, state = nil, country = nil, options = {})
17
+ options = name.is_a?(Hash) ? options.merge(name) : options.merge(city: name, state: state, country: country)
18
+ current_weather(options)
19
+ end
20
+
21
+ def current_city_id(id, options = {})
22
+ options = id.is_a?(Hash) ? options.merge(id) : options.merge(id: id)
23
+ current_weather(options)
24
+ end
25
+
26
+ def current_weather(options = {})
27
+ if options.key?(:zip) && options.key?(:country)
28
+ options = options.dup
29
+ options[:zip] = [
30
+ options.delete(:zip),
31
+ options.delete(:country)
32
+ ].compact.join(',')
33
+ elsif options.key?(:city)
34
+ options = options.dup
35
+ options[:q] = [
36
+ options.delete(:city),
37
+ options.delete(:state),
38
+ options.delete(:country)
39
+ ].compact.join(',')
40
+ end
41
+ OpenWeather::Models::CityWeather.new(get('weather', options))
42
+ end
43
+
44
+ def current_cities_geo_box(*args)
45
+ options = args[-1].is_a?(Hash) ? args.pop.dup : {}
46
+ options[:bbox] = args.join(',') if args.any?
47
+ options[:bbox] ||= [
48
+ options.delete(:lon_left),
49
+ options.delete(:lat_bottom),
50
+ options.delete(:lon_right),
51
+ options.delete(:lat_top),
52
+ options.delete(:zoom)
53
+ ].join(',')
54
+ OpenWeather::Models::List.new(get('box/city', options))
55
+ end
56
+
57
+ def current_cities_geo_circle(*args)
58
+ options = args[-1].is_a?(Hash) ? args.pop.dup : {}
59
+
60
+ if args.any?
61
+ options[:lat] = args.shift
62
+ options[:lon] = args.shift
63
+ options[:cnt] = args.shift || 1
64
+ end
65
+
66
+ OpenWeather::Models::List.new(get('find', options))
67
+ end
68
+
69
+ def current_cities_id(*args)
70
+ options = args[-1].is_a?(Hash) ? args.pop.dup : {}
71
+ options[:id] = args.join(',') if args.any?
72
+ options[:id] = options.delete(:ids) if options.key?(:ids)
73
+ options[:id] = options[:id].join(',') if options[:id].is_a?(Array)
74
+ OpenWeather::Models::List.new(get('group', options))
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'endpoints/current'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Errors
5
+ class Fault < ::Faraday::ClientError
6
+ def message
7
+ response[:body]['message'] || super
8
+ end
9
+
10
+ def headers
11
+ response[:headers]
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors/fault'
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ module OpenWeather
6
+ class Logger < ::Logger
7
+ def self.logger
8
+ @logger ||= begin
9
+ logger = new STDOUT
10
+ logger.level = Logger::WARN
11
+ logger
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class CityWeather < Model
6
+ property 'coord', transform_with: ->(v) { OpenWeather::Models::Coord.new(v) }
7
+ property 'weather', transform_with: ->(v) { v.map { |i| OpenWeather::Models::Weather.new(i) } }
8
+ property 'base' # internal parameter
9
+ property 'main', transform_with: ->(v) { OpenWeather::Models::Main.new(v) }
10
+ property 'visibility'
11
+ property 'wind', transform_with: ->(v) { OpenWeather::Models::Wind.new(v) }
12
+ property 'clouds', transform_with: ->(v) { OpenWeather::Models::Clouds.new(v) }
13
+ property 'rain', transform_with: ->(v) { OpenWeather::Models::Rain.new(v) }
14
+ property 'snow', transform_with: ->(v) { OpenWeather::Models::Snow.new(v) }
15
+ property 'dt', transform_with: ->(v) { Time.at(v).utc } # time of data calculation, UTC
16
+ property 'sys', transform_with: ->(v) { OpenWeather::Models::Sys.new(v) }
17
+ property 'id' # city id
18
+ property 'timezone' # shift in seconds from UTC
19
+ property 'name' # city name
20
+ property 'cod' # internal parameter
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Clouds < Model
6
+ property 'all' # cloudiness, %
7
+ property 'today' # cloudiness today, %
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Coord < Model
6
+ property 'lon', from: 'Lon' # City geo location, longitude
7
+ property 'lat', from: 'Lat' # City geo location, latitude
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class List < Model
6
+ include Enumerable
7
+
8
+ property 'cod'
9
+ property 'calctime'
10
+ property 'cnt', from: 'count'
11
+ property 'list', transform_with: ->(v) { v.map { |i| OpenWeather::Models::CityWeather.new(i) } }
12
+ property 'message'
13
+
14
+ def each(&block)
15
+ list.each(&block)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Main < Model
6
+ property 'temp' # temperature in requested unit
7
+ property 'pressure' # atmospheric pressure on the sea_level or grnd_level when unavailable, hPa
8
+ property 'humidity' # humidity in %
9
+ property 'feels_like' # temperature, accounting for the human perception of weather, in requested unit
10
+ property 'temp_min' # minimal currently observed temperature
11
+ property 'temp_max' # maximal currently observed temperature
12
+ property 'sea_level' # atmospheric pressure on the sea level, hPa
13
+ property 'grnd_level' # atmospheric pressure on the ground level, hPa
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Model < Hashie::Trash
6
+ include Hashie::Extensions::IgnoreUndeclared
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Rain < Model
6
+ property '1h' # rain volume for the last 1 hour, mm
7
+ property '3h' # rain volume for the last 3 hours, mm
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Snow < Model
6
+ property '1h' # snow volume for the last 1 hour, mm
7
+ property '3h' # snow volume for the last 3 hours, mm
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Sys < Model
6
+ property 'type' # internal parameter
7
+ property 'id' # internal parameter
8
+ property 'message' # internal parameter
9
+ property 'country' # country code
10
+ property 'sunrise', transform_with: ->(v) { Time.at(v).utc } # sunrise time, UTC
11
+ property 'sunset', transform_with: ->(v) { Time.at(v).utc } # sunset time, UTC
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Weather < Model
6
+ property 'id' # weather condition id
7
+ property 'main' # group of weather parameters (Rain, Snow, Extreme, etc.)
8
+ property 'description' # weather condition within the group, in your language
9
+ property 'icon' # weather icon id
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Models
5
+ class Wind < Model
6
+ property 'speed' # wind speed in meter/sec or miles/hour
7
+ property 'deg' # wind direction in degrees (meteorological)
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'models/model'
4
+ require_relative 'models/clouds'
5
+ require_relative 'models/coord'
6
+ require_relative 'models/city_weather'
7
+ require_relative 'models/main'
8
+ require_relative 'models/sys'
9
+ require_relative 'models/weather'
10
+ require_relative 'models/wind'
11
+ require_relative 'models/rain'
12
+ require_relative 'models/snow'
13
+ require_relative 'models/list'
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Response
5
+ class RaiseError < ::Faraday::Response::Middleware
6
+ def on_complete(env)
7
+ case env[:status]
8
+ when 404
9
+ raise Faraday::Error::ResourceNotFound, response_values(env)
10
+ when 407
11
+ # mimic the behavior that we get with proxy requests with HTTPS
12
+ raise Faraday::Error::ConnectionFailed, %(407 "Proxy Authentication Required ")
13
+ when (400...600).freeze
14
+ raise OpenWeather::Errors::Fault, response_values(env)
15
+ end
16
+ end
17
+
18
+ def response_values(env)
19
+ {
20
+ status: env.status,
21
+ headers: env.response_headers,
22
+ body: env.body
23
+ }
24
+ end
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,43 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ module Request
5
+ def get(path, options = {})
6
+ request(:get, path, options)
7
+ end
8
+
9
+ def post(path, options = {})
10
+ request(:post, path, options)
11
+ end
12
+
13
+ def put(path, options = {})
14
+ request(:put, path, options)
15
+ end
16
+
17
+ def delete(path, options = {})
18
+ request(:delete, path, options)
19
+ end
20
+
21
+ private
22
+
23
+ def request(method, path, options)
24
+ options = options.dup
25
+ options[:appid] ||= api_key if api_key.present?
26
+ options[:lang] ||= lang if lang.present?
27
+ options[:units] ||= units if units.present?
28
+ root = options.delete(:endpoint) || endpoint
29
+ path = [root, path].join('/')
30
+ response = connection.send(method) do |request|
31
+ case method
32
+ when :get, :delete
33
+ request.url(path, options)
34
+ when :post, :put
35
+ request.path = path
36
+ request.body = options unless options.empty?
37
+ end
38
+ request.options.merge!(options.delete(:request)) if options.key?(:request)
39
+ end
40
+ response.body
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module OpenWeather
4
+ VERSION = '0.1.0'
5
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: open-weather-ruby-client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Daniel Doubrovkine
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-05-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: faraday
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0.9'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0.9'
41
+ - !ruby/object:Gem::Dependency
42
+ name: faraday_middleware
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: hashie
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description:
70
+ email: dblock@dblock.org
71
+ executables: []
72
+ extensions: []
73
+ extra_rdoc_files: []
74
+ files:
75
+ - CHANGELOG.md
76
+ - LICENSE.md
77
+ - README.md
78
+ - lib/open-weather-ruby-client.rb
79
+ - lib/open_weather/client.rb
80
+ - lib/open_weather/config.rb
81
+ - lib/open_weather/connection.rb
82
+ - lib/open_weather/endpoints.rb
83
+ - lib/open_weather/endpoints/current.rb
84
+ - lib/open_weather/errors.rb
85
+ - lib/open_weather/errors/fault.rb
86
+ - lib/open_weather/logger.rb
87
+ - lib/open_weather/models.rb
88
+ - lib/open_weather/models/city_weather.rb
89
+ - lib/open_weather/models/clouds.rb
90
+ - lib/open_weather/models/coord.rb
91
+ - lib/open_weather/models/list.rb
92
+ - lib/open_weather/models/main.rb
93
+ - lib/open_weather/models/model.rb
94
+ - lib/open_weather/models/rain.rb
95
+ - lib/open_weather/models/snow.rb
96
+ - lib/open_weather/models/sys.rb
97
+ - lib/open_weather/models/weather.rb
98
+ - lib/open_weather/models/wind.rb
99
+ - lib/open_weather/raise_error.rb
100
+ - lib/open_weather/request.rb
101
+ - lib/open_weather/version.rb
102
+ homepage: http://github.com/dblock/open-weather-ruby-client
103
+ licenses:
104
+ - MIT
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: 1.3.6
120
+ requirements: []
121
+ rubygems_version: 3.0.3
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: OpenWeather API Ruby client.
125
+ test_files: []