open-meteo 0.0.3 → 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 +4 -4
- data/lib/open_meteo/client/config.rb +4 -3
- data/lib/open_meteo/configuration.rb +31 -0
- data/lib/open_meteo/entities/contracts/application_contract.rb +30 -0
- data/lib/open_meteo/entities/contracts/location_contract.rb +18 -0
- data/lib/open_meteo/entities/forecast/current.rb +20 -0
- data/lib/open_meteo/entities/forecast/daily.rb +33 -0
- data/lib/open_meteo/entities/forecast/hourly.rb +33 -0
- data/lib/open_meteo/entities/forecast/item.rb +81 -0
- data/lib/open_meteo/entities/forecast/units.rb +32 -0
- data/lib/open_meteo/entities/forecast.rb +37 -0
- data/lib/open_meteo/entities/location.rb +20 -0
- data/lib/open_meteo/errors.rb +6 -0
- data/lib/open_meteo/forecast/variables.rb +32 -0
- data/lib/open_meteo/forecast.rb +8 -7
- data/lib/open_meteo/response_wrapper.rb +40 -0
- data/lib/open_meteo/types.rb +1 -1
- data/lib/open_meteo/version.rb +1 -1
- data/lib/open_meteo.rb +35 -1
- metadata +16 -8
- data/lib/open_meteo/application_contract.rb +0 -26
- data/lib/open_meteo/forecast/variables/general.rb +0 -40
- data/lib/open_meteo/forecast/variables/general_contract.rb +0 -286
- data/lib/open_meteo/location.rb +0 -18
- data/lib/open_meteo/location_contract.rb +0 -14
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 1c6c6b4ccb93360c8c3f27479f8bc01cc5cc37a7d14f2ff6942d745e3bd243a8
         | 
| 4 | 
            +
              data.tar.gz: e10768db1766c5c7a48f8c68e6b15d2e367aefa0dc1bc3fc9a3fa263ce7cca93
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 966bbb364b37dc3e4fe846516f862216c172e242949b5b64d45afded542336f704904e6725b7fcb867de0481a23988789c4392f7480c62dc24491d62b65740fa
         | 
| 7 | 
            +
              data.tar.gz: 694c506e84309461346622763b562f34cd9f11d6fb34d7ab81b25faa7a808298cc07ecb58e02765ae9abd8a80b4122df388f9a57d657b7b63131e7cda07008ee
         | 
| @@ -3,10 +3,11 @@ module OpenMeteo | |
| 3 3 | 
             
                ##
         | 
| 4 4 | 
             
                # The configuration for the OpenMeteo::Client.
         | 
| 5 5 | 
             
                class Config
         | 
| 6 | 
            -
                  attr_reader :host
         | 
| 6 | 
            +
                  attr_reader :host, :logger
         | 
| 7 7 |  | 
| 8 | 
            -
                  def initialize(host:  | 
| 9 | 
            -
                    @host = host
         | 
| 8 | 
            +
                  def initialize(host: nil, logger: nil)
         | 
| 9 | 
            +
                    @host = host || OpenMeteo.configuration.host
         | 
| 10 | 
            +
                    @logger = logger || OpenMeteo.configuration.logger
         | 
| 10 11 | 
             
                  end
         | 
| 11 12 |  | 
| 12 13 | 
             
                  def url
         | 
| @@ -0,0 +1,31 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              ##
         | 
| 3 | 
            +
              # The global configuration of the OpenMeteo client.
         | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              # @see OpenMeteo.configure
         | 
| 6 | 
            +
              class Configuration
         | 
| 7 | 
            +
                def initialize
         | 
| 8 | 
            +
                  @config = {}
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                ##
         | 
| 12 | 
            +
                # Create a getter and a setter for a setting.
         | 
| 13 | 
            +
                #
         | 
| 14 | 
            +
                # If the default value is a Proc, it will be called on initialize.
         | 
| 15 | 
            +
                #
         | 
| 16 | 
            +
                # @param name: Symbol
         | 
| 17 | 
            +
                # @param default: Proc | Object
         | 
| 18 | 
            +
                def self.add_setting(name, default)
         | 
| 19 | 
            +
                  define_method name do
         | 
| 20 | 
            +
                    @config[name] ||= default.is_a?(Proc) ? default.call : default
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                  define_method "#{name}=" do |value|
         | 
| 24 | 
            +
                    @config[name] = value
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                add_setting :logger, -> { Logger.new($stdout) }
         | 
| 29 | 
            +
                add_setting :host, "api.open-meteo.com"
         | 
| 30 | 
            +
              end
         | 
| 31 | 
            +
            end
         | 
| @@ -0,0 +1,30 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                module Contracts
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # Shared functionality for dry contracts.
         | 
| 6 | 
            +
                  class ApplicationContract < Dry::Validation::Contract
         | 
| 7 | 
            +
                    ##
         | 
| 8 | 
            +
                    # A validation error that can be raised on contract validation.
         | 
| 9 | 
            +
                    class ValidationError < StandardError
         | 
| 10 | 
            +
                      attr_reader :result, :errors
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      def initialize(result)
         | 
| 13 | 
            +
                        @errors = result.errors
         | 
| 14 | 
            +
                        first_error_key = result.errors.first.path.first
         | 
| 15 | 
            +
                        first_error_value = result[first_error_key]
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                        super(
         | 
| 18 | 
            +
                          "Validation failed: :#{first_error_key} is #{first_error_value} but #{errors.first.text}",
         | 
| 19 | 
            +
                        )
         | 
| 20 | 
            +
                      end
         | 
| 21 | 
            +
                    end
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                    def self.validate!(object)
         | 
| 24 | 
            +
                      result = new.call(object)
         | 
| 25 | 
            +
                      raise ValidationError, result unless result.errors.empty?
         | 
| 26 | 
            +
                    end
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
              end
         | 
| 30 | 
            +
            end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                module Contracts
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # Validation contract for OpenMeteo::Entities::Location.
         | 
| 6 | 
            +
                  class LocationContract < OpenMeteo::Entities::Contracts::ApplicationContract
         | 
| 7 | 
            +
                    params do
         | 
| 8 | 
            +
                      required(:latitude).filled(:float)
         | 
| 9 | 
            +
                      required(:longitude).filled(:float)
         | 
| 10 | 
            +
                    end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                    rule(:latitude) { key.failure("must be within [-90;90]") if value < -90 || value > 90 }
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                    rule(:longitude) { key.failure("must be within [-180;180]") if value < -180 || value > 180 }
         | 
| 15 | 
            +
                  end
         | 
| 16 | 
            +
                end
         | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                class Forecast
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # A forecast Entity for current data returned by OpenMeteo
         | 
| 6 | 
            +
                  class Current
         | 
| 7 | 
            +
                    attr_reader :item, :units, :raw_json_current, :raw_json_current_units
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def initialize(json_current, json_current_units)
         | 
| 10 | 
            +
                      @item = json_current && OpenMeteo::Entities::Forecast::Item.new(json_current)
         | 
| 11 | 
            +
                      @units =
         | 
| 12 | 
            +
                        json_current_units && OpenMeteo::Entities::Forecast::Units.new(json_current_units)
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                      @raw_json_current = json_current
         | 
| 15 | 
            +
                      @raw_json_current_units = json_current_units
         | 
| 16 | 
            +
                    end
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                class Forecast
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # A forecast Entity for daily data returned by OpenMeteo
         | 
| 6 | 
            +
                  class Daily
         | 
| 7 | 
            +
                    attr_reader :items, :units, :raw_json_daily, :raw_json_daily_units
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def initialize(json_daily, json_daily_units)
         | 
| 10 | 
            +
                      @items = initialize_items(json_daily)
         | 
| 11 | 
            +
                      @units = json_daily_units && OpenMeteo::Entities::Forecast::Units.new(json_daily_units)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                      @raw_json_daily = json_daily
         | 
| 14 | 
            +
                      @raw_json_daily_units = json_daily_units
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def initialize_items(json_daily)
         | 
| 20 | 
            +
                      json_daily["time"]
         | 
| 21 | 
            +
                        .map do |element|
         | 
| 22 | 
            +
                          json_daily
         | 
| 23 | 
            +
                            .keys
         | 
| 24 | 
            +
                            .each_with_object({}) do |attr, json_item|
         | 
| 25 | 
            +
                              json_item[attr] = json_daily[attr][json_daily["time"].index(element)]
         | 
| 26 | 
            +
                            end
         | 
| 27 | 
            +
                        end
         | 
| 28 | 
            +
                        .map { |json_item| OpenMeteo::Entities::Forecast::Item.new(json_item) }
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                class Forecast
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # A forecast Entity for hourly data returned by OpenMeteo
         | 
| 6 | 
            +
                  class Hourly
         | 
| 7 | 
            +
                    attr_reader :items, :units, :raw_json_hourly, :raw_json_hourly_units
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def initialize(json_hourly, json_hourly_units)
         | 
| 10 | 
            +
                      @items = initialize_items(json_hourly)
         | 
| 11 | 
            +
                      @units = json_hourly_units && OpenMeteo::Entities::Forecast::Units.new(json_hourly_units)
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                      @raw_json_hourly = json_hourly
         | 
| 14 | 
            +
                      @raw_json_hourly_units = json_hourly_units
         | 
| 15 | 
            +
                    end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    private
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                    def initialize_items(json_hourly)
         | 
| 20 | 
            +
                      json_hourly["time"]
         | 
| 21 | 
            +
                        .map do |element|
         | 
| 22 | 
            +
                          json_hourly
         | 
| 23 | 
            +
                            .keys
         | 
| 24 | 
            +
                            .each_with_object({}) do |attr, json_item|
         | 
| 25 | 
            +
                              json_item[attr] = json_hourly[attr][json_hourly["time"].index(element)]
         | 
| 26 | 
            +
                            end
         | 
| 27 | 
            +
                        end
         | 
| 28 | 
            +
                        .map { |json_item| OpenMeteo::Entities::Forecast::Item.new(json_item) }
         | 
| 29 | 
            +
                    end
         | 
| 30 | 
            +
                  end
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 33 | 
            +
            end
         | 
| @@ -0,0 +1,81 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                class Forecast
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # A forecast entity for a data item returned by OpenMeteo
         | 
| 6 | 
            +
                  class Item
         | 
| 7 | 
            +
                    class UnknownWeatherCode < StandardError
         | 
| 8 | 
            +
                    end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                    ##
         | 
| 11 | 
            +
                    # The conversion map of weather_codes to a more descriptive symbol.
         | 
| 12 | 
            +
                    #
         | 
| 13 | 
            +
                    # See "WMO Weather interpretation codes (WW)" on
         | 
| 14 | 
            +
                    # https://open-meteo.com/en/docs
         | 
| 15 | 
            +
                    WMO_CODE_TO_SYMBOL_MAP = {
         | 
| 16 | 
            +
                      0 => :clear_sky,
         | 
| 17 | 
            +
                      1 => :mainly_clear,
         | 
| 18 | 
            +
                      2 => :partly_cloudy,
         | 
| 19 | 
            +
                      3 => :overcast,
         | 
| 20 | 
            +
                      45 => :fog,
         | 
| 21 | 
            +
                      48 => :depositing_rime_fog,
         | 
| 22 | 
            +
                      51 => :drizzle_light,
         | 
| 23 | 
            +
                      53 => :drizzle_moderate,
         | 
| 24 | 
            +
                      55 => :drizzle_dense,
         | 
| 25 | 
            +
                      56 => :freezing_drizzle_light,
         | 
| 26 | 
            +
                      57 => :freezing_drizzle_dense,
         | 
| 27 | 
            +
                      61 => :rain_slight,
         | 
| 28 | 
            +
                      63 => :rain_moderate,
         | 
| 29 | 
            +
                      65 => :rain_heavy,
         | 
| 30 | 
            +
                      66 => :freezing_rain_slight,
         | 
| 31 | 
            +
                      67 => :freezing_rain_heavy,
         | 
| 32 | 
            +
                      71 => :snow_slight,
         | 
| 33 | 
            +
                      73 => :snow_moderate,
         | 
| 34 | 
            +
                      75 => :snow_heavy,
         | 
| 35 | 
            +
                      77 => :snow_grains,
         | 
| 36 | 
            +
                      80 => :rain_showers_slight,
         | 
| 37 | 
            +
                      81 => :rain_showers_moderate,
         | 
| 38 | 
            +
                      82 => :rain_showers_violent,
         | 
| 39 | 
            +
                      85 => :snow_showers_slight,
         | 
| 40 | 
            +
                      86 => :snow_showers_heavy,
         | 
| 41 | 
            +
                      95 => :thunderstorm_slight_or_moderate,
         | 
| 42 | 
            +
                      96 => :thunderstorm_with_slight_hail,
         | 
| 43 | 
            +
                      99 => :thunderstorm_with_heavy_hail,
         | 
| 44 | 
            +
                    }.freeze
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                    attr_reader :raw_json, :attributes, :time
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                    def initialize(json_data)
         | 
| 49 | 
            +
                      @raw_json = json_data
         | 
| 50 | 
            +
             | 
| 51 | 
            +
                      @attributes = json_data.keys
         | 
| 52 | 
            +
                      @time = json_data["time"]
         | 
| 53 | 
            +
                    end
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                    ##
         | 
| 56 | 
            +
                    # Provide a symbol for the weather_code.
         | 
| 57 | 
            +
                    #
         | 
| 58 | 
            +
                    # @see WMO_CODE_TO_SYMBOL_MAP
         | 
| 59 | 
            +
                    def weather_code_symbol
         | 
| 60 | 
            +
                      return if weather_code.nil?
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                      WMO_CODE_TO_SYMBOL_MAP.fetch(weather_code) { raise UnknownWeatherCode, weather_code }
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                    private
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                    def method_missing(name, *args)
         | 
| 68 | 
            +
                      if raw_json.key?(name.to_s)
         | 
| 69 | 
            +
                        raw_json[name.to_s]
         | 
| 70 | 
            +
                      else
         | 
| 71 | 
            +
                        super
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
             | 
| 75 | 
            +
                    def respond_to_missing?(name, include_private = false)
         | 
| 76 | 
            +
                      raw_json.key?(name.to_s) || super
         | 
| 77 | 
            +
                    end
         | 
| 78 | 
            +
                  end
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
              end
         | 
| 81 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              module Entities
         | 
| 3 | 
            +
                class Forecast
         | 
| 4 | 
            +
                  ##
         | 
| 5 | 
            +
                  # A forecast entity for data units returned by OpenMeteo
         | 
| 6 | 
            +
                  class Units
         | 
| 7 | 
            +
                    attr_reader :raw_json_units, :attributes, :time
         | 
| 8 | 
            +
             | 
| 9 | 
            +
                    def initialize(json_units)
         | 
| 10 | 
            +
                      @raw_json_units = json_units
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                      @attributes = json_units.keys
         | 
| 13 | 
            +
                      @time = json_units["time"]
         | 
| 14 | 
            +
                    end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                    private
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                    def method_missing(name, *args)
         | 
| 19 | 
            +
                      if raw_json_units.key?(name.to_s)
         | 
| 20 | 
            +
                        raw_json_units[name.to_s]
         | 
| 21 | 
            +
                      else
         | 
| 22 | 
            +
                        super
         | 
| 23 | 
            +
                      end
         | 
| 24 | 
            +
                    end
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                    def respond_to_missing?(name, include_private = false)
         | 
| 27 | 
            +
                      raw_json_units.key?(name.to_s) || super
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            require_relative "forecast/current"
         | 
| 2 | 
            +
            require_relative "forecast/hourly"
         | 
| 3 | 
            +
            require_relative "forecast/daily"
         | 
| 4 | 
            +
            require_relative "forecast/units"
         | 
| 5 | 
            +
            require_relative "forecast/item"
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            module OpenMeteo
         | 
| 8 | 
            +
              module Entities
         | 
| 9 | 
            +
                #
         | 
| 10 | 
            +
                # A forecast Entity with data returned by OpenMeteo
         | 
| 11 | 
            +
                class Forecast
         | 
| 12 | 
            +
                  attr_reader :attributes, :current, :hourly, :daily, :raw_json
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def initialize(json_body)
         | 
| 15 | 
            +
                    @raw_json = json_body
         | 
| 16 | 
            +
             | 
| 17 | 
            +
                    @current =
         | 
| 18 | 
            +
                      json_body["current"] &&
         | 
| 19 | 
            +
                        OpenMeteo::Entities::Forecast::Current.new(
         | 
| 20 | 
            +
                          json_body["current"],
         | 
| 21 | 
            +
                          json_body["current_units"],
         | 
| 22 | 
            +
                        )
         | 
| 23 | 
            +
                    @hourly =
         | 
| 24 | 
            +
                      json_body["hourly"] &&
         | 
| 25 | 
            +
                        OpenMeteo::Entities::Forecast::Hourly.new(
         | 
| 26 | 
            +
                          json_body["hourly"],
         | 
| 27 | 
            +
                          json_body["hourly_units"],
         | 
| 28 | 
            +
                        )
         | 
| 29 | 
            +
                    @daily =
         | 
| 30 | 
            +
                      json_body["daily"] &&
         | 
| 31 | 
            +
                        OpenMeteo::Entities::Forecast::Daily.new(json_body["daily"], json_body["daily_units"])
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                    @attributes = json_body.keys
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,20 @@ | |
| 1 | 
            +
            require_relative "contracts/location_contract"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module OpenMeteo
         | 
| 4 | 
            +
              module Entities
         | 
| 5 | 
            +
                ##
         | 
| 6 | 
            +
                # A location for a request to OpenMeteo.
         | 
| 7 | 
            +
                class Location < Dry::Struct
         | 
| 8 | 
            +
                  attribute :latitude, OpenMeteo::Types::Coercible::Decimal
         | 
| 9 | 
            +
                  attribute :longitude, OpenMeteo::Types::Coercible::Decimal
         | 
| 10 | 
            +
             | 
| 11 | 
            +
                  def validate!
         | 
| 12 | 
            +
                    OpenMeteo::Entities::Contracts::LocationContract.validate!(to_hash)
         | 
| 13 | 
            +
                  end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                  def to_get_params
         | 
| 16 | 
            +
                    { latitude:, longitude: }
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
              end
         | 
| 20 | 
            +
            end
         | 
| @@ -0,0 +1,32 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              class Forecast
         | 
| 3 | 
            +
                ##
         | 
| 4 | 
            +
                # The Variables for a forecast request to the OpenMeteo API.
         | 
| 5 | 
            +
                #
         | 
| 6 | 
            +
                # See https://open-meteo.com/en/docs
         | 
| 7 | 
            +
                class Variables < Dry::Struct
         | 
| 8 | 
            +
                  attribute(
         | 
| 9 | 
            +
                    :current,
         | 
| 10 | 
            +
                    OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
         | 
| 11 | 
            +
                  )
         | 
| 12 | 
            +
                  attribute(
         | 
| 13 | 
            +
                    :hourly,
         | 
| 14 | 
            +
                    OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
         | 
| 15 | 
            +
                  )
         | 
| 16 | 
            +
                  attribute(
         | 
| 17 | 
            +
                    :daily,
         | 
| 18 | 
            +
                    OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
         | 
| 19 | 
            +
                  )
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                  def to_get_params
         | 
| 22 | 
            +
                    get_params = {}
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                    get_params[:current] = current.join(",") if current != []
         | 
| 25 | 
            +
                    get_params[:hourly] = hourly.join(",") if hourly != []
         | 
| 26 | 
            +
                    get_params[:daily] = daily.join(",") if daily != []
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                    get_params
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
            end
         | 
    
        data/lib/open_meteo/forecast.rb
    CHANGED
    
    | @@ -1,5 +1,5 @@ | |
| 1 1 | 
             
            require_relative "client"
         | 
| 2 | 
            -
            require_relative "forecast/variables | 
| 2 | 
            +
            require_relative "forecast/variables"
         | 
| 3 3 |  | 
| 4 4 | 
             
            module OpenMeteo
         | 
| 5 5 | 
             
              ##
         | 
| @@ -12,8 +12,9 @@ module OpenMeteo | |
| 12 12 | 
             
                class WrongLocationType < StandardError
         | 
| 13 13 | 
             
                end
         | 
| 14 14 |  | 
| 15 | 
            -
                def initialize(client: OpenMeteo::Client.new)
         | 
| 15 | 
            +
                def initialize(client: OpenMeteo::Client.new, response_wrapper: OpenMeteo::ResponseWrapper.new)
         | 
| 16 16 | 
             
                  @client = client
         | 
| 17 | 
            +
                  @response_wrapper = response_wrapper
         | 
| 17 18 | 
             
                end
         | 
| 18 19 |  | 
| 19 20 | 
             
                def get(location:, variables:, model: :general)
         | 
| @@ -21,8 +22,7 @@ module OpenMeteo | |
| 21 22 |  | 
| 22 23 | 
             
                  model_definition = get_model_definition(model)
         | 
| 23 24 |  | 
| 24 | 
            -
                  variables_object =  | 
| 25 | 
            -
                  variables_object.validate!
         | 
| 25 | 
            +
                  variables_object = OpenMeteo::Forecast::Variables.new(**variables)
         | 
| 26 26 |  | 
| 27 27 | 
             
                  get_forecast(model_definition[:endpoint], location, variables_object)
         | 
| 28 28 | 
             
                end
         | 
| @@ -34,7 +34,6 @@ module OpenMeteo | |
| 34 34 | 
             
                AVAILABLE_FORECAST_MODELS = {
         | 
| 35 35 | 
             
                  general: {
         | 
| 36 36 | 
             
                    # See https://open-meteo.com/en/docs
         | 
| 37 | 
            -
                    variables_class: OpenMeteo::Forecast::Variables::General,
         | 
| 38 37 | 
             
                    endpoint: :forecast,
         | 
| 39 38 | 
             
                  },
         | 
| 40 39 | 
             
                }.freeze
         | 
| @@ -44,14 +43,16 @@ module OpenMeteo | |
| 44 43 | 
             
                end
         | 
| 45 44 |  | 
| 46 45 | 
             
                def ensure_valid_location(location)
         | 
| 47 | 
            -
                  raise WrongLocationType unless location.is_a? OpenMeteo::Location
         | 
| 46 | 
            +
                  raise WrongLocationType unless location.is_a? OpenMeteo::Entities::Location
         | 
| 48 47 |  | 
| 49 48 | 
             
                  location.validate!
         | 
| 50 49 | 
             
                end
         | 
| 51 50 |  | 
| 52 51 | 
             
                def get_forecast(endpoint, location, variables)
         | 
| 53 52 | 
             
                  get_params = { **location.to_get_params, **variables.to_get_params }
         | 
| 54 | 
            -
                  client.get(endpoint, **get_params)
         | 
| 53 | 
            +
                  response = client.get(endpoint, **get_params)
         | 
| 54 | 
            +
             | 
| 55 | 
            +
                  @response_wrapper.wrap(response, entity: OpenMeteo::Entities::Forecast)
         | 
| 55 56 | 
             
                end
         | 
| 56 57 | 
             
              end
         | 
| 57 58 | 
             
            end
         | 
| @@ -0,0 +1,40 @@ | |
| 1 | 
            +
            module OpenMeteo
         | 
| 2 | 
            +
              ##
         | 
| 3 | 
            +
              # Wrap the JSON body response from the OpenMeteo request.
         | 
| 4 | 
            +
              #
         | 
| 5 | 
            +
              class ResponseWrapper
         | 
| 6 | 
            +
                def initialize(config: OpenMeteo::Client::Config.new)
         | 
| 7 | 
            +
                  @config = config
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def wrap(response, entity:)
         | 
| 11 | 
            +
                  raise OpenMeteo::Errors::ResponseError, "Empty body" if response.body.nil?
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                  json_body = JSON.parse(response.body)
         | 
| 14 | 
            +
                  check_for_error(response, json_body)
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                  entity.new(json_body)
         | 
| 17 | 
            +
                rescue JSON::ParserError
         | 
| 18 | 
            +
                  raise OpenMeteo::Errors::ResponseError, "Unable to parse the response body: #{response.body}"
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def check_for_error(response, json_body)
         | 
| 24 | 
            +
                  return if response.status == 200
         | 
| 25 | 
            +
             | 
| 26 | 
            +
                  error_messages = extract_error_messages(json_body)
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                  @config.logger.debug(error_messages)
         | 
| 29 | 
            +
             | 
| 30 | 
            +
                  raise OpenMeteo::Errors::ResponseError, error_messages
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                def extract_error_messages(json_body)
         | 
| 34 | 
            +
                  error_value = json_body["error"]
         | 
| 35 | 
            +
                  return "" if error_value.nil? || error_value == false
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                  json_body["reason"].to_s
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
            end
         | 
    
        data/lib/open_meteo/types.rb
    CHANGED
    
    
    
        data/lib/open_meteo/version.rb
    CHANGED
    
    
    
        data/lib/open_meteo.rb
    CHANGED
    
    | @@ -1,3 +1,37 @@ | |
| 1 1 | 
             
            require "open_meteo/types"
         | 
| 2 | 
            -
            require "open_meteo/ | 
| 2 | 
            +
            require "open_meteo/configuration"
         | 
| 3 | 
            +
            require "open_meteo/entities/location"
         | 
| 4 | 
            +
            require "open_meteo/entities/forecast"
         | 
| 3 5 | 
             
            require "open_meteo/forecast"
         | 
| 6 | 
            +
            require "open_meteo/response_wrapper"
         | 
| 7 | 
            +
            require "open_meteo/errors"
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            ##
         | 
| 10 | 
            +
            # The OpenMeteo client.
         | 
| 11 | 
            +
            module OpenMeteo
         | 
| 12 | 
            +
              # Returns the global `OpenMeteo::Configuration` object. While
         | 
| 13 | 
            +
              # you _can_ use this method to access the configuration, the more common
         | 
| 14 | 
            +
              # convention is to use `OpenMeteo.configure``
         | 
| 15 | 
            +
              #
         | 
| 16 | 
            +
              # @example
         | 
| 17 | 
            +
              #     OpenMeteo.configuration.logger = Logger.new($stdout)
         | 
| 18 | 
            +
              # @see OpenMeteo.configure
         | 
| 19 | 
            +
              # @see OpenMeteo::Configuration
         | 
| 20 | 
            +
              def self.configuration
         | 
| 21 | 
            +
                @configuration ||= OpenMeteo::Configuration.new
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              # Yields the global configuration to a block.
         | 
| 25 | 
            +
              # @yield [Configuration] global configuration
         | 
| 26 | 
            +
              #
         | 
| 27 | 
            +
              # @example
         | 
| 28 | 
            +
              #     OpenMeteo.configure do |config|
         | 
| 29 | 
            +
              #       config.logger Logger.new($stdout)
         | 
| 30 | 
            +
              #     end
         | 
| 31 | 
            +
              # @see OpenMeteo::Configuration
         | 
| 32 | 
            +
              def self.configure
         | 
| 33 | 
            +
                raise ArgumentError, "Please provide a block to configure" unless block_given?
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                yield configuration
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,14 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: open-meteo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0 | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Peter Morgenstern
         | 
| 8 8 | 
             
            autorequire:
         | 
| 9 9 | 
             
            bindir: bin
         | 
| 10 10 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date: 2023-11- | 
| 11 | 
            +
            date: 2023-11-08 00:00:00.000000000 Z
         | 
| 12 12 | 
             
            dependencies:
         | 
| 13 13 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 14 | 
             
              name: dry-struct
         | 
| @@ -78,15 +78,23 @@ extensions: [] | |
| 78 78 | 
             
            extra_rdoc_files: []
         | 
| 79 79 | 
             
            files:
         | 
| 80 80 | 
             
            - lib/open_meteo.rb
         | 
| 81 | 
            -
            - lib/open_meteo/application_contract.rb
         | 
| 82 81 | 
             
            - lib/open_meteo/client.rb
         | 
| 83 82 | 
             
            - lib/open_meteo/client/config.rb
         | 
| 84 83 | 
             
            - lib/open_meteo/client/url_builder.rb
         | 
| 84 | 
            +
            - lib/open_meteo/configuration.rb
         | 
| 85 | 
            +
            - lib/open_meteo/entities/contracts/application_contract.rb
         | 
| 86 | 
            +
            - lib/open_meteo/entities/contracts/location_contract.rb
         | 
| 87 | 
            +
            - lib/open_meteo/entities/forecast.rb
         | 
| 88 | 
            +
            - lib/open_meteo/entities/forecast/current.rb
         | 
| 89 | 
            +
            - lib/open_meteo/entities/forecast/daily.rb
         | 
| 90 | 
            +
            - lib/open_meteo/entities/forecast/hourly.rb
         | 
| 91 | 
            +
            - lib/open_meteo/entities/forecast/item.rb
         | 
| 92 | 
            +
            - lib/open_meteo/entities/forecast/units.rb
         | 
| 93 | 
            +
            - lib/open_meteo/entities/location.rb
         | 
| 94 | 
            +
            - lib/open_meteo/errors.rb
         | 
| 85 95 | 
             
            - lib/open_meteo/forecast.rb
         | 
| 86 | 
            -
            - lib/open_meteo/forecast/variables | 
| 87 | 
            -
            - lib/open_meteo/ | 
| 88 | 
            -
            - lib/open_meteo/location.rb
         | 
| 89 | 
            -
            - lib/open_meteo/location_contract.rb
         | 
| 96 | 
            +
            - lib/open_meteo/forecast/variables.rb
         | 
| 97 | 
            +
            - lib/open_meteo/response_wrapper.rb
         | 
| 90 98 | 
             
            - lib/open_meteo/types.rb
         | 
| 91 99 | 
             
            - lib/open_meteo/version.rb
         | 
| 92 100 | 
             
            homepage: https://github.com/open-meteo-ruby/open-meteo-ruby
         | 
| @@ -109,7 +117,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 109 117 | 
             
                - !ruby/object:Gem::Version
         | 
| 110 118 | 
             
                  version: '0'
         | 
| 111 119 | 
             
            requirements: []
         | 
| 112 | 
            -
            rubygems_version: 3. | 
| 120 | 
            +
            rubygems_version: 3.4.21
         | 
| 113 121 | 
             
            signing_key:
         | 
| 114 122 | 
             
            specification_version: 4
         | 
| 115 123 | 
             
            summary: A client for OpenMeteo weather data
         | 
| @@ -1,26 +0,0 @@ | |
| 1 | 
            -
            module OpenMeteo
         | 
| 2 | 
            -
              ##
         | 
| 3 | 
            -
              # Shared functionality for dry contracts.
         | 
| 4 | 
            -
              class ApplicationContract < Dry::Validation::Contract
         | 
| 5 | 
            -
                ##
         | 
| 6 | 
            -
                # A validation error that can be raised on contract validation.
         | 
| 7 | 
            -
                class ValidationError < StandardError
         | 
| 8 | 
            -
                  attr_reader :result, :errors
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                  def initialize(result)
         | 
| 11 | 
            -
                    @errors = result.errors
         | 
| 12 | 
            -
                    first_error_key = result.errors.first.path.first
         | 
| 13 | 
            -
                    first_error_value = result[first_error_key]
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                    super(
         | 
| 16 | 
            -
                      "Validation failed: :#{first_error_key} is #{first_error_value} but #{errors.first.text}",
         | 
| 17 | 
            -
                    )
         | 
| 18 | 
            -
                  end
         | 
| 19 | 
            -
                end
         | 
| 20 | 
            -
             | 
| 21 | 
            -
                def self.validate!(object)
         | 
| 22 | 
            -
                  result = new.call(object)
         | 
| 23 | 
            -
                  raise ValidationError, result unless result.errors.empty?
         | 
| 24 | 
            -
                end
         | 
| 25 | 
            -
              end
         | 
| 26 | 
            -
            end
         | 
| @@ -1,40 +0,0 @@ | |
| 1 | 
            -
            require_relative "general_contract"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module OpenMeteo
         | 
| 4 | 
            -
              class Forecast
         | 
| 5 | 
            -
                module Variables
         | 
| 6 | 
            -
                  ##
         | 
| 7 | 
            -
                  # The Variables for a general request (meaning without a specific model) to the OpenMeteo API.
         | 
| 8 | 
            -
                  #
         | 
| 9 | 
            -
                  # See https://open-meteo.com/en/docs
         | 
| 10 | 
            -
                  class General < Dry::Struct
         | 
| 11 | 
            -
                    attribute(
         | 
| 12 | 
            -
                      :current,
         | 
| 13 | 
            -
                      OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
         | 
| 14 | 
            -
                    )
         | 
| 15 | 
            -
                    attribute(
         | 
| 16 | 
            -
                      :hourly,
         | 
| 17 | 
            -
                      OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
         | 
| 18 | 
            -
                    )
         | 
| 19 | 
            -
                    attribute(
         | 
| 20 | 
            -
                      :daily,
         | 
| 21 | 
            -
                      OpenMeteo::Types::Strict::Array.of(OpenMeteo::Types::Strict::Symbol).default([].freeze),
         | 
| 22 | 
            -
                    )
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                    def validate!
         | 
| 25 | 
            -
                      GeneralContract.validate!(to_hash)
         | 
| 26 | 
            -
                    end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                    def to_get_params
         | 
| 29 | 
            -
                      get_params = {}
         | 
| 30 | 
            -
             | 
| 31 | 
            -
                      get_params[:current] = current.join(",") if current != []
         | 
| 32 | 
            -
                      get_params[:hourly] = hourly.join(",") if hourly != []
         | 
| 33 | 
            -
                      get_params[:daily] = daily.join(",") if daily != []
         | 
| 34 | 
            -
             | 
| 35 | 
            -
                      get_params
         | 
| 36 | 
            -
                    end
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
                end
         | 
| 39 | 
            -
              end
         | 
| 40 | 
            -
            end
         | 
| @@ -1,286 +0,0 @@ | |
| 1 | 
            -
            module OpenMeteo
         | 
| 2 | 
            -
              class Forecast
         | 
| 3 | 
            -
                module Variables
         | 
| 4 | 
            -
                  ##
         | 
| 5 | 
            -
                  # Validation contract for OpenMeteo::Forecast::Variables::General.
         | 
| 6 | 
            -
                  #
         | 
| 7 | 
            -
                  # See https://open-meteo.com/en/docs
         | 
| 8 | 
            -
                  class GeneralContract < OpenMeteo::ApplicationContract # rubocop:disable Metrics/ClassLength
         | 
| 9 | 
            -
                    params do
         | 
| 10 | 
            -
                      required(:current).array(:symbol)
         | 
| 11 | 
            -
                      required(:hourly).array(:symbol)
         | 
| 12 | 
            -
                      required(:daily).array(:symbol)
         | 
| 13 | 
            -
                    end
         | 
| 14 | 
            -
             | 
| 15 | 
            -
                    CURRENT_VARIABALES = %i[
         | 
| 16 | 
            -
                      apparent_temperature
         | 
| 17 | 
            -
                      cloudcover
         | 
| 18 | 
            -
                      is_day
         | 
| 19 | 
            -
                      precipitation
         | 
| 20 | 
            -
                      pressure_msl
         | 
| 21 | 
            -
                      rain
         | 
| 22 | 
            -
                      relativehumidity_2m
         | 
| 23 | 
            -
                      showers
         | 
| 24 | 
            -
                      snowfall
         | 
| 25 | 
            -
                      surface_pressure
         | 
| 26 | 
            -
                      temperature_2m
         | 
| 27 | 
            -
                      weathercode
         | 
| 28 | 
            -
                      winddirection_10m
         | 
| 29 | 
            -
                      windgusts_10m
         | 
| 30 | 
            -
                      windspeed_10m
         | 
| 31 | 
            -
                    ].freeze
         | 
| 32 | 
            -
             | 
| 33 | 
            -
                    HOURLY_VARIABLES_BASE = %i[
         | 
| 34 | 
            -
                      apparent_temperature
         | 
| 35 | 
            -
                      cloudcover
         | 
| 36 | 
            -
                      cloudcover_high
         | 
| 37 | 
            -
                      cloudcover_low
         | 
| 38 | 
            -
                      cloudcover_mid
         | 
| 39 | 
            -
                      dewpoint_2m
         | 
| 40 | 
            -
                      et0_fao_evapotranspiration
         | 
| 41 | 
            -
                      evapotranspiration
         | 
| 42 | 
            -
                      precipitation
         | 
| 43 | 
            -
                      precipitation_probability
         | 
| 44 | 
            -
                      pressure_msl
         | 
| 45 | 
            -
                      rain
         | 
| 46 | 
            -
                      relativehumidity_2m
         | 
| 47 | 
            -
                      showers
         | 
| 48 | 
            -
                      snow_depth
         | 
| 49 | 
            -
                      snowfall
         | 
| 50 | 
            -
                      soil_moisture_0_to_1cm
         | 
| 51 | 
            -
                      soil_moisture_1_to_3cm
         | 
| 52 | 
            -
                      soil_moisture_27_to_81cm
         | 
| 53 | 
            -
                      soil_moisture_3_to_9cm
         | 
| 54 | 
            -
                      soil_moisture_9_to_27cm
         | 
| 55 | 
            -
                      soil_temperature_0cm
         | 
| 56 | 
            -
                      soil_temperature_18cm
         | 
| 57 | 
            -
                      soil_temperature_54cm
         | 
| 58 | 
            -
                      soil_temperature_6cm
         | 
| 59 | 
            -
                      surface_pressure
         | 
| 60 | 
            -
                      temperature_120m
         | 
| 61 | 
            -
                      temperature_180m
         | 
| 62 | 
            -
                      temperature_2m
         | 
| 63 | 
            -
                      temperature_80m
         | 
| 64 | 
            -
                      vapor_pressure_deficit
         | 
| 65 | 
            -
                      visibility
         | 
| 66 | 
            -
                      weathercode
         | 
| 67 | 
            -
                      winddirection_10m
         | 
| 68 | 
            -
                      winddirection_120m
         | 
| 69 | 
            -
                      winddirection_180m
         | 
| 70 | 
            -
                      winddirection_80m
         | 
| 71 | 
            -
                      windgusts_10m
         | 
| 72 | 
            -
                      windspeed_10m
         | 
| 73 | 
            -
                      windspeed_120m
         | 
| 74 | 
            -
                      windspeed_180m
         | 
| 75 | 
            -
                      windspeed_80m
         | 
| 76 | 
            -
                    ].freeze
         | 
| 77 | 
            -
             | 
| 78 | 
            -
                    HOURLY_VARIABLES_ADDITIONAL = %i[
         | 
| 79 | 
            -
                      uv_index
         | 
| 80 | 
            -
                      uv_index_clear_sky
         | 
| 81 | 
            -
                      is_day
         | 
| 82 | 
            -
                      cape
         | 
| 83 | 
            -
                      freezinglevel_height
         | 
| 84 | 
            -
                    ].freeze
         | 
| 85 | 
            -
             | 
| 86 | 
            -
                    HOURLY_VARIABLES_SOLAR_RADIATION = %i[
         | 
| 87 | 
            -
                      shortwave_radiation
         | 
| 88 | 
            -
                      direct_radiation
         | 
| 89 | 
            -
                      diffuse_radiation
         | 
| 90 | 
            -
                      direct_normal_irradiance
         | 
| 91 | 
            -
                      terrestrial_radiation
         | 
| 92 | 
            -
                      shortwave_radiation_instant
         | 
| 93 | 
            -
                      direct_radiation_instant
         | 
| 94 | 
            -
                      diffuse_radiation_instant
         | 
| 95 | 
            -
                      direct_normal_irradiance_instant
         | 
| 96 | 
            -
                      terrestrial_radiation_instant
         | 
| 97 | 
            -
                    ].freeze
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                    HOURLY_VARIABLES_PRESSURE_LEVEL_TEMPERATURE = %i[
         | 
| 100 | 
            -
                      temperature_1000hPa
         | 
| 101 | 
            -
                      temperature_975hPa
         | 
| 102 | 
            -
                      temperature_950hPa
         | 
| 103 | 
            -
                      temperature_925hPa
         | 
| 104 | 
            -
                      temperature_900hPa
         | 
| 105 | 
            -
                      temperature_850hPa
         | 
| 106 | 
            -
                      temperature_800hPa
         | 
| 107 | 
            -
                      temperature_700hPa
         | 
| 108 | 
            -
                      temperature_600hPa
         | 
| 109 | 
            -
                      temperature_500hPa
         | 
| 110 | 
            -
                      temperature_400hPa
         | 
| 111 | 
            -
                      temperature_300hPa
         | 
| 112 | 
            -
                      temperature_250hPa
         | 
| 113 | 
            -
                      temperature_200hPa
         | 
| 114 | 
            -
                      temperature_150hPa
         | 
| 115 | 
            -
                      temperature_100hPa
         | 
| 116 | 
            -
                      temperature_70hPa
         | 
| 117 | 
            -
                      temperature_50hPa
         | 
| 118 | 
            -
                      temperature_30hPa
         | 
| 119 | 
            -
                    ].freeze
         | 
| 120 | 
            -
             | 
| 121 | 
            -
                    HOURLY_VARIABLES_PRESSURE_LEVEL_RELATIVE_HUMIDITY = %i[
         | 
| 122 | 
            -
                      relativehumidity_1000hPa
         | 
| 123 | 
            -
                      relativehumidity_975hPa
         | 
| 124 | 
            -
                      relativehumidity_950hPa
         | 
| 125 | 
            -
                      relativehumidity_925hPa
         | 
| 126 | 
            -
                      relativehumidity_900hPa
         | 
| 127 | 
            -
                      relativehumidity_850hPa
         | 
| 128 | 
            -
                      relativehumidity_800hPa
         | 
| 129 | 
            -
                      relativehumidity_700hPa
         | 
| 130 | 
            -
                      relativehumidity_600hPa
         | 
| 131 | 
            -
                      relativehumidity_500hPa
         | 
| 132 | 
            -
                      relativehumidity_400hPa
         | 
| 133 | 
            -
                      relativehumidity_300hPa
         | 
| 134 | 
            -
                      relativehumidity_250hPa
         | 
| 135 | 
            -
                      relativehumidity_200hPa
         | 
| 136 | 
            -
                      relativehumidity_150hPa
         | 
| 137 | 
            -
                      relativehumidity_100hPa
         | 
| 138 | 
            -
                      relativehumidity_70hPa
         | 
| 139 | 
            -
                      relativehumidity_50hPa
         | 
| 140 | 
            -
                      relativehumidity_30hPa
         | 
| 141 | 
            -
                    ].freeze
         | 
| 142 | 
            -
             | 
| 143 | 
            -
                    HOURLY_VARIABLES_PRESSURE_LEVEL_CLOUDCOVER = %i[
         | 
| 144 | 
            -
                      cloudcover_1000hPa
         | 
| 145 | 
            -
                      cloudcover_975hPa
         | 
| 146 | 
            -
                      cloudcover_950hPa
         | 
| 147 | 
            -
                      cloudcover_925hPa
         | 
| 148 | 
            -
                      cloudcover_900hPa
         | 
| 149 | 
            -
                      cloudcover_850hPa
         | 
| 150 | 
            -
                      cloudcover_800hPa
         | 
| 151 | 
            -
                      cloudcover_700hPa
         | 
| 152 | 
            -
                      cloudcover_600hPa
         | 
| 153 | 
            -
                      cloudcover_500hPa
         | 
| 154 | 
            -
                      cloudcover_400hPa
         | 
| 155 | 
            -
                      cloudcover_300hPa
         | 
| 156 | 
            -
                      cloudcover_250hPa
         | 
| 157 | 
            -
                      cloudcover_200hPa
         | 
| 158 | 
            -
                      cloudcover_150hPa
         | 
| 159 | 
            -
                      cloudcover_100hPa
         | 
| 160 | 
            -
                      cloudcover_70hPa
         | 
| 161 | 
            -
                      cloudcover_50hPa
         | 
| 162 | 
            -
                      cloudcover_30hPa
         | 
| 163 | 
            -
                    ].freeze
         | 
| 164 | 
            -
             | 
| 165 | 
            -
                    HOURLY_VARIABLES_PRESSURE_LEVEL_WIND_SPEED = %i[
         | 
| 166 | 
            -
                      windspeed_1000hPa
         | 
| 167 | 
            -
                      windspeed_975hPa
         | 
| 168 | 
            -
                      windspeed_950hPa
         | 
| 169 | 
            -
                      windspeed_925hPa
         | 
| 170 | 
            -
                      windspeed_900hPa
         | 
| 171 | 
            -
                      windspeed_850hPa
         | 
| 172 | 
            -
                      windspeed_800hPa
         | 
| 173 | 
            -
                      windspeed_700hPa
         | 
| 174 | 
            -
                      windspeed_600hPa
         | 
| 175 | 
            -
                      windspeed_500hPa
         | 
| 176 | 
            -
                      windspeed_400hPa
         | 
| 177 | 
            -
                      windspeed_300hPa
         | 
| 178 | 
            -
                      windspeed_250hPa
         | 
| 179 | 
            -
                      windspeed_200hPa
         | 
| 180 | 
            -
                      windspeed_150hPa
         | 
| 181 | 
            -
                      windspeed_100hPa
         | 
| 182 | 
            -
                      windspeed_70hPa
         | 
| 183 | 
            -
                      windspeed_50hPa
         | 
| 184 | 
            -
                      windspeed_30hPa
         | 
| 185 | 
            -
                    ].freeze
         | 
| 186 | 
            -
             | 
| 187 | 
            -
                    HOURLY_VARIABLES_PRESSURE_LEVEL_WIND_DIRECTION = %i[
         | 
| 188 | 
            -
                      winddirection_1000hPa
         | 
| 189 | 
            -
                      winddirection_975hPa
         | 
| 190 | 
            -
                      winddirection_950hPa
         | 
| 191 | 
            -
                      winddirection_925hPa
         | 
| 192 | 
            -
                      winddirection_900hPa
         | 
| 193 | 
            -
                      winddirection_850hPa
         | 
| 194 | 
            -
                      winddirection_800hPa
         | 
| 195 | 
            -
                      winddirection_700hPa
         | 
| 196 | 
            -
                      winddirection_600hPa
         | 
| 197 | 
            -
                      winddirection_500hPa
         | 
| 198 | 
            -
                      winddirection_400hPa
         | 
| 199 | 
            -
                      winddirection_300hPa
         | 
| 200 | 
            -
                      winddirection_250hPa
         | 
| 201 | 
            -
                      winddirection_200hPa
         | 
| 202 | 
            -
                      winddirection_150hPa
         | 
| 203 | 
            -
                      winddirection_100hPa
         | 
| 204 | 
            -
                      winddirection_70hPa
         | 
| 205 | 
            -
                      winddirection_50hPa
         | 
| 206 | 
            -
                      winddirection_30hPa
         | 
| 207 | 
            -
                    ].freeze
         | 
| 208 | 
            -
             | 
| 209 | 
            -
                    HOURLY_VARIABLES_PRESSURE_LEVEL_GEOPOTENTIAL_HEIGHT = %i[
         | 
| 210 | 
            -
                      geopotential_height_1000hPa
         | 
| 211 | 
            -
                      geopotential_height_975hPa
         | 
| 212 | 
            -
                      geopotential_height_950hPa
         | 
| 213 | 
            -
                      geopotential_height_925hPa
         | 
| 214 | 
            -
                      geopotential_height_900hPa
         | 
| 215 | 
            -
                      geopotential_height_850hPa
         | 
| 216 | 
            -
                      geopotential_height_800hPa
         | 
| 217 | 
            -
                      geopotential_height_700hPa
         | 
| 218 | 
            -
                      geopotential_height_600hPa
         | 
| 219 | 
            -
                      geopotential_height_500hPa
         | 
| 220 | 
            -
                      geopotential_height_400hPa
         | 
| 221 | 
            -
                      geopotential_height_300hPa
         | 
| 222 | 
            -
                      geopotential_height_250hPa
         | 
| 223 | 
            -
                      geopotential_height_200hPa
         | 
| 224 | 
            -
                      geopotential_height_150hPa
         | 
| 225 | 
            -
                      geopotential_height_100hPa
         | 
| 226 | 
            -
                      geopotential_height_70hPa
         | 
| 227 | 
            -
                      geopotential_height_50hPa
         | 
| 228 | 
            -
                      geopotential_height_30hPa
         | 
| 229 | 
            -
                    ].freeze
         | 
| 230 | 
            -
             | 
| 231 | 
            -
                    HOURLY_VARIABLES = [
         | 
| 232 | 
            -
                      *HOURLY_VARIABLES_BASE,
         | 
| 233 | 
            -
                      *HOURLY_VARIABLES_ADDITIONAL,
         | 
| 234 | 
            -
                      *HOURLY_VARIABLES_SOLAR_RADIATION,
         | 
| 235 | 
            -
                      *HOURLY_VARIABLES_PRESSURE_LEVEL_TEMPERATURE,
         | 
| 236 | 
            -
                      *HOURLY_VARIABLES_PRESSURE_LEVEL_RELATIVE_HUMIDITY,
         | 
| 237 | 
            -
                      *HOURLY_VARIABLES_PRESSURE_LEVEL_CLOUDCOVER,
         | 
| 238 | 
            -
                      *HOURLY_VARIABLES_PRESSURE_LEVEL_WIND_SPEED,
         | 
| 239 | 
            -
                      *HOURLY_VARIABLES_PRESSURE_LEVEL_WIND_DIRECTION,
         | 
| 240 | 
            -
                      *HOURLY_VARIABLES_PRESSURE_LEVEL_GEOPOTENTIAL_HEIGHT,
         | 
| 241 | 
            -
                    ].freeze
         | 
| 242 | 
            -
             | 
| 243 | 
            -
                    DAILY_VARIABLES = %i[
         | 
| 244 | 
            -
                      apparent_temperature_max
         | 
| 245 | 
            -
                      apparent_temperature_min
         | 
| 246 | 
            -
                      et0_fao_evapotranspiration
         | 
| 247 | 
            -
                      precipitation_hours
         | 
| 248 | 
            -
                      precipitation_probability_max
         | 
| 249 | 
            -
                      precipitation_sum
         | 
| 250 | 
            -
                      rain_sum
         | 
| 251 | 
            -
                      shortwave_radiation_sum
         | 
| 252 | 
            -
                      showers_sum
         | 
| 253 | 
            -
                      snowfall_sum
         | 
| 254 | 
            -
                      sunrise
         | 
| 255 | 
            -
                      sunset
         | 
| 256 | 
            -
                      temperature_2m_max
         | 
| 257 | 
            -
                      temperature_2m_min
         | 
| 258 | 
            -
                      uv_index_clear_sky_max
         | 
| 259 | 
            -
                      uv_index_max
         | 
| 260 | 
            -
                      weathercode
         | 
| 261 | 
            -
                      winddirection_10m_dominant
         | 
| 262 | 
            -
                      windgusts_10m_max
         | 
| 263 | 
            -
                      windspeed_10m_max
         | 
| 264 | 
            -
                    ].freeze
         | 
| 265 | 
            -
             | 
| 266 | 
            -
                    rule(:current).each do
         | 
| 267 | 
            -
                      unless CURRENT_VARIABALES.include?(value)
         | 
| 268 | 
            -
                        key.failure("must be one of #{CURRENT_VARIABALES.join(", ")}")
         | 
| 269 | 
            -
                      end
         | 
| 270 | 
            -
                    end
         | 
| 271 | 
            -
             | 
| 272 | 
            -
                    rule(:hourly).each do
         | 
| 273 | 
            -
                      unless HOURLY_VARIABLES.include?(value)
         | 
| 274 | 
            -
                        key.failure("must be one of #{HOURLY_VARIABLES.join(", ")}")
         | 
| 275 | 
            -
                      end
         | 
| 276 | 
            -
                    end
         | 
| 277 | 
            -
             | 
| 278 | 
            -
                    rule(:daily).each do
         | 
| 279 | 
            -
                      unless DAILY_VARIABLES.include?(value)
         | 
| 280 | 
            -
                        key.failure("must be one of #{DAILY_VARIABLES.join(", ")}")
         | 
| 281 | 
            -
                      end
         | 
| 282 | 
            -
                    end
         | 
| 283 | 
            -
                  end
         | 
| 284 | 
            -
                end
         | 
| 285 | 
            -
              end
         | 
| 286 | 
            -
            end
         | 
    
        data/lib/open_meteo/location.rb
    DELETED
    
    | @@ -1,18 +0,0 @@ | |
| 1 | 
            -
            require_relative "location_contract"
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            module OpenMeteo
         | 
| 4 | 
            -
              ##
         | 
| 5 | 
            -
              # A location for a request to OpenMeteo.
         | 
| 6 | 
            -
              class Location < Dry::Struct
         | 
| 7 | 
            -
                attribute :latitude, OpenMeteo::Types::Strict::Float
         | 
| 8 | 
            -
                attribute :longitude, OpenMeteo::Types::Strict::Float
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                def validate!
         | 
| 11 | 
            -
                  LocationContract.validate!(to_hash)
         | 
| 12 | 
            -
                end
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                def to_get_params
         | 
| 15 | 
            -
                  { latitude:, longitude: }
         | 
| 16 | 
            -
                end
         | 
| 17 | 
            -
              end
         | 
| 18 | 
            -
            end
         | 
| @@ -1,14 +0,0 @@ | |
| 1 | 
            -
            module OpenMeteo
         | 
| 2 | 
            -
              ##
         | 
| 3 | 
            -
              # Validation contract for OpenMeteo::Location.
         | 
| 4 | 
            -
              class LocationContract < OpenMeteo::ApplicationContract
         | 
| 5 | 
            -
                params do
         | 
| 6 | 
            -
                  required(:latitude).filled(:float)
         | 
| 7 | 
            -
                  required(:longitude).filled(:float)
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                rule(:latitude) { key.failure("must be within [-90;90]") if value < -90 || value > 90 }
         | 
| 11 | 
            -
             | 
| 12 | 
            -
                rule(:longitude) { key.failure("must be within [-180;180]") if value < -180 || value > 180 }
         | 
| 13 | 
            -
              end
         | 
| 14 | 
            -
            end
         |