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.
- checksums.yaml +7 -0
- data/.gitignore +42 -0
- data/.rubocop.yml +24 -0
- data/.ruby-version +1 -0
- data/.travis.yml +2 -0
- data/Gemfile +3 -0
- data/LICENSE.md +22 -0
- data/README.md +85 -0
- data/Rakefile +49 -0
- data/config-factory.gemspec +32 -0
- data/example.rb +45 -0
- data/lib/config/factory.rb +5 -0
- data/lib/config/factory/abstract_factory.rb +45 -0
- data/lib/config/factory/environment.rb +35 -0
- data/lib/config/factory/environments.rb +25 -0
- data/lib/config/factory/log.rb +35 -0
- data/lib/config/factory/module_info.rb +12 -0
- data/spec/.rubocop.yml +7 -0
- data/spec/data/multiple-environments.yml +52 -0
- data/spec/data/single-environment.yml +19 -0
- data/spec/spec_helper.rb +29 -0
- data/spec/unit/config/factory/abstract_factory_spec.rb +47 -0
- data/spec/unit/config/factory/environment_spec.rb +36 -0
- data/spec/unit/config/factory/environments_spec.rb +20 -0
- data/spec/unit/config/factory/fixtures.rb +73 -0
- data/spec/unit/config/factory/log_spec.rb +23 -0
- metadata +164 -0
checksums.yaml
ADDED
@@ -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
|
data/.gitignore
ADDED
@@ -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
|
data/.rubocop.yml
ADDED
@@ -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
|
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.2.3
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/LICENSE.md
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
# config-factory
|
2
|
+
|
3
|
+
[](https://travis-ci.org/dmolesUC3/config-factory)
|
4
|
+
[](https://codeclimate.com/github/dmolesUC3/config-factory)
|
5
|
+
[](http://inch-ci.org/github/dmolesUC3/config-factory)
|
6
|
+
[](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
|
+
```
|
data/Rakefile
ADDED
@@ -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
|
data/example.rb
ADDED
@@ -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,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
|
data/spec/.rubocop.yml
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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:
|