weatherxu 1.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 85e16dc76187027dc9e39d22a18519601e33ffb95257731b2ed04dec28152e69
4
+ data.tar.gz: 7642f4a499ec155a472a4e5f0c42e647df90d865fbcec8105210651a1a9770e2
5
+ SHA512:
6
+ metadata.gz: c56f7ea3667523047b913444750d319b5af09fd5154755114f8d9da0cca59df286015c595de6a26dbfb069cf0092e9fd7e154a19fd0367f799e7087844e1a717
7
+ data.tar.gz: 778187ae76c3ffffb49f0e53af43ee1d86468a87a14037c041944205862e14f9cd44f49534e58c5224445ed2240fae3db43d43c33a82e472e97cbe36f43136c8
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 WeatherXu
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,152 @@
1
+ # WeatherXu Ruby SDK
2
+
3
+ Official Ruby SDK for accessing WeatherXu's weather data API.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'weatherxu'
11
+ ```
12
+
13
+ And then execute:
14
+ ```bash
15
+ $ bundle install
16
+ ```
17
+
18
+ Or install it yourself as:
19
+ ```bash
20
+ $ gem install weatherxu
21
+ ```
22
+
23
+ ## Quick Start
24
+
25
+ ```ruby
26
+ require 'weatherxu'
27
+
28
+ # Initialize the client
29
+ client = WeatherXu.new(
30
+ api_key: 'YOUR_API_KEY',
31
+ units: 'metric'
32
+ )
33
+
34
+ begin
35
+ # Get current weather and forecast for New York City
36
+ weather = client.get_weather(
37
+ lat: 40.7128,
38
+ lon: -74.0060,
39
+ parts: ['currently', 'hourly', 'daily']
40
+ )
41
+
42
+ # Access current conditions
43
+ puts "Current temperature: #{weather.currently.temperature}°C"
44
+
45
+ # Access hourly forecast
46
+ weather.hourly&.each do |hour|
47
+ puts "Time: #{hour.forecast_start.strftime('%Y-%m-%d %H:%M')}, " \
48
+ "Temperature: #{hour.temperature}°C"
49
+ end
50
+
51
+ # Get historical weather data
52
+ end_time = Time.now.to_i
53
+ start_time = end_time - (24 * 60 * 60) # 24 hours ago
54
+
55
+ historical = client.get_historical(
56
+ lat: 40.7128,
57
+ lon: -74.0060,
58
+ start: start_time,
59
+ end_time: end_time
60
+ )
61
+
62
+ # Access historical data
63
+ historical.hourly.each do |record|
64
+ puts "Time: #{record.forecast_start.strftime('%Y-%m-%d %H:%M')}, " \
65
+ "Temperature: #{record.temperature}°C"
66
+ end
67
+ rescue WeatherXu::Error => e
68
+ puts "Error: #{e.message}"
69
+ puts "Status code: #{e.status_code}" if e.status_code
70
+ puts "Error code: #{e.error_code}" if e.error_code
71
+ end
72
+ ```
73
+
74
+ ## Features
75
+
76
+ - Modern Ruby features and best practices
77
+ - Automatic parsing of timestamps to Time objects
78
+ - Comprehensive error handling
79
+ - Support for both metric and imperial units
80
+ - Configurable request timeout
81
+ - Automatic retries with exponential backoff
82
+
83
+ ## API Reference
84
+
85
+ ### Initialization
86
+
87
+ ```ruby
88
+ WeatherXu.new(
89
+ api_key: String,
90
+ units: String = "metric",
91
+ timeout: Integer = 10
92
+ )
93
+ ```
94
+
95
+ ### Methods
96
+
97
+ #### get_weather
98
+
99
+ Get current weather and forecast data for a location.
100
+
101
+ ```ruby
102
+ get_weather(
103
+ lat: Float,
104
+ lon: Float,
105
+ parts: Array<String> = nil,
106
+ units: String = nil
107
+ ) -> WeatherData
108
+ ```
109
+
110
+ Parameters:
111
+ - `lat`: Latitude (-90 to 90)
112
+ - `lon`: Longitude (-180 to 180)
113
+ - `parts`: Optional array of data blocks to include ('alerts', 'currently', 'hourly', 'daily')
114
+ - `units`: Optional unit system ('metric' or 'imperial')
115
+
116
+ #### get_historical
117
+
118
+ Get historical weather data for a location.
119
+
120
+ ```ruby
121
+ get_historical(
122
+ lat: Float,
123
+ lon: Float,
124
+ start: Integer,
125
+ end_time: Integer,
126
+ units: String = nil
127
+ ) -> HistoricalData
128
+ ```
129
+
130
+ Parameters:
131
+ - `lat`: Latitude (-90 to 90)
132
+ - `lon`: Longitude (-180 to 180)
133
+ - `start`: Start time (Unix timestamp)
134
+ - `end_time`: End time (Unix timestamp)
135
+ - `units`: Optional unit system ('metric' or 'imperial')
136
+
137
+ ## Error Handling
138
+
139
+ The SDK raises `WeatherXu::Error` for any API or network-related errors. Each error includes:
140
+ - Error message
141
+ - HTTP status code (when available)
142
+ - API error code (when provided by the API)
143
+
144
+ ## Development
145
+
146
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
147
+
148
+ To install this gem onto your local machine, run `bundle exec rake install`.
149
+
150
+ ## Requirements
151
+
152
+ - Ruby 2.7 or higher
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "net/http"
4
+ require "json"
5
+ require "uri"
6
+
7
+ module WeatherXu
8
+ # Main client for interacting with the WeatherXu API
9
+ class Client
10
+ WEATHER_BASE_URL = "https://api.weatherxu.com/v1"
11
+ HISTORICAL_BASE_URL = "https://historical.weatherxu.com/v1"
12
+
13
+ # @return [String] API key for authentication
14
+ attr_reader :api_key
15
+
16
+ # @return [String] Unit system ('metric' or 'imperial')
17
+ attr_reader :units
18
+
19
+ # @return [Integer] Request timeout in seconds
20
+ attr_reader :timeout
21
+
22
+ # Initialize a new WeatherXu client
23
+ #
24
+ # @param api_key [String] Your WeatherXu API key
25
+ # @param units [String] Unit system ('metric' or 'imperial')
26
+ # @param timeout [Integer] Request timeout in seconds
27
+ # @raise [Error] if API key is missing
28
+ def initialize(api_key:, units: "metric", timeout: 10)
29
+ raise Error, "API key is required" if api_key.nil? || api_key.empty?
30
+
31
+ @api_key = api_key
32
+ @units = units
33
+ @timeout = timeout
34
+ end
35
+
36
+ # Get current weather and forecast data for a location
37
+ #
38
+ # @param lat [Float] Latitude (-90 to 90)
39
+ # @param lon [Float] Longitude (-180 to 180)
40
+ # @param parts [Array<String>] Data blocks to include ('alerts', 'currently', 'hourly', 'daily')
41
+ # @param units [String, nil] Unit system ('metric' or 'imperial')
42
+ # @return [WeatherData] Weather data response
43
+ # @raise [Error] if the API request fails
44
+ def get_weather(lat:, lon:, parts: nil, units: nil)
45
+ params = {
46
+ lat: lat,
47
+ lon: lon,
48
+ units: units || @units
49
+ }
50
+ params[:parts] = parts.join(",") if parts
51
+
52
+ response = make_request(
53
+ :get,
54
+ "#{WEATHER_BASE_URL}/weather",
55
+ params
56
+ )
57
+
58
+ WeatherData.new(response)
59
+ end
60
+
61
+ # Get historical weather data for a location
62
+ #
63
+ # @param lat [Float] Latitude (-90 to 90)
64
+ # @param lon [Float] Longitude (-180 to 180)
65
+ # @param start [Integer] Start time (Unix timestamp)
66
+ # @param end_time [Integer] End time (Unix timestamp)
67
+ # @param units [String, nil] Unit system ('metric' or 'imperial')
68
+ # @return [HistoricalData] Historical weather data response
69
+ # @raise [Error] if the API request fails
70
+ def get_historical(lat:, lon:, start:, end_time:, units: nil)
71
+ params = {
72
+ lat: lat,
73
+ lon: lon,
74
+ start: start,
75
+ end: end_time,
76
+ units: units || @units
77
+ }
78
+
79
+ response = make_request(
80
+ :get,
81
+ "#{HISTORICAL_BASE_URL}/history",
82
+ params
83
+ )
84
+
85
+ HistoricalData.new(response)
86
+ end
87
+
88
+ private
89
+
90
+ def make_request(method, url, params = {})
91
+ uri = URI(url)
92
+ uri.query = URI.encode_www_form(params)
93
+
94
+ http = Net::HTTP.new(uri.host, uri.port)
95
+ http.use_ssl = true
96
+ http.read_timeout = timeout
97
+ http.open_timeout = timeout
98
+
99
+ request = Net::HTTP::Get.new(uri)
100
+ request["X-API-KEY"] = api_key
101
+ request["Content-Type"] = "application/json"
102
+
103
+ response = http.request(request)
104
+ handle_response(response)
105
+ rescue Net::OpenTimeout, Net::ReadTimeout => e
106
+ raise Error, "Request timed out: #{e.message}"
107
+ rescue SocketError, Errno::ECONNREFUSED => e
108
+ raise Error, "Connection failed: #{e.message}"
109
+ rescue StandardError => e
110
+ raise Error, "API request failed: #{e.message}"
111
+ end
112
+
113
+ def handle_response(response)
114
+ case response.code.to_i
115
+ when 200
116
+ JSON.parse(response.body)
117
+ when 401
118
+ raise Error, "Unauthorized: Invalid API key"
119
+ when 429
120
+ raise Error, "Rate limit exceeded"
121
+ else
122
+ begin
123
+ error_body = JSON.parse(response.body)
124
+ raise Error, error_body["error"]["message"] if error_body["error"]
125
+ rescue JSON::ParserError
126
+ # If we can't parse the error body, use the status text
127
+ raise Error, "API request failed with status #{response.code}: #{response.message}"
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WeatherXu
4
+ # Custom error class for WeatherXu API errors
5
+ class Error < StandardError
6
+ attr_reader :status_code, :error_code
7
+
8
+ def initialize(message, status_code: nil, error_code: nil)
9
+ super(message)
10
+ @status_code = status_code
11
+ @error_code = error_code
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,173 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "time"
4
+
5
+ module WeatherXu
6
+ # Base class for API responses
7
+ class BaseModel
8
+ def initialize(data)
9
+ data.each do |key, value|
10
+ instance_variable_set("@#{key}", value)
11
+ end
12
+ end
13
+ end
14
+
15
+ # Weather data response
16
+ class WeatherData < BaseModel
17
+ attr_reader :success, :data
18
+
19
+ def initialize(data)
20
+ @success = data["success"]
21
+ @data = data["data"]
22
+
23
+ if @data
24
+ @data["alerts"] = @data["alerts"]&.map { |alert| Alert.new(alert) }
25
+ @data["currently"] = CurrentConditions.new(@data["currently"]) if @data["currently"]
26
+ @data["hourly"] = { "data" => @data["hourly"]["data"].map { |hour| HourlyCondition.new(hour) } } if @data["hourly"]
27
+ @data["daily"] = { "data" => @data["daily"]["data"].map { |day| DailyCondition.new(day) } } if @data["daily"]
28
+ end
29
+ end
30
+ end
31
+
32
+ # Historical weather data response
33
+ class HistoricalData < BaseModel
34
+ attr_reader :success, :data
35
+
36
+ def initialize(data)
37
+ @success = data["success"]
38
+ @data = data["data"]
39
+
40
+ if @data && @data["hourly"]
41
+ @data["hourly"] = {
42
+ "data" => @data["hourly"]["data"].map { |hour| HistoricalHourlyCondition.new(hour) }
43
+ }
44
+ end
45
+ end
46
+ end
47
+
48
+ # Weather alert information
49
+ class Alert < BaseModel
50
+ attr_reader :title, :description, :ends_at
51
+
52
+ def initialize(data)
53
+ super(data)
54
+ @ends_at = data["endsAt"]
55
+ end
56
+ end
57
+
58
+ # Current weather conditions
59
+ class CurrentConditions < BaseModel
60
+ attr_reader :apparent_temperature, :cloud_cover, :dew_point, :humidity,
61
+ :icon, :precip_intensity, :pressure, :temperature, :uv_index,
62
+ :visibility, :wind_direction, :wind_gust, :wind_speed
63
+
64
+ def initialize(data)
65
+ @apparent_temperature = data["apparentTemperature"]
66
+ @cloud_cover = data["cloudCover"]
67
+ @dew_point = data["dewPoint"]
68
+ @humidity = data["humidity"]
69
+ @icon = data["icon"]
70
+ @precip_intensity = data["precipIntensity"]
71
+ @pressure = data["pressure"]
72
+ @temperature = data["temperature"]
73
+ @uv_index = data["uvIndex"]
74
+ @visibility = data["visibility"]
75
+ @wind_direction = data["windDirection"]
76
+ @wind_gust = data["windGust"]
77
+ @wind_speed = data["windSpeed"]
78
+ end
79
+ end
80
+
81
+ # Hourly weather condition
82
+ class HourlyCondition < BaseModel
83
+ attr_reader :apparent_temperature, :cloud_cover, :dew_point, :forecast_start,
84
+ :humidity, :icon, :precip_intensity, :precip_probability, :pressure,
85
+ :temperature, :uv_index, :visibility, :wind_direction, :wind_gust,
86
+ :wind_speed
87
+
88
+ def initialize(data)
89
+ @apparent_temperature = data["apparentTemperature"]
90
+ @cloud_cover = data["cloudCover"]
91
+ @dew_point = data["dewPoint"]
92
+ @forecast_start = data["forecastStart"]
93
+ @humidity = data["humidity"]
94
+ @icon = data["icon"]
95
+ @precip_intensity = data["precipIntensity"]
96
+ @precip_probability = data["precipProbability"]
97
+ @pressure = data["pressure"]
98
+ @temperature = data["temperature"]
99
+ @uv_index = data["uvIndex"]
100
+ @visibility = data["visibility"]
101
+ @wind_direction = data["windDirection"]
102
+ @wind_gust = data["windGust"]
103
+ @wind_speed = data["windSpeed"]
104
+ end
105
+ end
106
+
107
+ # Historical hourly condition
108
+ class HistoricalHourlyCondition < BaseModel
109
+ attr_reader :apparent_temperature, :cloud_cover, :dew_point, :forecast_start,
110
+ :humidity, :icon, :precip_intensity, :pressure, :temperature,
111
+ :wind_direction, :wind_gust, :wind_speed
112
+
113
+ def initialize(data)
114
+ @apparent_temperature = data["apparentTemperature"]
115
+ @cloud_cover = data["cloudCover"]
116
+ @dew_point = data["dewPoint"]
117
+ @forecast_start = data["forecastStart"]
118
+ @humidity = data["humidity"]
119
+ @icon = data["icon"]
120
+ @precip_intensity = data["precipIntensity"]
121
+ @pressure = data["pressure"]
122
+ @temperature = data["temperature"]
123
+ @wind_direction = data["windDirection"]
124
+ @wind_gust = data["windGust"]
125
+ @wind_speed = data["windSpeed"]
126
+ end
127
+ end
128
+
129
+ # Daily weather condition
130
+ class DailyCondition < BaseModel
131
+ attr_reader :apparent_temperature_avg, :apparent_temperature_max,
132
+ :apparent_temperature_min, :cloud_cover, :dew_point_avg,
133
+ :dew_point_max, :dew_point_min, :forecast_end, :forecast_start,
134
+ :humidity, :icon, :moon_phase, :precip_intensity,
135
+ :precip_probability, :pressure, :sunrise_time, :sunset_time,
136
+ :temperature_avg, :temperature_max, :temperature_min,
137
+ :uv_index_max, :visibility, :wind_direction_avg, :wind_gust_avg,
138
+ :wind_gust_max, :wind_gust_min, :wind_speed_avg, :wind_speed_max,
139
+ :wind_speed_min
140
+
141
+ def initialize(data)
142
+ @apparent_temperature_avg = data["apparentTemperatureAvg"]
143
+ @apparent_temperature_max = data["apparentTemperatureMax"]
144
+ @apparent_temperature_min = data["apparentTemperatureMin"]
145
+ @cloud_cover = data["cloudCover"]
146
+ @dew_point_avg = data["dewPointAvg"]
147
+ @dew_point_max = data["dewPointMax"]
148
+ @dew_point_min = data["dewPointMin"]
149
+ @forecast_end = data["forecastEnd"]
150
+ @forecast_start = data["forecastStart"]
151
+ @humidity = data["humidity"]
152
+ @icon = data["icon"]
153
+ @moon_phase = data["moonPhase"]
154
+ @precip_intensity = data["precipIntensity"]
155
+ @precip_probability = data["precipProbability"]
156
+ @pressure = data["pressure"]
157
+ @sunrise_time = data["sunriseTime"]
158
+ @sunset_time = data["sunsetTime"]
159
+ @temperature_avg = data["temperatureAvg"]
160
+ @temperature_max = data["temperatureMax"]
161
+ @temperature_min = data["temperatureMin"]
162
+ @uv_index_max = data["uvIndexMax"]
163
+ @visibility = data["visibility"]
164
+ @wind_direction_avg = data["windDirectionAvg"]
165
+ @wind_gust_avg = data["windGustAvg"]
166
+ @wind_gust_max = data["windGustMax"]
167
+ @wind_gust_min = data["windGustMin"]
168
+ @wind_speed_avg = data["windSpeedAvg"]
169
+ @wind_speed_max = data["windSpeedMax"]
170
+ @wind_speed_min = data["windSpeedMin"]
171
+ end
172
+ end
173
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WeatherXu
4
+ VERSION = "1.0.0"
5
+ end
data/lib/weatherxu.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "weatherxu/version"
4
+ require_relative "weatherxu/error"
5
+ require_relative "weatherxu/models"
6
+ require_relative "weatherxu/client"
7
+
8
+ # WeatherXu module for accessing weather data
9
+ module WeatherXu
10
+ class << self
11
+ # Create a new client instance
12
+ #
13
+ # @param api_key [String] Your WeatherXu API key
14
+ # @param units [String] Unit system ('metric' or 'imperial')
15
+ # @param timeout [Integer] Request timeout in seconds
16
+ # @return [Client] A new client instance
17
+ def new(api_key:, units: "metric", timeout: 10)
18
+ Client.new(api_key: api_key, units: units, timeout: timeout)
19
+ end
20
+ end
21
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: weatherxu
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - WeatherXu
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '13.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '13.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rubocop
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.21'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.21'
69
+ - !ruby/object:Gem::Dependency
70
+ name: yard
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
83
+ description: A Ruby SDK for accessing WeatherXu's weather data, including current
84
+ conditions, forecasts, and historical weather data.
85
+ email:
86
+ - support@weatherxu.com
87
+ executables: []
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - LICENSE
92
+ - README.md
93
+ - lib/weatherxu.rb
94
+ - lib/weatherxu/client.rb
95
+ - lib/weatherxu/error.rb
96
+ - lib/weatherxu/models.rb
97
+ - lib/weatherxu/version.rb
98
+ homepage: https://weatherxu.com
99
+ licenses:
100
+ - MIT
101
+ metadata:
102
+ homepage_uri: https://weatherxu.com
103
+ source_code_uri: https://github.com/weatherxu/weatherxu-ruby
104
+ changelog_uri: https://github.com/weatherxu/weatherxu-ruby/blob/main/CHANGELOG.md
105
+ documentation_uri: https://weatherxu.com/documentation
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: 2.6.0
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubygems_version: 3.4.10
122
+ signing_key:
123
+ specification_version: 4
124
+ summary: Official Ruby SDK for WeatherXu's weather data API
125
+ test_files: []