Skip to content

Commit

Permalink
Reduced configuration duplication.
Browse files Browse the repository at this point in the history
  • Loading branch information
AlphaHydrae committed May 11, 2016
1 parent 4973858 commit 0416cf4
Show file tree
Hide file tree
Showing 18 changed files with 413 additions and 108 deletions.
46 changes: 0 additions & 46 deletions lib/probe_dock_ruby/project.rb

This file was deleted.

36 changes: 0 additions & 36 deletions lib/probe_dock_ruby/scm.rb

This file was deleted.

2 changes: 1 addition & 1 deletion lib/probedock-ruby.rb
Original file line number Diff line number Diff line change
@@ -1 +1 @@
require 'probe_dock_ruby'
require 'probedock_ruby'
2 changes: 1 addition & 1 deletion lib/probe_dock_ruby.rb → lib/probedock_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@ class Error < StandardError; end
class PayloadError < Error; end
end

Dir[File.join File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb'].each{ |lib| require lib }
Dir[File.join(File.dirname(__FILE__), File.basename(__FILE__, '.*'), '*.rb')].each{ |lib| require lib }
File renamed without changes.
File renamed without changes.
19 changes: 14 additions & 5 deletions lib/probe_dock_ruby/config.rb → lib/probedock_ruby/config.rb
Original file line number Diff line number Diff line change
@@ -1,14 +1,24 @@
require 'yaml'
require File.join(File.dirname(__FILE__), 'configurable.rb')

module ProbeDockProbe
class Config
include Configurable

class Error < ProbeDockProbe::Error; end

configurable({
publish: :boolean,
local_mode: :boolean,
print_payload: :boolean,
save_payload: :boolean
})

# TODO: add silent/verbose option(s)
attr_writer :publish, :local_mode, :print_payload, :save_payload
attr_reader :project, :server, :scm, :workspace, :load_warnings

def initialize
def initialize options = {}
super options
initialize_servers
@project = Project.new
@scm = Scm.new
Expand Down Expand Up @@ -64,14 +74,14 @@ def load! &block

def apply_configuration! config

@publish = config.fetch(:publish, true)
@server_name = config[:server]
@publish = !!config.fetch(:publish, true)
@local_mode = !!config[:local]

self.workspace = config[:workspace]
@print_payload = !!config[:payload][:print]
@save_payload = !!config[:payload][:save]

@server_name = config[:server]
build_servers! config

project_options = config[:project]
Expand All @@ -83,7 +93,6 @@ def apply_configuration! config

@scm.update(config[:scm])

# TODO: test config block
yield self if block_given?
end

Expand Down
132 changes: 132 additions & 0 deletions lib/probedock_ruby/configurable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
module ProbeDockProbe
module Configurable
def self.included mod
mod.extend ClassMethods
end

def initialize attrs = {}
set_configurable_attrs(nil_attrs.merge(attrs.kind_of?(Hash) ? attrs : {}))
end

def empty?
self.class.configurable_attrs.all? do |attr|
value = send(attr)
value.nil? || value.respond_to?(:empty?) && value.empty?
end
end

def update attrs = {}
set_configurable_attrs(attrs)
end

def clear
self.class.configurable_attrs.each do |attr|
value = send(attr)
if value.kind_of?(Configurable)
value.clear
else
send("#{attr}=", nil)
end
end
end

def to_h
self.class.configurable_attrs.inject({}) do |memo,attr|

value = send(attr)
if value.kind_of?(Configurable)
memo[attr] = value.to_h
elsif !attr_empty?(attr)
memo[attr] = value
end

memo
end
end

private

def attr_empty?(attr)
value = send(attr)
value.nil? || value.respond_to?(:empty?) && value.empty?
end

def nil_attrs
self.class.configurable_attrs.inject({}) do |memo,attr|
memo[attr] = nil
memo
end
end

def set_boolean attr, value
instance_variable_set("@#{attr}", value.nil? ? nil : !!value)
end

def set_integer attr, value
instance_variable_set("@#{attr}", value.nil? ? nil : value.to_s.to_i)
end

def set_string attr, value
instance_variable_set("@#{attr}", value.nil? ? nil : value.to_s)
end

def set_string_array attr, value
instance_variable_set("@#{attr}", wrap(value).compact.collect(&:to_s))
end

def set_configurable klass, attr, value
variable = "@#{attr}"
if configurable = instance_variable_get(variable)
configurable.update value
else
instance_variable_set("@#{attr}", klass.new(value))
end
end

def set_configurable_attrs attrs = {}
return self unless attrs.kind_of?(Hash)

self.class.configurable_attrs.each do |attr|
send("#{attr}=", attrs[attr]) if attrs.key?(attr)
end

self
end

def wrap a
a.kind_of?(Array) ? a : [ a ]
end

module ClassMethods
def configurable attr_definitions = {}

@configurable_attrs = attr_definitions.keys

attr_definitions.each do |attr,type|

setter = if type.kind_of?(Class) && type.included_modules.include?(Configurable)
:configurable
elsif type.kind_of?(Symbol)
type
else
raise "Unsupported type of configurable attribute #{type.inspect}; must be either a symbol or a configurable class"
end

attr_reader attr

define_method "#{attr}=" do |value|
if setter == :configurable
send :set_configurable, type, attr, value
else
send "set_#{type}", attr, value
end
end
end
end

def configurable_attrs *attrs
@configurable_attrs || []
end
end
end
end
21 changes: 21 additions & 0 deletions lib/probedock_ruby/project.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
require File.join(File.dirname(__FILE__), 'configurable.rb')

module ProbeDockProbe
class Project
include Configurable

configurable({
api_id: :string,
version: :string,
category: :string,
tags: :string_array,
tickets: :string_array
})

def validate!
required = { "version" => @version, "API identifier" => @api_id }
missing = required.inject([]){ |memo,(k,v)| v.to_s.strip.length <= 0 ? memo << k : memo }
raise PayloadError.new("Missing project options: #{missing.join ', '}") if missing.any?
end
end
end
35 changes: 35 additions & 0 deletions lib/probedock_ruby/scm.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
require 'ostruct'
require File.join(File.dirname(__FILE__), 'configurable.rb')

module ProbeDockProbe
class ScmRemoteUrl
include Configurable

configurable({
fetch: :string,
push: :string
})
end

class ScmRemote
include Configurable

configurable({
name: :string,
ahead: :integer,
behind: :integer,
url: ScmRemoteUrl
})
end

class Scm
include Configurable

configurable({
name: :string,
version: :string,
dirty: :boolean,
remote: ScmRemote
})
end
end
27 changes: 11 additions & 16 deletions lib/probe_dock_ruby/server.rb → lib/probedock_ruby/server.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
require 'oj'
require 'httparty'
require File.join(File.dirname(__FILE__), 'configurable.rb')

module ProbeDockProbe
class Server
attr_reader :name
attr_accessor :api_url, :api_token, :project_api_id
include Configurable

class Error < ProbeDockProbe::Error
attr_reader :response
Expand All @@ -15,22 +15,17 @@ def initialize msg, response = nil
end
end

def initialize options = {}
@name = options[:name].to_s.strip if options[:name]
@api_url = options[:api_url].to_s if options[:api_url]
@api_token = options[:api_token].to_s if options[:api_token]
@project_api_id = options[:project_api_id].to_s if options[:project_api_id]
end
configurable({
api_url: :string,
api_token: :string,
project_api_id: :string
})

def clear
@name = nil
@api_url = nil
@api_token = nil
@project_api_id = nil
end
attr_reader :name

def empty?
%i(api_url api_token project_api_id).all?{ |attr| send(attr).nil? || send(attr).empty? }
def initialize options = {}
super options
@name = options[:name].to_s.strip if options[:name]
end

def upload payload
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions spec/config_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@
config.load!(&config_block)

actual_scm = %i(name version dirty).inject({}){ |memo,attr| memo[attr] = scm.send(attr); memo }.reject{ |k,v| v.nil? }
actual_scm[:remote] = scm.remote.to_h
actual_scm[:remote][:url] = scm.remote[:url].to_h
actual_scm[:remote] = %i(name ahead behind).inject({}){ |memo,attr| memo[attr] = scm.remote.send(attr); memo }.reject{ |k,v| v.nil? }
actual_scm[:remote][:url] = %i(fetch push).inject({}){ |memo,attr| memo[attr] = scm.remote.url.send(attr); memo }.reject{ |k,v| v.nil? }

expect(actual_scm).to eq(expected_scm_configuration)
end
Expand Down
Loading

0 comments on commit 0416cf4

Please sign in to comment.