Skip to content

Commit 9090062

Browse files
author
exybore
authored
Merge pull request #2 from BecauseOfProg/develop
Releasing v0.2.3
2 parents 54aed93 + 4297ad5 commit 9090062

File tree

11 files changed

+266
-79
lines changed

11 files changed

+266
-79
lines changed

.github/.git_commit_msg.txt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# <type>: (If applied, this commit will...) <subject> (Max 50 char)
2+
# |<---- Using a Maximum Of 50 Characters ---->| Hard limit to 72 -->|
3+
4+
5+
# Explain why this change is being made
6+
# |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->|
7+
8+
# Provide links to any relevant issues, articles, commits, or other
9+
# pull requests
10+
# Example: See #23, fixes #58
11+
12+
# --- COMMIT END ---
13+
# <type> can be
14+
# feat (new feature)
15+
# fix (bug fix)
16+
# refactor (refactoring production code)
17+
# style (formatting, missing semi colons, etc; no code change)
18+
# test (adding or refactoring tests; no production code change)
19+
# chore (updating npm scripts etc; no production code change)
20+
# --------------------
21+
# Remember to
22+
# Capitalize the subject line
23+
# Use the imperative mood in the subject line
24+
# Do not end the subject line with a period
25+
# Separate subject from body with a blank line (comments don't count)
26+
# Use the body to explain what and why vs. how
27+
# Can use multiple lines with "-" for bullet points in body
28+
#
29+
# If you can't summarize your changes in a single line, they should
30+
# probably be split into multiple commits
31+
# --------------------
32+
# For more information about this template, check out
33+
# https://gist.github.com/adeekshith/cd4c95a064977cdc6c50

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
*.gem
2-
.vscode/
2+
.vscode/
3+
.idea

README.md

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,17 @@
55
<a href="LICENSE">License</a> - <a href="http://rubydoc.info/gems/openweathermap">RubyDoc</a>
66
</div>
77

8+
## Why would I use this library ?
9+
10+
Before writing this OpenWeatherMap implementation, I checked for existing ones on rubygems.org. There's only small libraries, that has at least one or two good thing but that's all. Consequently, I decided to make my own one, combining all their advantages :
11+
12+
- **Centralized :** all the options and fetch methods are stored in one class, that is initialized only once in all the program. Parameters are the same across all requests.
13+
- **Fast :** the only thing that can slow the library is your Internet connection : indeed, no heavy operations are made in the background. As soon as it receives weather conditions, the only step for it is organizing them.
14+
- **Simple :** the library only contains essential operations to keep the number of methods low. Moreover, all the information is perfectly human-readable.
15+
- **Documented :** every method and class attribute is explained and every exception thrown is explicit, therefore learning or debugging the library remains easy.
16+
17+
This work resulted in a powerful implementation that responds to primary needs while staying abordable.
18+
819
- [📌 Requirements](#-requirements)
920
- [🔧 Setup](#-setup)
1021
- [Quick installation](#quick-installation)
@@ -90,7 +101,7 @@ The constructor takes three parameters :
90101
- The first is an API key, that can be generated on the [OpenWeatherMap website](https://openweathermap.org/appid)
91102
- The second is the language of the data. It can be one of these : Arabic - ar, Bulgarian - bg, Catalan - ca, Czech - cz, German - de, Greek - el, English - en, Persian (Farsi) - fa, Finnish - fi, French - fr, Galician - gl, Croatian - hr, Hungarian - hu, Italian - it, Japanese - ja, Korean - kr, Latvian - la, Lithuanian - lt, Macedonian - mk, Dutch - nl, Polish - pl, Portuguese - pt, Romanian - ro, Russian - ru, Swedish - se, Slovak - sk, Slovenian - sl, Spanish - es, Turkish - tr, Ukrainian - ua, Vietnamese - vi, Chinese Simplified - zh_cn, Chinese Traditional - zh_tw.
92103
- The third is the unit system. It can be one of these :
93-
- none (temperatures in Kelvin)
104+
- default (temperatures in Kelvin)
94105
- metric (temperatures in Celsius)
95106
- imperial (temperatures in Fahrenheit)
96107

@@ -122,7 +133,7 @@ Its parameter is the same as the `current` method. It will return a `OpenWeather
122133

123134
### Possible exceptions
124135

125-
Your requests may return exceptions that are in the `OpenWeatherMap::Exceptions` module :
136+
Your requests may return exceptions that are in the `OpenWeatherMap::Exceptions` module. All are based on the `OpenWeatherMap::Exception` class.
126137

127138
- An `Unauthorized` exception, caused when your API key is wrong
128139
- An `UnknownLocation` exception, caused if the location you wrote is wrong

lib/openweathermap.rb

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,99 @@
1+
# frozen_string_literal: true
2+
13
require 'net/http'
24
require 'json'
35

4-
require 'openweathermap/data/constants'
5-
require 'openweathermap/data/exceptions'
66
require 'openweathermap/classes'
77
require 'openweathermap/current-weather'
88
require 'openweathermap/forecast'
99
require 'openweathermap/api'
10+
11+
module OpenWeatherMap
12+
13+
##
14+
# All the constants needed for the library
15+
16+
module Constants
17+
18+
##
19+
# URL of the OpenWeatherMap API
20+
21+
API_URL = 'https://api.openweathermap.org'
22+
23+
##
24+
# Accepted types of unit
25+
26+
UNITS = %w(default metric imperial)
27+
28+
##
29+
# Accepted locales
30+
31+
LANGS = %w(ar bg ca cz de el fa fi fr gl hr hu it ja kr la lt mk nl pl pt ro ru se sk sl es tr ua vi zh_cn zh_tw en)
32+
33+
##
34+
# The different URLs
35+
36+
URLS = {
37+
current: '/data/2.5/weather',
38+
forecast: '/data/2.5/forecast'
39+
}
40+
41+
##
42+
# All condition codes associated with emojis
43+
44+
CONDITION_CODE = {
45+
'01d' => '☀',
46+
'02d' => '⛅',
47+
'03d' => '☁',
48+
'04d' => '☁☁',
49+
'09d' => '🌧',
50+
'10d' => '🌦',
51+
'11d' => '🌩',
52+
'13d' => '🌨',
53+
'50d' => '🌫',
54+
}
55+
end
56+
57+
##
58+
# Base exception for the OpenWeatherMap library
59+
60+
class Exception < StandardError
61+
end
62+
63+
##
64+
# Exceptions that can be thrown by the library
65+
66+
module Exceptions
67+
68+
##
69+
# Exception to handle unknown lang
70+
71+
class UnknownLang < OpenWeatherMap::Exception
72+
end
73+
74+
##
75+
# Exception to handle unknown units
76+
77+
class UnknownUnits < OpenWeatherMap::Exception
78+
end
79+
80+
##
81+
# Exception to handle unknown location
82+
83+
class UnknownLocation < OpenWeatherMap::Exception
84+
end
85+
86+
##
87+
# Exception to tell that the API key isn't authorized
88+
89+
class Unauthorized < OpenWeatherMap::Exception
90+
end
91+
92+
##
93+
# Exception to handle data error
94+
95+
class DataError < OpenWeatherMap::Exception
96+
end
97+
98+
end
99+
end

lib/openweathermap/api.rb

Lines changed: 29 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,23 @@
1+
# frozen_string_literal: true
2+
13
module OpenWeatherMap
4+
##
25
# The main API class.
6+
37
class API
4-
# @return [String] Default lang to use
5-
attr_accessor :lang
6-
7-
# @return [String] Default units to use
8-
attr_accessor :units
8+
##
9+
# The default lang to use across the program
10+
# @return [String]
11+
12+
attr_reader :lang
913

14+
##
15+
# The default unit system to use across the program
16+
# @return [String]
17+
18+
attr_reader :units
19+
20+
##
1021
# Initialize the API object
1122
#
1223
# @param api_key [String] your OpenWeatherMap's API key
@@ -20,16 +31,18 @@ class API
2031
# - imperial (temperatures in Fahrenheit)
2132
# @raise [OpenWeatherMap::Exceptions::UnknownLang] if the selected lang is not unknown
2233
# @raise [OpenWeatherMap::Exceptions::UnknownUnits] if the selected units is not unknown
23-
def initialize(api_key, lang = 'en', units = nil)
34+
35+
def initialize(api_key, lang = 'en', units = 'default')
2436
@api_key = api_key
2537

26-
raise OpenWeatherMap::Exceptions::UnknownLang, "[owm-ruby] error : unknown lang #{lang}" unless OpenWeatherMap::Constants::LANGS.include? lang
38+
raise OpenWeatherMap::Exceptions::UnknownLang, "unknown lang #{lang}" unless OpenWeatherMap::Constants::LANGS.include? lang
2739
@lang = lang
2840

29-
raise OpenWeatherMap::Exceptions::UnknownUnits, "[owm-ruby] error : unknown units #{units}" unless OpenWeatherMap::Constants::UNITS.include? units
41+
raise OpenWeatherMap::Exceptions::UnknownUnits, "unknown units #{units}" unless OpenWeatherMap::Constants::UNITS.include? units
3042
@units = units
3143
end
3244

45+
##
3346
# Get current weather at a specific location.
3447
#
3548
# @param location [String, Integer, Array] the location
@@ -38,11 +51,13 @@ def initialize(api_key, lang = 'en', units = nil)
3851
# - Integer : search by city ID (refer to http://bulk.openweathermap.org/sample/city.list.json.gz)
3952
# - Array : search by coordinates (format : [lon, lat])
4053
# @return [OpenWeatherMap::CurrentWeather] requested data
54+
4155
def current(location)
4256
data = make_request(OpenWeatherMap::Constants::URLS[:current], location)
4357
OpenWeatherMap::CurrentWeather.new(data)
4458
end
4559

60+
##
4661
# Get weather forecast for a specific location.
4762
#
4863
# @param location [String, Integer, Array] the location
@@ -51,18 +66,21 @@ def current(location)
5166
# - Integer : search by city ID (refer to bulk.openweathermap.org/sample/city.list.json.gz)
5267
# - Array : search by coordinates (format : [lon, lat])
5368
# @return [OpenWeatherMap::Forecast] requested data
69+
5470
def forecast(location)
5571
data = make_request(OpenWeatherMap::Constants::URLS[:forecast], location)
5672
OpenWeatherMap::Forecast.new(data)
5773
end
5874

5975
private
6076

77+
##
6178
# Make a request to the OpenWeatherMap API.
6279
#
6380
# @param url [String] The endpoint to reach
6481
# @param options [Hash] mixed options
6582
# @return [String] request's body
83+
6684
def make_request(url, location)
6785
options = {}
6886
options[:q] = location if location.is_a? String
@@ -79,16 +97,12 @@ def make_request(url, location)
7997
}
8098
params.merge! options
8199

82-
url = "#{OpenWeatherMap::Constants::API_URL}/#{url}?"
83-
84-
params.each do |key, value|
85-
url += "#{key}=#{value}&"
86-
end
100+
url = "#{OpenWeatherMap::Constants::API_URL}/#{url}?#{URI.encode_www_form(params)}"
87101

88102
response = Net::HTTP.get_response(URI(url))
89103
case response.code.to_i
90-
when 401 then raise OpenWeatherMap::Exceptions::Unauthorized, "[openweathermap] error : unauthorized key. API message : #{response.message}"
91-
when 404 then raise OpenWeatherMap::Exceptions::UnknownLocation, "[openweathermap] error : unknown location. API message : #{location}"
104+
when 401 then raise OpenWeatherMap::Exceptions::Unauthorized, "unauthorized key. API message : #{response.message}"
105+
when 404 then raise OpenWeatherMap::Exceptions::UnknownLocation, "unknown location. API message : #{location}"
92106
else response.body
93107
end
94108
end

0 commit comments

Comments
 (0)