Skip to content

Commit

Permalink
Merge pull request #2 from BecauseOfProg/develop
Browse files Browse the repository at this point in the history
Releasing v0.2.3
  • Loading branch information
exybore authored Aug 12, 2019
2 parents 54aed93 + 4297ad5 commit 9090062
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 79 deletions.
33 changes: 33 additions & 0 deletions .github/.git_commit_msg.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# <type>: (If applied, this commit will...) <subject> (Max 50 char)
# |<---- Using a Maximum Of 50 Characters ---->| Hard limit to 72 -->|


# Explain why this change is being made
# |<---- Try To Limit Each Line to a Maximum Of 72 Characters ---->|

# Provide links to any relevant issues, articles, commits, or other
# pull requests
# Example: See #23, fixes #58

# --- COMMIT END ---
# <type> can be
# feat (new feature)
# fix (bug fix)
# refactor (refactoring production code)
# style (formatting, missing semi colons, etc; no code change)
# test (adding or refactoring tests; no production code change)
# chore (updating npm scripts etc; no production code change)
# --------------------
# Remember to
# Capitalize the subject line
# Use the imperative mood in the subject line
# Do not end the subject line with a period
# Separate subject from body with a blank line (comments don't count)
# Use the body to explain what and why vs. how
# Can use multiple lines with "-" for bullet points in body
#
# If you can't summarize your changes in a single line, they should
# probably be split into multiple commits
# --------------------
# For more information about this template, check out
# https://gist.github.com/adeekshith/cd4c95a064977cdc6c50
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
*.gem
.vscode/
.vscode/
.idea
15 changes: 13 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,17 @@
<a href="LICENSE">License</a> - <a href="http://rubydoc.info/gems/openweathermap">RubyDoc</a>
</div>

## Why would I use this library ?

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 :

- **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.
- **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.
- **Simple :** the library only contains essential operations to keep the number of methods low. Moreover, all the information is perfectly human-readable.
- **Documented :** every method and class attribute is explained and every exception thrown is explicit, therefore learning or debugging the library remains easy.

This work resulted in a powerful implementation that responds to primary needs while staying abordable.

- [📌 Requirements](#-requirements)
- [🔧 Setup](#-setup)
- [Quick installation](#quick-installation)
Expand Down Expand Up @@ -90,7 +101,7 @@ The constructor takes three parameters :
- The first is an API key, that can be generated on the [OpenWeatherMap website](https://openweathermap.org/appid)
- 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.
- The third is the unit system. It can be one of these :
- none (temperatures in Kelvin)
- default (temperatures in Kelvin)
- metric (temperatures in Celsius)
- imperial (temperatures in Fahrenheit)

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

### Possible exceptions

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

- An `Unauthorized` exception, caused when your API key is wrong
- An `UnknownLocation` exception, caused if the location you wrote is wrong
Expand Down
94 changes: 92 additions & 2 deletions lib/openweathermap.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,99 @@
# frozen_string_literal: true

require 'net/http'
require 'json'

require 'openweathermap/data/constants'
require 'openweathermap/data/exceptions'
require 'openweathermap/classes'
require 'openweathermap/current-weather'
require 'openweathermap/forecast'
require 'openweathermap/api'

module OpenWeatherMap

##
# All the constants needed for the library

module Constants

##
# URL of the OpenWeatherMap API

API_URL = 'https://api.openweathermap.org'

##
# Accepted types of unit

UNITS = %w(default metric imperial)

##
# Accepted locales

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)

##
# The different URLs

URLS = {
current: '/data/2.5/weather',
forecast: '/data/2.5/forecast'
}

##
# All condition codes associated with emojis

CONDITION_CODE = {
'01d' => '☀',
'02d' => '⛅',
'03d' => '☁',
'04d' => '☁☁',
'09d' => '🌧',
'10d' => '🌦',
'11d' => '🌩',
'13d' => '🌨',
'50d' => '🌫',
}
end

##
# Base exception for the OpenWeatherMap library

class Exception < StandardError
end

##
# Exceptions that can be thrown by the library

module Exceptions

##
# Exception to handle unknown lang

class UnknownLang < OpenWeatherMap::Exception
end

##
# Exception to handle unknown units

class UnknownUnits < OpenWeatherMap::Exception
end

##
# Exception to handle unknown location

class UnknownLocation < OpenWeatherMap::Exception
end

##
# Exception to tell that the API key isn't authorized

class Unauthorized < OpenWeatherMap::Exception
end

##
# Exception to handle data error

class DataError < OpenWeatherMap::Exception
end

end
end
44 changes: 29 additions & 15 deletions lib/openweathermap/api.rb
Original file line number Diff line number Diff line change
@@ -1,12 +1,23 @@
# frozen_string_literal: true

module OpenWeatherMap
##
# The main API class.

class API
# @return [String] Default lang to use
attr_accessor :lang

# @return [String] Default units to use
attr_accessor :units
##
# The default lang to use across the program
# @return [String]

attr_reader :lang

##
# The default unit system to use across the program
# @return [String]

attr_reader :units

##
# Initialize the API object
#
# @param api_key [String] your OpenWeatherMap's API key
Expand All @@ -20,16 +31,18 @@ class API
# - imperial (temperatures in Fahrenheit)
# @raise [OpenWeatherMap::Exceptions::UnknownLang] if the selected lang is not unknown
# @raise [OpenWeatherMap::Exceptions::UnknownUnits] if the selected units is not unknown
def initialize(api_key, lang = 'en', units = nil)

def initialize(api_key, lang = 'en', units = 'default')
@api_key = api_key

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

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

##
# Get current weather at a specific location.
#
# @param location [String, Integer, Array] the location
Expand All @@ -38,11 +51,13 @@ def initialize(api_key, lang = 'en', units = nil)
# - Integer : search by city ID (refer to http://bulk.openweathermap.org/sample/city.list.json.gz)
# - Array : search by coordinates (format : [lon, lat])
# @return [OpenWeatherMap::CurrentWeather] requested data

def current(location)
data = make_request(OpenWeatherMap::Constants::URLS[:current], location)
OpenWeatherMap::CurrentWeather.new(data)
end

##
# Get weather forecast for a specific location.
#
# @param location [String, Integer, Array] the location
Expand All @@ -51,18 +66,21 @@ def current(location)
# - Integer : search by city ID (refer to bulk.openweathermap.org/sample/city.list.json.gz)
# - Array : search by coordinates (format : [lon, lat])
# @return [OpenWeatherMap::Forecast] requested data

def forecast(location)
data = make_request(OpenWeatherMap::Constants::URLS[:forecast], location)
OpenWeatherMap::Forecast.new(data)
end

private

##
# Make a request to the OpenWeatherMap API.
#
# @param url [String] The endpoint to reach
# @param options [Hash] mixed options
# @return [String] request's body

def make_request(url, location)
options = {}
options[:q] = location if location.is_a? String
Expand All @@ -79,16 +97,12 @@ def make_request(url, location)
}
params.merge! options

url = "#{OpenWeatherMap::Constants::API_URL}/#{url}?"

params.each do |key, value|
url += "#{key}=#{value}&"
end
url = "#{OpenWeatherMap::Constants::API_URL}/#{url}?#{URI.encode_www_form(params)}"

response = Net::HTTP.get_response(URI(url))
case response.code.to_i
when 401 then raise OpenWeatherMap::Exceptions::Unauthorized, "[openweathermap] error : unauthorized key. API message : #{response.message}"
when 404 then raise OpenWeatherMap::Exceptions::UnknownLocation, "[openweathermap] error : unknown location. API message : #{location}"
when 401 then raise OpenWeatherMap::Exceptions::Unauthorized, "unauthorized key. API message : #{response.message}"
when 404 then raise OpenWeatherMap::Exceptions::UnknownLocation, "unknown location. API message : #{location}"
else response.body
end
end
Expand Down
Loading

0 comments on commit 9090062

Please sign in to comment.