linqueta/katinguele

View on GitHub
lib/eezee/request.rb

Summary

Maintainability
A
25 mins
Test Coverage
# frozen_string_literal: true

module Eezee
  class Request
    ACCESSORS = %i[
      after
      before
      headers
      logger
      open_timeout
      params
      path
      payload
      protocol
      raise_error
      timeout
      url
      url_encoded
      preserve_url_params
      ddtrace
    ].freeze

    DEFAULT = {
      headers: {},
      logger: false,
      params: {},
      payload: {},
      raise_error: false,
      url_encoded: false,
      preserve_url_params: false,
      ddtrace: {}
    }.freeze

    attr_accessor(*(ACCESSORS | %i[uri method]))

    def initialize(options = {})
      setup!(options)
    end

    def log
      Eezee::Logger.request(self, @method.to_s.upcase)
    end

    def attributes
      ACCESSORS.each_with_object({}) { |accessor, obj| obj[accessor] = send(accessor) }
    end

    def before!(*params)
      hook!(:before, params)
    end

    def after!(*params)
      hook!(:after, params)
    end

    private

    def setup!(options = {})
      accessors!(DEFAULT.merge(options || {}))
      validate!
      build_urn!
      handle_query_params!
      handle_urn_params! unless @preserve_url_params
    end

    def hook!(hook, params)
      return unless send(hook)&.is_a?(Proc)

      send(hook).call(*params[0..(send(hook).parameters.length - 1)])
    end

    def validate!
      return if ENV['EEZEE_DISCARD_REQUEST_VALIDATIONS']

      raise Eezee::RequiredFieldError.new(self.class, :url) unless @url
    end

    def accessors!(params)
      params.slice(*ACCESSORS)
            .each { |k, v| instance_variable_set("@#{k}", v) }
    end

    def build_urn!
      @uri = [@protocol, [@url, @path].compact.join('/')].compact.join('://')
    end

    def handle_urn_params!
      return unless @params.is_a?(Hash)

      @params.filter { |k, _v| @uri.include?(":#{k}") }
             .each   { |k, v|  @uri.gsub!(":#{k}", v.to_s) }
             .then   { @uri.gsub!(/:[a-z_-]+/, '') }
             .then   { @uri.gsub!(%r{/$}, '') }
    end

    def handle_query_params!
      return unless @params.is_a?(Hash)

      @params.reject { |k, _v| @uri.include?(":#{k}") }
             .map    { |k, v|  "#{k}=#{v}" }
             .then   { |array| array.join('&') }
             .then   { |query| query unless query.empty? }
             .then   { |query| @uri = [@uri, query].compact.join('?') }
    end
  end
end