jwaterfaucett/bugherd_client

View on GitHub
lib/bugherd_client/client.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'logger'
require 'monitor'

module BugherdClient
  class Client

    API_VERSIONS = [1,2].freeze

    RESOURCE_NAMES = [
      :organization,
      :user,
      :project,
      :task,
      :comment,
      :webhook,
      :attachment
    ]

    DEFAULT_OPTIONS = {
      base_url: 'https://www.bugherd.com',
      api_version: 2,
      username: nil,
      password: nil,
      api_key: nil,
      api_rate_limiting_token: 'x',
      debug: false
    }.freeze

    attr_accessor :options, :connection

    DEFAULT_OPTIONS.each do |option_name, v|
      define_method("#{option_name}") { @options[option_name] }
      define_method("#{option_name}=") { |value| @options[option_name] = value }
    end

    def initialize(opts={}, &block)
      mutex = Monitor.new
      mutex.synchronize do
        @options = DEFAULT_OPTIONS.merge(opts)
        yield(self) if block_given?
        establish_connection!
      end
    end

    def establish_connection!
      check_options!
      username, password = build_credentials

      if @options[:debug]
        RestClient.log        = ::Logger.new($stderr)
        RestClient.log.level  = ::Logger::DEBUG
      end

      resource_klass = Class.new(RestClient::Resource)
      self.connection = resource_klass.new(base_url, user: username, password: password)
    end

    def base_url
      File.join(options[:base_url], "api_v#{options[:api_version]}")
    end

    def check_options!
      if !@options[:api_key] && !(@options[:username] && @options[:password])
        raise BugherdClient::Errors::InvalidOption, 'api_key or username and password is required'
      end
      unless API_VERSIONS.include?(@options[:api_version])
        raise(BugherdClient::Errors::InvalidOption.new("api_version must be #{API_VERSIONS.join(',')}"))
      end
    end

    def build_credentials
      if @options[:api_key].present?
        [@options[:api_key], @options[:api_rate_limiting_token]]
      else
        [@options[:username], @options[:password]]
      end
    end

    def resource(name)
      version = self.options[:api_version]
      version_base = "BugherdClient::Resources::V#{version}".constantize
      klass_name   = name.to_s.classify.to_sym
      unless version_base.constants.include?(klass_name)
        raise(BugherdClient::Errors::NotAvailable.new(version, klass_name))
      end
      klass = version_base.const_get(klass_name)
      klass.new(self.connection, @options)
    end

    #
    # generate RESTful resource factory methods
    #
    RESOURCE_NAMES.each do |resource_name|
      define_method("#{resource_name.to_s.pluralize}") do
        resource(resource_name.to_s)
      end
    end

  end
end