config-factory 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 1c37c92cb2e03fac96a921680f19865fa0caceb0
4
+ data.tar.gz: 1df74e155e1c9b087595ce54d495b7718daf4045
5
+ SHA512:
6
+ metadata.gz: e0616e9f0628f6cfc0fb6fe26b6594cf760225203998eb72225d85b8ef14584778e49960c9ef41b363a2b5c13194f4b0421ca494186d685667c87fa449cce954
7
+ data.tar.gz: 25b40edecf4cd5d8eb4e82de174f69bc230de9d4818fd66c3bf3a442e296d8141abfa2fc507f31621b440e2941e65456bb54bd424306d471cf8623f8cd702778
@@ -0,0 +1,42 @@
1
+ # Ruby defaults
2
+
3
+ /.bundle/
4
+ /.yardoc
5
+ /Gemfile.lock
6
+ /_yardoc/
7
+ /coverage/
8
+ /doc/
9
+ /pkg/
10
+ /spec/reports/
11
+ /tmp/
12
+ *.bundle
13
+ *.so
14
+ *.o
15
+ *.a
16
+ mkmf.log
17
+
18
+ # Gem
19
+
20
+ *.gem
21
+
22
+ # Logs
23
+
24
+ /log/
25
+
26
+ # IntellJ
27
+
28
+ *.iml
29
+ *.ipr
30
+ *.iws
31
+ *.ids
32
+ .rakeTasks
33
+
34
+ # Emacs
35
+
36
+ *~
37
+ \#*
38
+ .#*
39
+
40
+ # Mac OS
41
+
42
+ .DS_Store
@@ -0,0 +1,24 @@
1
+ # Disable compact style check for example.rb
2
+ Style/ClassAndModuleChildren:
3
+ Exclude:
4
+ - 'example.rb'
5
+
6
+ # Disable line-length check; it's too easy for the cure to be worse than the disease
7
+ Metrics/LineLength:
8
+ Enabled: False
9
+
10
+ # Disable problematic module documentation check (see https://github.com/bbatsov/rubocop/issues/947)
11
+ Style/Documentation:
12
+ Enabled: false
13
+
14
+ # Allow one line around class body (Style/EmptyLines will still disallow two or more)
15
+ Style/EmptyLinesAroundClassBody:
16
+ Enabled: false
17
+
18
+ # Allow one line around module body (Style/EmptyLines will still disallow two or more)
19
+ Style/EmptyLinesAroundModuleBody:
20
+ Enabled: false
21
+
22
+ # Allow one line around block body (Style/EmptyLines will still disallow two or more)
23
+ Style/EmptyLinesAroundBlockBody:
24
+ Enabled: false
@@ -0,0 +1 @@
1
+ 2.2.3
@@ -0,0 +1,2 @@
1
+ language: ruby
2
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 The Regents of the University of California
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,85 @@
1
+ # config-factory
2
+
3
+ [![Build Status](https://travis-ci.org/dmolesUC3/config-factory.svg?branch=master)](https://travis-ci.org/dmolesUC3/config-factory)
4
+ [![Code Climate](https://codeclimate.com/github/dmolesUC3/config-factory.svg)](https://codeclimate.com/github/dmolesUC3/config-factory)
5
+ [![Inline docs](http://inch-ci.org/github/dmolesUC3/config-factory.svg)](http://inch-ci.org/github/dmolesUC3/config-factory)
6
+ [![Gem Version](https://img.shields.io/gem/v/config-factory.svg)](https://github.com/dmolesUC3/config-factory/releases)
7
+
8
+ A gem for creating configuration classes using the
9
+ [Abstract Factory](https://web.archive.org/web/20111109224959/http://www.informit.com/articles/article.aspx?p=1398599),
10
+ pattern, with run-time configuration provided by hashes or YAML files.
11
+
12
+ ## Example
13
+
14
+ ```ruby
15
+ class SourceConfig
16
+ include Config::Factory
17
+ key :protocol
18
+ end
19
+
20
+ class OAISourceConfig < SourceConfig
21
+ protocol 'OAI'
22
+
23
+ def initialize(oai_base_url:, metadata_prefix:, set: nil, seconds_granularity: false)
24
+ end
25
+ end
26
+
27
+ class ResyncSourceConfig < SourceConfig
28
+ protocol 'Resync'
29
+
30
+ def initialize(capability_list_url:)
31
+ end
32
+ end
33
+ ```
34
+
35
+ ### Single-environment example
36
+
37
+ Configuration file:
38
+
39
+ ```YAML
40
+ source:
41
+ protocol: OAI
42
+ oai_base_url: http://oai.example.org/oai
43
+ metadata_prefix: some_prefix
44
+ set: some_set
45
+ seconds_granularity: true
46
+ ```
47
+
48
+ Loading:
49
+
50
+ ```ruby
51
+ environment = Environment.load_file('spec/data/single-environment.yml')
52
+ # => #<Config::Factory::Environment:0x007fe8d3883240 @name=:production, @configs={"source"=>{"protocol"=>"OAI", "oai_base_url"=>"http://oai.example.org/oai", "metadata_prefix"=>"some_prefix", "set"=>"some_set", "seconds_granularity"=>true}}>
53
+ source_config = SourceConfig.for_environment(environment, :source)
54
+ # => #<OAISourceConfig:0x007fe8d38b3990 @oai_base_url="http://oai.example.org/oai", @metadata_prefix="some_prefix", @set="some_set", @seconds_granularity=true>
55
+ ```
56
+
57
+ ### Multiple-environment example
58
+
59
+ Configuration file:
60
+
61
+ ```YAML
62
+ test:
63
+ source:
64
+ protocol: Resync
65
+ capability_list_url: http://localhost:8888/capabilitylist.xml
66
+
67
+ production:
68
+ source:
69
+ protocol: OAI
70
+ oai_base_url: http://oai.example.org/oai
71
+ metadata_prefix: some_prefix
72
+ set: some_set
73
+ seconds_granularity: true
74
+ ```
75
+
76
+ Loading:
77
+
78
+ ```ruby
79
+ environments = Environments.load_file('spec/data/multiple_environments.yml')
80
+ # => {:test=>#<Config::Factory::Environment:0x007fe8d3863dc8 @name=:test, @configs={"source"=>{"protocol"=>"Resync", "capability_list_url"=>"http://localhost:8888/capabilitylist.xml"}}>, :production=>#<Config::Factory::Environment:0x007fe8d3863be8 @name=:production, @configs={"source"=>{"protocol"=>"OAI", "oai_base_url"=>"http://oai.example.org/oai", "metadata_prefix"=>"some_prefix", "set"=>"some_set", "seconds_granularity"=>true}}>}
81
+ test_env = environments[:test]
82
+ # => #<Config::Factory::Environment:0x007fe8d383a400 @name=:test, @configs={"source"=>{"protocol"=>"Resync", "capability_list_url"=>"http://localhost:8888/capabilitylist.xml"}}>
83
+ source_config = SourceConfig.for_environment(test_env, :source)
84
+ # => #<ResyncSourceConfig:0x007fe8d48180c0 @capability_list_url="http://localhost:8888/capabilitylist.xml">
85
+ ```
@@ -0,0 +1,49 @@
1
+ # ------------------------------------------------------------
2
+ # RSpec
3
+
4
+ require 'rspec/core'
5
+ require 'rspec/core/rake_task'
6
+
7
+ namespace :spec do
8
+
9
+ desc 'Run all unit tests'
10
+ RSpec::Core::RakeTask.new(:unit) do |task|
11
+ task.rspec_opts = %w(--color --format documentation --order default)
12
+ task.pattern = 'unit/**/*_spec.rb'
13
+ end
14
+
15
+ task all: [:unit]
16
+ end
17
+
18
+ desc 'Run all tests'
19
+ task spec: 'spec:all'
20
+
21
+ # ------------------------------------------------------------
22
+ # Coverage
23
+
24
+ desc 'Run all unit tests with coverage'
25
+ task :coverage do
26
+ ENV['COVERAGE'] = 'true'
27
+ Rake::Task['spec:unit'].execute
28
+ end
29
+
30
+ # ------------------------------------------------------------
31
+ # RuboCop
32
+
33
+ require 'rubocop/rake_task'
34
+ RuboCop::RakeTask.new
35
+
36
+ # ------------------------------------------------------------
37
+ # TODOs
38
+
39
+ desc 'List TODOs (from spec/todo.rb)'
40
+ RSpec::Core::RakeTask.new(:todo) do |task|
41
+ task.rspec_opts = %w(--color --format documentation --order default)
42
+ task.pattern = 'todo.rb'
43
+ end
44
+
45
+ # ------------------------------------------------------------
46
+ # Defaults
47
+
48
+ desc 'Run unit tests, check test coverage, run acceptance tests, check code style'
49
+ task default: [:coverage, :rubocop]
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+
5
+ require 'uri'
6
+ require 'config/factory/module_info'
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = Config::Factory::NAME
10
+ spec.version = Config::Factory::VERSION
11
+ spec.authors = ['David Moles']
12
+ spec.email = ['david.moles@ucop.edu']
13
+ spec.summary = 'A gem for creating configuration classes using the Abstract Factory pattern.'
14
+ spec.description = 'A gem for creating configuration classes using the Abstract Factory pattern, with run-time configuration provided by hashes or YAML files.'
15
+ spec.license = 'MIT'
16
+
17
+ origin_uri = URI(`git config --get remote.origin.url`.chomp)
18
+ spec.homepage = URI::HTTP.build(host: origin_uri.host, path: origin_uri.path.chomp('.git')).to_s
19
+
20
+ spec.files = `git ls-files -z`.split("\x0")
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ['lib']
25
+
26
+ spec.add_development_dependency 'bundler', '~> 1.7'
27
+ spec.add_development_dependency 'rake', '~> 10.4'
28
+ spec.add_development_dependency 'rspec', '~> 3.2'
29
+ spec.add_development_dependency 'simplecov', '~> 0.9.2'
30
+ spec.add_development_dependency 'simplecov-console', '~> 0.2.0'
31
+ spec.add_development_dependency 'rubocop', '~> 0.35.1'
32
+ end
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'config/factory'
4
+ include Config::Factory
5
+
6
+ # Configuration classes
7
+
8
+ class SourceConfig
9
+ include Config::Factory
10
+ key :protocol
11
+ end
12
+
13
+ class OAISourceConfig < SourceConfig
14
+ protocol 'OAI'
15
+
16
+ def initialize(oai_base_url:, metadata_prefix:, set: nil, seconds_granularity: false)
17
+ @oai_base_url = oai_base_url
18
+ @metadata_prefix = metadata_prefix
19
+ @set = set
20
+ @seconds_granularity = seconds_granularity
21
+ end
22
+ end
23
+
24
+ class ResyncSourceConfig < SourceConfig
25
+ protocol 'Resync'
26
+
27
+ def initialize(capability_list_url:)
28
+ @capability_list_url = capability_list_url
29
+ end
30
+ end
31
+
32
+ # Single-environment example
33
+
34
+ env = Environment.load_file('spec/data/single-environment.yml')
35
+ source_config = SourceConfig.for_environment(env, :source)
36
+ puts source_config
37
+ # => #<OAISourceConfig:0x007fe8d38b3990 @oai_base_url="http://oai.example.org/oai", @metadata_prefix="some_prefix", @set="some_set", @seconds_granularity=true>
38
+
39
+ # Multiple-environment example
40
+
41
+ envs = Environments.load_file('spec/data/multiple-environments.yml')
42
+ env = envs[:test]
43
+ source_config = SourceConfig.for_environment(env, :source)
44
+ puts source_config
45
+ # => #<ResyncSourceConfig:0x007fe8d48180c0 @capability_list_url="http://localhost:8888/capabilitylist.xml">
@@ -0,0 +1,5 @@
1
+ module Config
2
+ module Factory
3
+ Dir.glob(File.expand_path('../factory/*.rb', __FILE__)).sort.each(&method(:require))
4
+ end
5
+ end
@@ -0,0 +1,45 @@
1
+ module Config
2
+ module Factory
3
+ def self.included(base)
4
+ base.extend(AbstractFactory)
5
+ end
6
+
7
+ module AbstractFactory
8
+ attr_reader :product_key
9
+
10
+ def key(k)
11
+ @product_key = k
12
+ registry = products
13
+ define_singleton_method(k) do |v|
14
+ registry[v] = self
15
+ end
16
+ end
17
+
18
+ def for_environment(env, key)
19
+ arg_hash = env.args_for(key)
20
+ build_from(arg_hash)
21
+ end
22
+
23
+ def build_from(arg_hash)
24
+ args = deep_symbolize_keys(arg_hash)
25
+ key_value = args.delete(product_key)
26
+ product_class = products[key_value]
27
+ fail ArgumentError, "No #{name} product class found for #{product_key}: #{key_value}" unless product_class
28
+ product_class.new(args)
29
+ end
30
+
31
+ private
32
+
33
+ def deep_symbolize_keys(val)
34
+ return val unless val.is_a?(Hash)
35
+ val.map do |k, v|
36
+ [k.respond_to?(:to_sym) ? k.to_sym : k, deep_symbolize_keys(v)]
37
+ end.to_h
38
+ end
39
+
40
+ def products
41
+ @products ||= {}
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,35 @@
1
+ module Config
2
+ module Factory
3
+ class Environment
4
+
5
+ attr_reader :name
6
+
7
+ def initialize(name:, configs:)
8
+ self.name = name
9
+ @configs = configs
10
+ end
11
+
12
+ def args_for(config_name)
13
+ config_name = config_name.to_s unless config_name.is_a?(String)
14
+ @configs[config_name]
15
+ end
16
+
17
+ def self.load_file(path)
18
+ hash = YAML.load_file(path)
19
+ load_hash(hash)
20
+ end
21
+
22
+ def self.load_hash(hash)
23
+ Environment.new(name: Environments::DEFAULT_ENVIRONMENT, configs: hash)
24
+ end
25
+
26
+ private
27
+
28
+ def name=(v)
29
+ fail ArgumentError, 'Environment name must be a symbol' unless v && v.is_a?(Symbol)
30
+ @name = v
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,25 @@
1
+ require 'yaml'
2
+ require_relative 'environment'
3
+
4
+ module Config
5
+ module Factory
6
+ module Environments
7
+ DEFAULT_ENVIRONMENT = :production
8
+ STANDARD_ENVIRONMENTS = [:defaults, :development, :test, :stage, :staging, :production].freeze
9
+ STANDARD_ENVIRONMENTS_NOT_FOUND = "No standard environment tags (#{STANDARD_ENVIRONMENTS.join(', ')}) found; is this really a multiple-environment configuration?"
10
+
11
+ def self.load_file(path)
12
+ hash = YAML.load_file(path)
13
+ load_hash(hash)
14
+ end
15
+
16
+ def self.load_hash(hash)
17
+ warn STANDARD_ENVIRONMENTS_NOT_FOUND unless STANDARD_ENVIRONMENTS.any? { |k| hash.key?(k.to_s) }
18
+ hash.map do |k, v|
19
+ k2 = k.to_sym
20
+ [k2, Environment.new(name: k2, configs: v)]
21
+ end.to_h
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,35 @@
1
+ require 'logger'
2
+
3
+ module Config
4
+ module Factory
5
+
6
+ class << self
7
+ attr_writer :log
8
+ end
9
+
10
+ # Gets the logger for the module. Default logger logs to `$stdout`.
11
+ # @return [Logger] the logger
12
+ def self.log
13
+ self.log_device = $stdout unless @log
14
+ @log
15
+ end
16
+
17
+ # Sets the log device. Defaults to `$stdout`
18
+ # @param value [IO] the log device
19
+ def self.log_device=(value)
20
+ @log = new_logger(logdev: value)
21
+ end
22
+
23
+ private
24
+
25
+ def self.new_logger(logdev:, level: Logger::DEBUG, shift_age: 10, shift_size: 1024 * 1024)
26
+ logger = Logger.new(logdev, shift_age, shift_size)
27
+ logger.level = level
28
+ logger.formatter = proc do |severity, datetime, progname, msg|
29
+ "#{datetime.to_time.utc} #{severity} -#{progname}- #{msg}\n"
30
+ end
31
+ logger
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,12 @@
1
+ module Config
2
+ module Factory
3
+ # The name of this gem
4
+ NAME = 'config-factory'
5
+
6
+ # The version of this gem
7
+ VERSION = '0.0.1'
8
+
9
+ # The copyright notice for this gem
10
+ COPYRIGHT = 'Copyright (c) 2015 The Regents of the University of California'
11
+ end
12
+ end
@@ -0,0 +1,7 @@
1
+ inherit_from: ../.rubocop.yml
2
+
3
+ Metrics/MethodLength:
4
+ Enabled: false
5
+
6
+ Metrics/ModuleLength:
7
+ Enabled: false
@@ -0,0 +1,52 @@
1
+ defaults: &defaults
2
+ source:
3
+ protocol: OAI
4
+ oai_base_url: http://oai.example.org/oai
5
+ metadata_prefix: some_prefix
6
+ set: some_set
7
+ seconds_granularity: true
8
+ index:
9
+ adapter: solr
10
+ url: http://solr.example.org/
11
+ proxy: http://foo:bar@proxy.example.com/
12
+ open_timeout: 120
13
+ read_timeout: 300
14
+
15
+ development:
16
+ <<: *defaults
17
+ db:
18
+ adapter: mysql2
19
+ encoding: utf8
20
+ pool: 5
21
+ database: example_pord
22
+ host: mysql-dev.example.org
23
+ port: 3306
24
+ index:
25
+ adapter: solr
26
+ url: http://solr-dev.example.org/
27
+ proxy: http://foo:bar@proxy.example.com/
28
+ open_timeout: 120
29
+ read_timeout: 300
30
+
31
+ test:
32
+ db:
33
+ adapter: sqlite3
34
+ database: ':memory:'
35
+ pool: 5
36
+ timeout: 5000
37
+ source:
38
+ protocol: Resync
39
+ capability_list_url: http://localhost:8888/capabilitylist.xml
40
+ index:
41
+ adapter: solr
42
+ url: http://localhost:8000/solr/
43
+
44
+ production:
45
+ <<: *defaults
46
+ db:
47
+ adapter: mysql2
48
+ encoding: utf8
49
+ pool: 5
50
+ database: example_pord
51
+ host: mysql.example.org
52
+ port: 3306
@@ -0,0 +1,19 @@
1
+ db:
2
+ adapter: mysql2
3
+ encoding: utf8
4
+ pool: 5
5
+ database: example_pord
6
+ host: mysql-dev.example.org
7
+ port: 3306
8
+ source:
9
+ protocol: OAI
10
+ oai_base_url: http://oai.example.org/oai
11
+ metadata_prefix: some_prefix
12
+ set: some_set
13
+ seconds_granularity: true
14
+ index:
15
+ adapter: solr
16
+ url: http://solr.example.org/
17
+ proxy: http://foo:bar@proxy.example.com/
18
+ open_timeout: 120
19
+ read_timeout: 300
@@ -0,0 +1,29 @@
1
+ # ------------------------------------------------------------
2
+ # SimpleCov setup
3
+
4
+ if ENV['COVERAGE']
5
+ require 'simplecov'
6
+ require 'simplecov-console'
7
+
8
+ SimpleCov.minimum_coverage 100
9
+ SimpleCov.start do
10
+ add_filter '/spec/'
11
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
12
+ SimpleCov::Formatter::HTMLFormatter,
13
+ SimpleCov::Formatter::Console,
14
+ ]
15
+ end
16
+ end
17
+
18
+ # ------------------------------------------------------------
19
+ # Rspec configuration
20
+
21
+ RSpec.configure do |config|
22
+ config.raise_errors_for_deprecations!
23
+ config.mock_with :rspec
24
+ end
25
+
26
+ # ------------------------------------------------------------
27
+ # Config::Factory
28
+
29
+ require 'config/factory'
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require_relative 'fixtures'
3
+
4
+ module Config
5
+ module Factory
6
+ describe AbstractFactory do
7
+ describe '#build_from' do
8
+ it 'builds the correct class with the correct config' do
9
+ config_hash = { protocol: 'OAI', oai_base_url: 'http://oai.example.org/oai', metadata_prefix: 'some_prefix', set: 'some_set', seconds_granularity: true }
10
+ product = SourceConfig.build_from(config_hash)
11
+ expect(product).to be_an(OAISourceConfig)
12
+ args = { oai_base_url: URI('http://oai.example.org/oai'), metadata_prefix: 'some_prefix', set: 'some_set', seconds_granularity: true }
13
+ args.each do |k, v|
14
+ expect(product.send(k)).to eq(v)
15
+ end
16
+ end
17
+
18
+ it 'raises a sensible exception if no product found for the key' do
19
+ config_hash = { protocol: 'Elvis' }
20
+ expect { SourceConfig.build_from(config_hash) }.to raise_error(ArgumentError, /SourceConfig.*protocol.*Elvis/)
21
+ end
22
+ end
23
+
24
+ describe '#for_environment' do
25
+ it 'builds the correct class with the correct config' do
26
+ config_hash = { protocol: 'OAI', oai_base_url: 'http://oai.example.org/oai', metadata_prefix: 'some_prefix', set: 'some_set', seconds_granularity: true }
27
+ env = instance_double(Environment)
28
+ expect(env).to receive(:args_for).with(:source) { config_hash }
29
+
30
+ product = SourceConfig.for_environment(env, :source)
31
+ expect(product).to be_an(OAISourceConfig)
32
+ args = { oai_base_url: URI('http://oai.example.org/oai'), metadata_prefix: 'some_prefix', set: 'some_set', seconds_granularity: true }
33
+ args.each do |k, v|
34
+ expect(product.send(k)).to eq(v)
35
+ end
36
+ end
37
+
38
+ it 'raises a sensible exception if no product found for the key' do
39
+ config_hash = { protocol: 'Elvis' }
40
+ env = instance_double(Environment)
41
+ expect(env).to receive(:args_for).with(:source) { config_hash }
42
+ expect { SourceConfig.for_environment(env, :source) }.to raise_error(ArgumentError, /SourceConfig.*protocol.*Elvis/)
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+ require_relative 'fixtures'
3
+
4
+ module Config
5
+ module Factory
6
+ describe Environment do
7
+ describe '#new' do
8
+ it 'sets the name' do
9
+ env = Environment.new(name: :name, configs: {})
10
+ expect(env.name).to eq(:name)
11
+ end
12
+ it 'requires a name' do
13
+ expect { Environment.new(name: nil, configs: {}) }.to raise_error(ArgumentError)
14
+ end
15
+ it 'requires a symbol name' do
16
+ expect { Environment.new(name: 'name', configs: {}) }.to raise_error(ArgumentError)
17
+ end
18
+ it 'registers the configurations' do
19
+ yaml_hash = YAML.load_file('spec/data/single-environment.yml')
20
+ env = Environment.new(name: :test, configs: yaml_hash)
21
+ %w(db source index).each do |key|
22
+ expect(env.args_for(key)).to eq(yaml_hash[key])
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#load_file' do
28
+ it 'loads a single-environment config file' do
29
+ env = Environment.load_file('spec/data/single-environment.yml')
30
+ expect(env).to be_an(Environment)
31
+ expect(env.name).to eq(Environments::DEFAULT_ENVIRONMENT)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+
3
+ module Config
4
+ module Factory
5
+ module Environments
6
+ describe '#load_file' do
7
+ it 'loads a multi-environment config file' do
8
+ envs = Environments.load_file('spec/data/multiple-environments.yml')
9
+ expect(envs).to be_a(Hash)
10
+ expect(envs.size).to eq(4)
11
+ [:defaults, :development, :test, :production].each do |env_name|
12
+ env = envs[env_name]
13
+ expect(env).to be_an(Environment)
14
+ expect(env.name).to eq(env_name)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,73 @@
1
+ require 'config/factory'
2
+ require 'uri'
3
+
4
+ class SourceConfig
5
+ include Config::Factory
6
+
7
+ key :protocol
8
+
9
+ attr_reader :source_uri
10
+
11
+ def initialize(source_url:)
12
+ @source_uri = URI(source_url)
13
+ end
14
+ end
15
+
16
+ class OAISourceConfig < SourceConfig
17
+ protocol 'OAI'
18
+
19
+ attr_reader :oai_base_url
20
+ attr_reader :metadata_prefix
21
+ attr_reader :set
22
+ attr_reader :seconds_granularity
23
+
24
+ def initialize(oai_base_url:, metadata_prefix:, set: nil, seconds_granularity: false)
25
+ super(source_url: oai_base_url)
26
+ @oai_base_url = source_uri
27
+ @metadata_prefix = metadata_prefix
28
+ @set = set
29
+ @seconds_granularity = seconds_granularity
30
+ end
31
+ end
32
+
33
+ class ResyncSourceConfig < SourceConfig
34
+ protocol 'Resync'
35
+
36
+ attr_reader :capability_list_url
37
+
38
+ def initialize(capability_list_url:)
39
+ super(url: capability_list_url)
40
+ @capability_list_url = source_uri
41
+ end
42
+ end
43
+
44
+ # IndexConfig
45
+
46
+ class IndexConfig
47
+ include Config::Factory
48
+
49
+ key :adapter
50
+
51
+ attr_reader :uri
52
+
53
+ def initialize(url:)
54
+ @uri = URI(url)
55
+ end
56
+ end
57
+
58
+ class SolrConfig < IndexConfig
59
+ adapter 'Solr'
60
+
61
+ attr_reader :url
62
+ attr_reader :proxy
63
+ attr_reader :open_timeout
64
+ attr_reader :read_timeout
65
+
66
+ def initialize(url:, proxy: nil, open_timeout: 60, read_timeout: 120)
67
+ super(url: url)
68
+ @url = uri
69
+ @proxy = proxy
70
+ @open_timeout = open_timeout
71
+ @read_timeout = read_timeout
72
+ end
73
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ module Config
4
+ module Factory
5
+ describe 'log' do
6
+ it 'logs to stdout in a timestamp-first format' do
7
+ out = StringIO.new
8
+ Factory.log_device = out
9
+ begin
10
+ msg = 'I am a log message'
11
+ Factory.log.warn(msg)
12
+ logged = out.string
13
+ expect(logged).to include(msg)
14
+ timestamp_str = logged.split[0]
15
+ timestamp = DateTime.parse(timestamp_str)
16
+ expect(timestamp.to_date).to eq(Time.now.utc.to_date)
17
+ ensure
18
+ Factory.log_device = $stdout
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: config-factory
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - David Moles
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-01-05 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: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.4'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.4'
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.2'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: simplecov
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.2
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.9.2
69
+ - !ruby/object:Gem::Dependency
70
+ name: simplecov-console
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.2.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.2.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.35.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.35.1
97
+ description: A gem for creating configuration classes using the Abstract Factory pattern,
98
+ with run-time configuration provided by hashes or YAML files.
99
+ email:
100
+ - david.moles@ucop.edu
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".rubocop.yml"
107
+ - ".ruby-version"
108
+ - ".travis.yml"
109
+ - Gemfile
110
+ - LICENSE.md
111
+ - README.md
112
+ - Rakefile
113
+ - config-factory.gemspec
114
+ - example.rb
115
+ - lib/config/factory.rb
116
+ - lib/config/factory/abstract_factory.rb
117
+ - lib/config/factory/environment.rb
118
+ - lib/config/factory/environments.rb
119
+ - lib/config/factory/log.rb
120
+ - lib/config/factory/module_info.rb
121
+ - spec/.rubocop.yml
122
+ - spec/data/multiple-environments.yml
123
+ - spec/data/single-environment.yml
124
+ - spec/spec_helper.rb
125
+ - spec/unit/config/factory/abstract_factory_spec.rb
126
+ - spec/unit/config/factory/environment_spec.rb
127
+ - spec/unit/config/factory/environments_spec.rb
128
+ - spec/unit/config/factory/fixtures.rb
129
+ - spec/unit/config/factory/log_spec.rb
130
+ homepage: http://github.com/dmolesUC3/config-factory
131
+ licenses:
132
+ - MIT
133
+ metadata: {}
134
+ post_install_message:
135
+ rdoc_options: []
136
+ require_paths:
137
+ - lib
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ requirements:
140
+ - - ">="
141
+ - !ruby/object:Gem::Version
142
+ version: '0'
143
+ required_rubygems_version: !ruby/object:Gem::Requirement
144
+ requirements:
145
+ - - ">="
146
+ - !ruby/object:Gem::Version
147
+ version: '0'
148
+ requirements: []
149
+ rubyforge_project:
150
+ rubygems_version: 2.4.5.1
151
+ signing_key:
152
+ specification_version: 4
153
+ summary: A gem for creating configuration classes using the Abstract Factory pattern.
154
+ test_files:
155
+ - spec/.rubocop.yml
156
+ - spec/data/multiple-environments.yml
157
+ - spec/data/single-environment.yml
158
+ - spec/spec_helper.rb
159
+ - spec/unit/config/factory/abstract_factory_spec.rb
160
+ - spec/unit/config/factory/environment_spec.rb
161
+ - spec/unit/config/factory/environments_spec.rb
162
+ - spec/unit/config/factory/fixtures.rb
163
+ - spec/unit/config/factory/log_spec.rb
164
+ has_rdoc: