clean_config 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.gitignore +22 -0
- data/.rspec +1 -0
- data/.rubocop.yml +22 -0
- data/.travis.yml +6 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +4 -0
- data/LICENSE +13 -0
- data/README.md +94 -0
- data/Rakefile +1 -0
- data/build.sh +31 -0
- data/clean_config.gemspec +38 -0
- data/lib/clean_config.rb +4 -0
- data/lib/clean_config/configurable.rb +33 -0
- data/lib/clean_config/configuration.rb +161 -0
- data/lib/clean_config/ext/recursive_open_struct.rb +16 -0
- data/lib/clean_config/version.rb +3 -0
- data/lib/tasks.rb +63 -0
- data/spec/e2e/core/.gitignore +19 -0
- data/spec/e2e/core/.rakeTasks +7 -0
- data/spec/e2e/core/.rspec +1 -0
- data/spec/e2e/core/.rubocop.yml +22 -0
- data/spec/e2e/core/Gemfile +5 -0
- data/spec/e2e/core/Rakefile +1 -0
- data/spec/e2e/core/config/config.yml +3 -0
- data/spec/e2e/core/core.gemspec +31 -0
- data/spec/e2e/core/lib/core.rb +2 -0
- data/spec/e2e/core/lib/core/core_one.rb +13 -0
- data/spec/e2e/core/lib/core/version.rb +4 -0
- data/spec/e2e/core/lib/tasks.rb +17 -0
- data/spec/e2e/core/spec/spec_helper.rb +15 -0
- data/spec/e2e/core/spec/unit/core_spec.rb +12 -0
- data/spec/e2e/core_config_spec.rb +14 -0
- data/spec/fixtures/config.yml +5 -0
- data/spec/fixtures/empty.yml +0 -0
- data/spec/spec_helper.rb +14 -0
- data/spec/unit/clean_configuration_spec.rb +140 -0
- data/spec/unit/configurable_spec.rb +16 -0
- data/spec/unit/recursive_open_struct_spec.rb +22 -0
- metadata +261 -0
checksums.yaml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
---
|
2
|
+
!binary "U0hBMQ==":
|
3
|
+
metadata.gz: !binary |-
|
4
|
+
YTc4YTQ0Mjg4OWIzNGJkMmViYzQwYjI4YTkyMTY0YWE2OGQ3N2QzMw==
|
5
|
+
data.tar.gz: !binary |-
|
6
|
+
NTZlYTM1M2QxNTRmYmNkMDgwNjlhYThkYTM5MmU3MGQ4ZTQzOTM5ZA==
|
7
|
+
SHA512:
|
8
|
+
metadata.gz: !binary |-
|
9
|
+
ZTdlY2ZkZDAyY2M2Y2I3YTcwY2M2ODJiMzlmZTYyYTljMmUwMzQzOTJkY2Jk
|
10
|
+
MmNmMjczNjgyZDI5YTczNGVhYzRhOGU2NGQ4MWNhODBhZWNkNmVmZTg2NjQy
|
11
|
+
YjY5YmZlYmM2MGEwMjkyYTVhZTRlY2I0ZWU4YTFhYjkyOTc3OTM=
|
12
|
+
data.tar.gz: !binary |-
|
13
|
+
YWExOTljY2FmNDJlZmEwNGYyOGU4MThlMzkyMzQ0Y2YwZGU0Zjk2MGRhNDBi
|
14
|
+
Nzg0ZDM5NmQwYWEwMjVkNDVkNzVkNjU3NDFiNTQ1NTQ4MmRkZDA2M2Y1NzE4
|
15
|
+
NDc0MTE1YTljZmM5ZGZlMjdmYjM0ZWYxYTY3MWY5OWE4ZjgzMmM=
|
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
.rvmrc
|
6
|
+
.yardoc
|
7
|
+
Gemfile.lock
|
8
|
+
InstalledFiles
|
9
|
+
_yardoc
|
10
|
+
coverage
|
11
|
+
doc/
|
12
|
+
lib/bundler/man
|
13
|
+
pkg
|
14
|
+
rdoc
|
15
|
+
spec/reports
|
16
|
+
test/tmp
|
17
|
+
test/version_tmp
|
18
|
+
tmp
|
19
|
+
vendor
|
20
|
+
*.log
|
21
|
+
annotations_report.html
|
22
|
+
annotations.yml
|
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#do not check for utf stamp
|
2
|
+
Encoding:
|
3
|
+
Enabled: false
|
4
|
+
|
5
|
+
LineLength:
|
6
|
+
Enabled: true
|
7
|
+
Max: 128
|
8
|
+
|
9
|
+
# The rubocop Documentation cop is a duplicate of the Reek IrresponsibleModule
|
10
|
+
# check.
|
11
|
+
Documentation:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
CaseIndentation:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
# MethodLength is superseded by Reek's TooManyStatements smell-finder.
|
18
|
+
MethodLength:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
CyclomaticComplexity:
|
22
|
+
Max: 10
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2015, Opower
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
#clean_config
|
2
|
+
|
3
|
+
A simple configuration library for Ruby projects.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'clean_config'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle install
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install 'clean_config'
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
By convention, configuration lives in a single file: `config/config.yml`.
|
22
|
+
|
23
|
+
You can put any data you want in this file and access that data in one of three ways:
|
24
|
+
|
25
|
+
```yaml
|
26
|
+
# config/config.yml
|
27
|
+
:foo:
|
28
|
+
:bar: 'baz'
|
29
|
+
```
|
30
|
+
|
31
|
+
```ruby
|
32
|
+
require 'clean_config'
|
33
|
+
|
34
|
+
class MyClass
|
35
|
+
include CleanConfig::Configurable
|
36
|
+
|
37
|
+
def initialize()
|
38
|
+
config = CleanConfig::Configuration.instance
|
39
|
+
config[:foo][:bar] # 'baz'
|
40
|
+
config.foo.bar # 'baz'
|
41
|
+
config.parse_key('foo.bar') # 'baz'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
### Conventions
|
47
|
+
Loading configuration data in Ruby is easy. In fact, it is so easy that if you look at several different Ruby projects,
|
48
|
+
you'll likely find several different implementations for loading configuration. We decided to standardize how we would
|
49
|
+
load our configuration across all our gems.
|
50
|
+
|
51
|
+
This library requires your configuration be stored in a single yml file, located at
|
52
|
+
|
53
|
+
`config/config.yml`
|
54
|
+
|
55
|
+
### Loading Configuration
|
56
|
+
Including the `Configurable` module is what initializes the `Configuration` object with the data from `config/config.yml`.
|
57
|
+
Simply include this module and your configuration will be available via `CleanConfig::Configuration.instance`.
|
58
|
+
|
59
|
+
If you are using the CleanConfig outside of a module or class, there are a few methods available to you
|
60
|
+
to point CleanConfig to your configuration directory.
|
61
|
+
|
62
|
+
`add!` allows you to change the directory/file name for your configuration files.
|
63
|
+
|
64
|
+
`load!` looks for the default directory/file name (`config/config.yml`) but at the same level as the calling code.
|
65
|
+
|
66
|
+
`merge!` allows you to pass in a hash of additional configuration to add to your CleanConfig.
|
67
|
+
|
68
|
+
### Accessing Configuration
|
69
|
+
After `include CleanConfig::Configurable` you can access your config with: `CleanConfig::Configuration.instance`.
|
70
|
+
This will have all of your project's configuration and any configuration defined in dependencies.
|
71
|
+
|
72
|
+
To get access to the underlying `Hash` methods prefix them with `to_hash` or `to_h`, e.g. `config.to_h.values`.
|
73
|
+
|
74
|
+
Note: We have added a `#keys` method also.
|
75
|
+
As a result, if you have a field called `:keys:` in your config file the only way to access it is `config.to_h[:keys]`
|
76
|
+
|
77
|
+
### Layering Configuration
|
78
|
+
If you depend on gems that are using clean_config, you can override their key-value pairs in your own `config/config.yml`.
|
79
|
+
Also, it's a good idea to nest your configuration under some top-level, project-specific key to prevent accidental
|
80
|
+
configuration collisions.
|
81
|
+
|
82
|
+
## Contributing
|
83
|
+
|
84
|
+
#### Contacts
|
85
|
+
+ Adrian Cazacu
|
86
|
+
+ CivJ
|
87
|
+
+ Crystal Hsiung
|
88
|
+
|
89
|
+
#### Process
|
90
|
+
1. Fork it
|
91
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
92
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
93
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
94
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'lib/tasks'
|
data/build.sh
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/bin/bash
|
2
|
+
|
3
|
+
# Tell bash that we want the whole script to fail if any part fails.
|
4
|
+
set -e
|
5
|
+
|
6
|
+
# Global Variables
|
7
|
+
SOURCE_DIR=`pwd`
|
8
|
+
|
9
|
+
# Begin
|
10
|
+
echo "*************************************"
|
11
|
+
echo "Running build script..."
|
12
|
+
echo "PWD :"$SOURCE_DIR
|
13
|
+
|
14
|
+
main() {
|
15
|
+
echo "*************************************"
|
16
|
+
startTime=$(date +%s)
|
17
|
+
|
18
|
+
bundle install --path vendor/bundle
|
19
|
+
bundle exec rake rubocop
|
20
|
+
bundle exec rake spec:full --trace
|
21
|
+
gem build orb_configuration.gemspec
|
22
|
+
|
23
|
+
endTime=$(date +%s)
|
24
|
+
timeDifference=$(( $endTime - $startTime ))
|
25
|
+
|
26
|
+
echo "Execution time :" $timeDifference
|
27
|
+
echo "Finished."
|
28
|
+
}
|
29
|
+
|
30
|
+
# RUN
|
31
|
+
main
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/clean_config/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'clean_config'
|
6
|
+
spec.version = CleanConfig::VERSION
|
7
|
+
spec.summary = 'A simple configuration library'
|
8
|
+
spec.description = 'Provides programatic access to config/config.yml'
|
9
|
+
spec.homepage = 'http://github.com/opower/clean_config'
|
10
|
+
|
11
|
+
spec.authors = ['John Crimmins', 'Crystal Hsiung', 'Adrian Cazacu']
|
12
|
+
spec.email = ['john.crimmins@opower.com']
|
13
|
+
|
14
|
+
# This gem will work with 1.9.3 or greater...
|
15
|
+
spec.required_ruby_version = '>= 1.9.3'
|
16
|
+
|
17
|
+
spec.license = 'Apache 2'
|
18
|
+
|
19
|
+
# file attributes...
|
20
|
+
spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
21
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_development_dependency('rake', '~> 10.1')
|
26
|
+
spec.add_development_dependency('rspec', '~> 3.1')
|
27
|
+
spec.add_development_dependency('rspec-legacy_formatters', '~> 1.0')
|
28
|
+
spec.add_development_dependency('rspec-extra-formatters', '~> 1.0')
|
29
|
+
spec.add_development_dependency('rubocop', '= 0.26.1')
|
30
|
+
spec.add_development_dependency('fuubar', '~> 2.0')
|
31
|
+
spec.add_development_dependency('yard')
|
32
|
+
spec.add_development_dependency('redcarpet')
|
33
|
+
spec.add_development_dependency('simplecov', '~> 0.7')
|
34
|
+
|
35
|
+
spec.add_runtime_dependency('recursive-open-struct', '~> 0.5')
|
36
|
+
# We're using deep_merge which is available in all versions of activesupport so far.
|
37
|
+
spec.add_runtime_dependency('activesupport', '< 5.0')
|
38
|
+
end
|
data/lib/clean_config.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'logger'
|
2
|
+
require_relative 'configuration'
|
3
|
+
|
4
|
+
module CleanConfig
|
5
|
+
# Module to help initialize and gain access to CleanConfig::Configuration object
|
6
|
+
module Configurable
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Initialize the CleanConfig::Configuration object
|
10
|
+
# Reads in from default config/config.yml file based on project root directory
|
11
|
+
def included(_parent)
|
12
|
+
log = ConfLogger.new(STDOUT)
|
13
|
+
|
14
|
+
# calling_file is the file name of the Ruby code that is our parent in the call stack.
|
15
|
+
calling_file = caller.first.split(':').first
|
16
|
+
log.debug("calling_file: #{calling_file}")
|
17
|
+
config_path = Configuration.resolve_config_path(calling_file)
|
18
|
+
|
19
|
+
if File.exist?(config_path)
|
20
|
+
Configuration.instance.add!(config_path)
|
21
|
+
log.debug("Reading configuration from #{config_path}")
|
22
|
+
begin
|
23
|
+
Configuration.instance.add!(config_path)
|
24
|
+
rescue InvalidConfigException
|
25
|
+
log.warn("Read configuration from #{config_path}, but configuration not valid. Ignoring, check your config")
|
26
|
+
end
|
27
|
+
else
|
28
|
+
log.debug("Expected config directory #{config_path} not found. Not loading configuration")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
require 'forwardable'
|
3
|
+
require 'recursive-open-struct'
|
4
|
+
require 'singleton'
|
5
|
+
require 'logger'
|
6
|
+
require 'yaml'
|
7
|
+
|
8
|
+
module CleanConfig
|
9
|
+
# Exception when file not found
|
10
|
+
FileNotFoundException = Class.new(Exception)
|
11
|
+
# Exception for configuration parsing errors
|
12
|
+
InvalidConfigException = Class.new(Exception)
|
13
|
+
|
14
|
+
# Logger that reads DEBUG environment variable to set level
|
15
|
+
class ConfLogger < Logger
|
16
|
+
def initialize(*args)
|
17
|
+
super
|
18
|
+
self.level = ENV['DEBUG'] ? Logger::DEBUG : Logger::INFO
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Provides access to configuration data
|
23
|
+
# Supports both [:property] and '.property' style access to yml configuration
|
24
|
+
# Default configuration path is `config/config.yml`
|
25
|
+
class Configuration
|
26
|
+
include ::Singleton
|
27
|
+
extend ::Forwardable
|
28
|
+
|
29
|
+
# directory where configuration yml is expected to be, relative to project root directory
|
30
|
+
DEFAULT_CONFIGURATION_DIRECTORY = 'config'
|
31
|
+
|
32
|
+
# name of configuration yml
|
33
|
+
DEFAULT_CONFIGURATION_FILE_NAME = "#{DEFAULT_CONFIGURATION_DIRECTORY}.yml"
|
34
|
+
|
35
|
+
# directories commonly found at project root directory, used to find the project root
|
36
|
+
CODE_DIRECTORIES = %w(lib spec bin)
|
37
|
+
|
38
|
+
# logger
|
39
|
+
LOG = ConfLogger.new(STDOUT)
|
40
|
+
|
41
|
+
def_delegators :@data_hash, :[]
|
42
|
+
|
43
|
+
class << self
|
44
|
+
# Finds the full path to the project's configuration file
|
45
|
+
#
|
46
|
+
# @param [String] calling_file path of the file that invoked this code
|
47
|
+
# @return [String] full path to configuration
|
48
|
+
def resolve_config_path(calling_file)
|
49
|
+
config_location = File.join(Configuration::DEFAULT_CONFIGURATION_DIRECTORY,
|
50
|
+
Configuration::DEFAULT_CONFIGURATION_FILE_NAME)
|
51
|
+
|
52
|
+
config_path = find_execution_path(calling_file)
|
53
|
+
config_path.empty? ? config_path : File.join(config_path, config_location)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Finds a Ruby project's lib directory by looking for a Gemfile sibling
|
57
|
+
#
|
58
|
+
# @param [String] path The path in which to look for the project's lib directory
|
59
|
+
# @return [String] the project root directory
|
60
|
+
def find_execution_path(path)
|
61
|
+
path = File.extname(path).empty? ? path : File.dirname(path)
|
62
|
+
directories = path.split(File::Separator)
|
63
|
+
project_directory = ''
|
64
|
+
|
65
|
+
until directories.nil? || directories.empty?
|
66
|
+
if CODE_DIRECTORIES.include?(directories.last) && project_directory.empty?
|
67
|
+
directories.pop
|
68
|
+
gemfile_location = File.join(directories.join(File::Separator), 'Gemfile')
|
69
|
+
project_directory = File.dirname(gemfile_location) if File.exist?(gemfile_location)
|
70
|
+
end
|
71
|
+
directories.pop
|
72
|
+
end
|
73
|
+
project_directory
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# Loads configuration relative to Ruby's execution directory.
|
78
|
+
# Useful for accessing config in tests and Rake tasks
|
79
|
+
#
|
80
|
+
# @return [Configuration] self
|
81
|
+
def load!
|
82
|
+
add!(File.join(DEFAULT_CONFIGURATION_DIRECTORY, DEFAULT_CONFIGURATION_FILE_NAME))
|
83
|
+
end
|
84
|
+
|
85
|
+
# Allows the user to specify a config file other than 'config/config.yml'
|
86
|
+
#
|
87
|
+
# @param [String] config_path provided as a convenience, but should be avoided in favor of the default location
|
88
|
+
# @return [CleanConfig::Configuration] self
|
89
|
+
def add!(config_path = nil)
|
90
|
+
calling_code_file_path = caller.first.split(':').first
|
91
|
+
config_path ||= Configuration.resolve_config_path(calling_code_file_path)
|
92
|
+
fail FileNotFoundException, "#{config_path} not found" unless File.exist?(config_path)
|
93
|
+
|
94
|
+
LOG.debug("Reading configuration from #{config_path}")
|
95
|
+
config_hash = YAML.load_file(config_path)
|
96
|
+
fail InvalidConfigException, "YAML unable to parse empty #{config_path}" unless config_hash # empty YAML returns false
|
97
|
+
|
98
|
+
merge!(config_hash)
|
99
|
+
end
|
100
|
+
|
101
|
+
# Set and merge config at runtime without a file
|
102
|
+
#
|
103
|
+
# @param [Hash] config data to add to configuration
|
104
|
+
# @return [CleanConfig::Configuration] self
|
105
|
+
def merge!(config = {})
|
106
|
+
@data_hash = @data_hash.nil? ? config : @data_hash.deep_merge(config)
|
107
|
+
@data_model = RecursiveOpenStruct.new(@data_hash, recurse_over_arrays: true)
|
108
|
+
self
|
109
|
+
end
|
110
|
+
|
111
|
+
# Given a period-delimited string of keys, find the nested value stored in the configuration
|
112
|
+
#
|
113
|
+
# @param [String] config_key period-delimited string of nested keys
|
114
|
+
# @return [Object] value retrieved
|
115
|
+
def parse_key(config_key)
|
116
|
+
fail 'config_key required' if config_key.nil? || config_key.empty?
|
117
|
+
parse_key_recursive(@data_model, config_key.split('.').reverse, '')
|
118
|
+
end
|
119
|
+
|
120
|
+
# Pass along methods not recognized to the underlying data structure
|
121
|
+
def method_missing(method, *args, &block)
|
122
|
+
@data_model.send(method, *args, &block)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Returns whether the configuration is empty or not
|
126
|
+
#
|
127
|
+
# @return [Boolean] true if configuration is empty
|
128
|
+
def empty?
|
129
|
+
@data_model.nil?
|
130
|
+
end
|
131
|
+
|
132
|
+
# Clear configuration
|
133
|
+
#
|
134
|
+
# @return [CleanConfig::Configuration] self
|
135
|
+
def reset!
|
136
|
+
@data_model = nil
|
137
|
+
@data_hash = nil
|
138
|
+
self
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
# For nested configurations, recursively look for the key
|
144
|
+
#
|
145
|
+
# @param [Object] data_model configuration object to look for key in
|
146
|
+
# @param [String] config_keys period-delimited string of keys to look for
|
147
|
+
# @param [String] key_message period-delimited string of keys we are nested in, used for debug output
|
148
|
+
# @return [Object] value
|
149
|
+
def parse_key_recursive(data_model, config_keys, key_message)
|
150
|
+
if config_keys.length > 0
|
151
|
+
config_key = config_keys.pop
|
152
|
+
key_message << config_key
|
153
|
+
configuration = data_model.send(config_key.to_sym)
|
154
|
+
fail "config_key #{key_message} has no defined value" unless configuration
|
155
|
+
parse_key_recursive(configuration, config_keys, key_message << '.')
|
156
|
+
else
|
157
|
+
data_model
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# Monkeypatching RecursiveOpenStruct to respond to common Hash methods
|
2
|
+
class RecursiveOpenStruct < OpenStruct
|
3
|
+
# Returns array with keys from the RecursiveOpenStruct
|
4
|
+
# @return [Array] keys
|
5
|
+
def keys
|
6
|
+
to_h.keys
|
7
|
+
end
|
8
|
+
|
9
|
+
# Returns value for given key
|
10
|
+
# @param [Object] key key to retrieve value
|
11
|
+
# @param [Object] default value to return if key is not found
|
12
|
+
# @return [Object] value associated with given key
|
13
|
+
def fetch(key, default = nil)
|
14
|
+
to_h.fetch(key, default)
|
15
|
+
end
|
16
|
+
end
|
data/lib/tasks.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# Please note this file does not use the test_support gem because test_support depends on orb_configuration.
|
3
|
+
# As a work-around to avoid a circular-dependency, we're rolling our own task code here.
|
4
|
+
# This is a special case. The vast majority of projects should be using test_support to provide Rspec tasks.
|
5
|
+
require 'rspec'
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
require 'rspec-extra-formatters'
|
8
|
+
require 'fuubar'
|
9
|
+
require 'rubocop/rake_task'
|
10
|
+
require 'logger'
|
11
|
+
|
12
|
+
TMP_DIR = 'tmp'
|
13
|
+
LOG = Logger.new(open('rake.log', File::WRONLY | File::APPEND | File::CREAT))
|
14
|
+
|
15
|
+
desc 'Run RuboCop on lib and spec directories, Gemfile, gemspec, Rakefile; Override with a space delimited list'
|
16
|
+
RuboCop::RakeTask.new(:rubocop, :pattern) do |task, args|
|
17
|
+
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'Gemfile', '*.gemspec', 'Rakefile']
|
18
|
+
task.patterns = args[:pattern].split(' ') if args[:pattern] # override default pattern
|
19
|
+
LOG.info("Running RuboCop against #{task.patterns}")
|
20
|
+
end
|
21
|
+
|
22
|
+
def timestamp
|
23
|
+
Time.now.strftime('%Y%m%d_%H%M%S')
|
24
|
+
end
|
25
|
+
|
26
|
+
def build_rspec_opts(test_type, task)
|
27
|
+
task.rspec_opts = ['-c']
|
28
|
+
task.rspec_opts << '--require' << 'fuubar'
|
29
|
+
task.rspec_opts << '--format' << Fuubar
|
30
|
+
task.rspec_opts << '--require' << 'rspec/legacy_formatters'
|
31
|
+
task.rspec_opts << '--require' << 'rspec-extra-formatters'
|
32
|
+
task.rspec_opts << '--format' << JUnitFormatter
|
33
|
+
task.rspec_opts << '--out' << "tmp/results/#{test_type}/#{timestamp}_results.xml"
|
34
|
+
task.rspec_opts << '--format' << 'html'
|
35
|
+
task.rspec_opts << '--out' << "tmp/results/#{test_type}/#{timestamp}_results.html"
|
36
|
+
task.pattern = "spec/#{test_type}/**/*_spec.rb"
|
37
|
+
end
|
38
|
+
|
39
|
+
namespace :clean do
|
40
|
+
desc 'Remove all tmp files'
|
41
|
+
task :tmp do
|
42
|
+
LOG.info("Deleting the #{TMP_DIR} directory...")
|
43
|
+
FileUtils.rm_rf(TMP_DIR)
|
44
|
+
LOG.info('Deleted.')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
namespace :spec do
|
49
|
+
RSpec::Core::RakeTask.new(:unit) do |task|
|
50
|
+
FileUtils.mkdir_p(TMP_DIR)
|
51
|
+
build_rspec_opts('unit', task)
|
52
|
+
end
|
53
|
+
|
54
|
+
RSpec::Core::RakeTask.new(:e2e) do |task|
|
55
|
+
FileUtils.mkdir_p(TMP_DIR)
|
56
|
+
build_rspec_opts('e2e', task)
|
57
|
+
end
|
58
|
+
|
59
|
+
desc 'Run all tests'
|
60
|
+
task full: %w(clean:tmp spec:unit spec:e2e)
|
61
|
+
end
|
62
|
+
|
63
|
+
LOG.close
|
@@ -0,0 +1,7 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<Settings><!--This file was automatically generated by Ruby plugin.
|
3
|
+
You are allowed to:
|
4
|
+
1. Remove rake task
|
5
|
+
2. Add existing rake tasks
|
6
|
+
To add existing rake tasks automatically delete this file and reload the project.
|
7
|
+
--><RakeGroup description="" fullCmd="" taksId="rake" /></Settings>
|
@@ -0,0 +1 @@
|
|
1
|
+
--require spec_helper
|
@@ -0,0 +1,22 @@
|
|
1
|
+
#do not check for utf stamp
|
2
|
+
Encoding:
|
3
|
+
Enabled: false
|
4
|
+
|
5
|
+
LineLength:
|
6
|
+
Enabled: true
|
7
|
+
Max: 128
|
8
|
+
|
9
|
+
# The rubocop Documentation cop is a duplicate of the Reek IrresponsibleModule
|
10
|
+
# check.
|
11
|
+
Documentation:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
CaseIndentation:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
# MethodLength is superseded by Reek's TooManyStatements smell-finder.
|
18
|
+
MethodLength:
|
19
|
+
Enabled: false
|
20
|
+
|
21
|
+
CyclomaticComplexity:
|
22
|
+
Max: 10
|
@@ -0,0 +1 @@
|
|
1
|
+
require_relative 'lib/tasks'
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/core/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'core'
|
6
|
+
spec.version = Core::VERSION
|
7
|
+
spec.summary = 'TODO: Write a short summary. Required.'
|
8
|
+
spec.description = 'TODO: Write a longer description. Optional.'
|
9
|
+
spec.homepage = 'http://github.com/your-GH-name-here/core'
|
10
|
+
|
11
|
+
spec.authors = ['foo']
|
12
|
+
spec.email = ['your-email-here@email.com']
|
13
|
+
|
14
|
+
# This gem will work with 1.9.3 or greater...
|
15
|
+
spec.required_ruby_version = '>= 1.9.3'
|
16
|
+
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
# file attributes...
|
20
|
+
spec.files = `git ls-files`.split($OUTPUT_RECORD_SEPARATOR)
|
21
|
+
spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
|
22
|
+
spec.test_files = spec.files.grep(/^(test|spec|features)\//)
|
23
|
+
spec.require_paths = ['lib']
|
24
|
+
|
25
|
+
spec.add_development_dependency('rake', '~> 10.1')
|
26
|
+
spec.add_development_dependency('rspec', ' 2.14.1')
|
27
|
+
spec.add_development_dependency('rspec-extra-formatters', ' 0.4')
|
28
|
+
spec.add_development_dependency('rubocop', ' 0.24.0')
|
29
|
+
spec.add_development_dependency('simplecov', ' 0.7.1')
|
30
|
+
spec.add_development_dependency('rspec', '~> 3.1')
|
31
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'rubocop/rake_task'
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
|
5
|
+
desc 'Run RuboCop on lib and spec directories, Gemfile, gemspec, Rakefile; Override with a space delimited list'
|
6
|
+
RuboCop::RakeTask.new(:rubocop, :pattern) do |task, args|
|
7
|
+
task.patterns = ['lib/**/*.rb', 'spec/**/*.rb', 'Gemfile', '*.gemspec', 'Rakefile']
|
8
|
+
task.patterns = args[:pattern].split(' ') if args[:pattern] # override default pattern
|
9
|
+
# don't abort rake on failure
|
10
|
+
task.fail_on_error = false
|
11
|
+
end
|
12
|
+
|
13
|
+
namespace :spec do
|
14
|
+
RSpec::Core::RakeTask.new(:unit) do |task|
|
15
|
+
task.pattern = 'spec/**/*_spec.rb'
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# TODO: make spec_helper_gem and spec_helper_test. Take coverage out of test.
|
2
|
+
require 'simplecov'
|
3
|
+
|
4
|
+
SimpleCov.start do
|
5
|
+
coverage_dir 'tmp/coverage/unit'
|
6
|
+
add_filter 'tmp/'
|
7
|
+
add_filter 'spec/'
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec.configure do |config|
|
11
|
+
# Only accept expect syntax do not allow old should syntax
|
12
|
+
config.expect_with :rspec do |c|
|
13
|
+
c.syntax = :expect
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'English'
|
2
|
+
|
3
|
+
module CleanConfig
|
4
|
+
describe Configuration do
|
5
|
+
it 'should load correct config when required in a different gem' do
|
6
|
+
Dir.chdir(File.join('spec', 'e2e', 'core')) do
|
7
|
+
Bundler.with_clean_env do
|
8
|
+
`bundle install && bundle exec rake spec:unit`
|
9
|
+
end
|
10
|
+
end
|
11
|
+
expect($CHILD_STATUS.success?).to be true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
File without changes
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
|
3
|
+
SimpleCov.start do
|
4
|
+
coverage_dir 'tmp/coverage/unit'
|
5
|
+
add_filter 'tmp/'
|
6
|
+
add_filter 'spec/'
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec.configure do |config|
|
10
|
+
# Only accept expect syntax do not allow old should syntax
|
11
|
+
config.expect_with :rspec do |c|
|
12
|
+
c.syntax = :expect
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require_relative '../../lib/clean_config/configuration'
|
2
|
+
|
3
|
+
module CleanConfig
|
4
|
+
describe Configuration do
|
5
|
+
context 'singleton creation' do
|
6
|
+
it 'only creates one instance' do
|
7
|
+
config = Configuration.instance
|
8
|
+
expect(config).to eql(Configuration.instance)
|
9
|
+
end
|
10
|
+
|
11
|
+
it '#new throws error' do
|
12
|
+
expect { Configuration.new }.to raise_error(NoMethodError)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context 'instance methods' do
|
17
|
+
let(:config_path) { File.join(File.dirname(__FILE__), '..', 'fixtures') }
|
18
|
+
let(:config) do
|
19
|
+
config = Configuration.instance
|
20
|
+
config.add!(File.join(config_path, 'config.yml'))
|
21
|
+
config
|
22
|
+
end
|
23
|
+
|
24
|
+
it '#load! loads the top-level config.yml' do
|
25
|
+
stub_const('CleanConfig::Configuration::DEFAULT_CONFIGURATION_DIRECTORY', config_path)
|
26
|
+
config = Configuration.instance
|
27
|
+
config.load!
|
28
|
+
expect(config.test.foo).to eq('bar')
|
29
|
+
end
|
30
|
+
|
31
|
+
it '#add! fails if YAML file is empty' do
|
32
|
+
config_path = File.join(File.dirname(__FILE__), '..', 'fixtures', 'empty.yml')
|
33
|
+
expect { config.add!(config_path) }.to raise_error("YAML unable to parse empty #{config_path}")
|
34
|
+
end
|
35
|
+
|
36
|
+
it '#merge! sets config as expected' do
|
37
|
+
expect(config.merge_test.foo).to eq('baz')
|
38
|
+
config.merge!(merge_test: { foo: 'asdf' })
|
39
|
+
expect(config.merge_test.foo).to eq('asdf')
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'delegated methods' do
|
43
|
+
it '#[] accepts a symbol and provides access to config data' do
|
44
|
+
expect(config[:test][:foo]).to eq('bar')
|
45
|
+
end
|
46
|
+
|
47
|
+
it '#[] accepts a string and provides access to config data' do
|
48
|
+
expect(config['other_test']).to eq(123)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'config properties are methods' do
|
53
|
+
it '#method_missing forwards methods to internal RecursiveStruct' do
|
54
|
+
expect(config.test.foo).to eq('bar')
|
55
|
+
end
|
56
|
+
|
57
|
+
it '#method_missing returns nil when internal RecursiveStruct has no associated property' do
|
58
|
+
expect(config.fake).to be_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'configuration string parsing' do
|
63
|
+
it '#parse_config_key returns the correct property value for the given string' do
|
64
|
+
expect(config.parse_key('test.foo')).to eq('bar')
|
65
|
+
expect(config.parse_key('test').foo).to eq('bar')
|
66
|
+
end
|
67
|
+
it '#parse_config_key throws an error for nonexistant keys' do
|
68
|
+
# Providing 'fail' does not throw the error I expect. I am not sure why.
|
69
|
+
# expect(config.parse_config_key('fail')).to eq('bar')
|
70
|
+
expect { config.parse_key('nope') }.to raise_error(RuntimeError)
|
71
|
+
expect { config.parse_key('nope.again') }.to raise_error(RuntimeError)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'read config file' do
|
76
|
+
it 'add! throws FileNotFoundException if there is no file.' do
|
77
|
+
expect { config.add!('') }.to raise_error(FileNotFoundException)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it '#empty? should return false if config file was read.' do
|
82
|
+
expect(config.empty?).to be false
|
83
|
+
end
|
84
|
+
|
85
|
+
it '#empty? should return true if no config file was read.' do
|
86
|
+
config.reset!
|
87
|
+
expect(config.empty?).to be true
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
context 'class methods' do
|
93
|
+
let(:var_lib_jenkins_foo) { '/var/lib/jenkins/foo' }
|
94
|
+
let(:var_jenkins_foo) { '/var/jenkins/foo' }
|
95
|
+
|
96
|
+
it '#find_execution_dir finds a config location when code is in a bin directory' do
|
97
|
+
# We use `File.exist?` in configuration.rb to check if we have a Gemfile.
|
98
|
+
allow(File).to receive(:exist?).and_return(true)
|
99
|
+
expect(Configuration.find_execution_path('/var/lib/jenkins/foo/bin/file.rb')).to eq(var_lib_jenkins_foo)
|
100
|
+
end
|
101
|
+
|
102
|
+
it '#find_execution_dir does not find a config when none exists under a lib directory' do
|
103
|
+
allow(File).to receive(:exist?).and_return(false, false)
|
104
|
+
expect(Configuration.find_execution_path('/var/lib/jenkins/foo/lib/file.rb')).to be_empty
|
105
|
+
end
|
106
|
+
|
107
|
+
it '#find_execution_dir finds config location with nested libs' do
|
108
|
+
allow(File).to receive(:exist?).and_return(true)
|
109
|
+
expect(Configuration.find_execution_path('/var/lib/jenkins/foo/lib/file.rb')).to eq(var_lib_jenkins_foo)
|
110
|
+
end
|
111
|
+
|
112
|
+
it '#find_execution_dir finds config location with nested specs' do
|
113
|
+
allow(File).to receive(:exist?).and_return(false, true)
|
114
|
+
expect(Configuration.find_execution_path('/var/lib/jenkins/foo/spec/smoke/spec'))
|
115
|
+
.to eq(var_lib_jenkins_foo)
|
116
|
+
end
|
117
|
+
|
118
|
+
it '#find_execution_dir finds config location when calling code is deep under lib' do
|
119
|
+
allow(File).to receive(:exist?).and_return(true)
|
120
|
+
expect(Configuration.find_execution_path('/var/lib/jenkins/foo/lib/one/two/three/file.rb'))
|
121
|
+
.to eq(var_lib_jenkins_foo)
|
122
|
+
end
|
123
|
+
|
124
|
+
it '#find_execution_dir finds config location with spec nested under lib' do
|
125
|
+
allow(File).to receive(:exist?).and_return(true)
|
126
|
+
expect(Configuration.find_execution_path('/var/lib/jenkins/foo/spec/file.rb')).to eq(var_lib_jenkins_foo)
|
127
|
+
end
|
128
|
+
|
129
|
+
it '#find_execution_dir finds config location with one lib' do
|
130
|
+
allow(File).to receive(:exist?).and_return(true)
|
131
|
+
expect(Configuration.find_execution_path('/var/jenkins/foo/lib/file.rb')).to eq(var_jenkins_foo)
|
132
|
+
end
|
133
|
+
|
134
|
+
it '#find_execution_dir finds config location with one spec' do
|
135
|
+
allow(File).to receive(:exist?).and_return(true, true)
|
136
|
+
expect(Configuration.find_execution_path('/var/jenkins/foo/spec/file.rb')).to eq(var_jenkins_foo)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative '../../lib/clean_config/configurable'
|
2
|
+
require_relative '../../lib/clean_config/configuration'
|
3
|
+
|
4
|
+
module CleanConfig
|
5
|
+
describe Configurable do
|
6
|
+
context 'hooks' do
|
7
|
+
it 'does not fail on include when config/config.yml not found' do
|
8
|
+
expect do
|
9
|
+
class ConfigTest
|
10
|
+
include Configurable
|
11
|
+
end
|
12
|
+
end.not_to raise_error
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require_relative '../../lib/clean_config/ext/recursive_open_struct'
|
2
|
+
|
3
|
+
module CleanConfig
|
4
|
+
describe RecursiveOpenStruct do
|
5
|
+
context 'monkey patched methods' do
|
6
|
+
let(:subject) do
|
7
|
+
hash = { key1: 'value1', key2: 'value2' }
|
8
|
+
RecursiveOpenStruct.new(hash, recurse_over_arrays: true)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'responds to keys' do
|
12
|
+
expect(subject.keys).to include(:key1)
|
13
|
+
expect(subject.keys).to include(:key2)
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'responds to fetch' do
|
17
|
+
expect(subject.fetch(:key1)).to eql('value1')
|
18
|
+
expect(subject.fetch(:monkey, 'default')).to eql('default')
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,261 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: clean_config
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- John Crimmins
|
8
|
+
- Crystal Hsiung
|
9
|
+
- Adrian Cazacu
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2015-10-15 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rake
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '10.1'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
requirements:
|
26
|
+
- - ~>
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
version: '10.1'
|
29
|
+
- !ruby/object:Gem::Dependency
|
30
|
+
name: rspec
|
31
|
+
requirement: !ruby/object:Gem::Requirement
|
32
|
+
requirements:
|
33
|
+
- - ~>
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: '3.1'
|
36
|
+
type: :development
|
37
|
+
prerelease: false
|
38
|
+
version_requirements: !ruby/object:Gem::Requirement
|
39
|
+
requirements:
|
40
|
+
- - ~>
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '3.1'
|
43
|
+
- !ruby/object:Gem::Dependency
|
44
|
+
name: rspec-legacy_formatters
|
45
|
+
requirement: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ~>
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: '1.0'
|
50
|
+
type: :development
|
51
|
+
prerelease: false
|
52
|
+
version_requirements: !ruby/object:Gem::Requirement
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '1.0'
|
57
|
+
- !ruby/object:Gem::Dependency
|
58
|
+
name: rspec-extra-formatters
|
59
|
+
requirement: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ~>
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '1.0'
|
64
|
+
type: :development
|
65
|
+
prerelease: false
|
66
|
+
version_requirements: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ~>
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '1.0'
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: rubocop
|
73
|
+
requirement: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - '='
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: 0.26.1
|
78
|
+
type: :development
|
79
|
+
prerelease: false
|
80
|
+
version_requirements: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - '='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: 0.26.1
|
85
|
+
- !ruby/object:Gem::Dependency
|
86
|
+
name: fuubar
|
87
|
+
requirement: !ruby/object:Gem::Requirement
|
88
|
+
requirements:
|
89
|
+
- - ~>
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
version: '2.0'
|
92
|
+
type: :development
|
93
|
+
prerelease: false
|
94
|
+
version_requirements: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - ~>
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '2.0'
|
99
|
+
- !ruby/object:Gem::Dependency
|
100
|
+
name: yard
|
101
|
+
requirement: !ruby/object:Gem::Requirement
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
type: :development
|
107
|
+
prerelease: false
|
108
|
+
version_requirements: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
- !ruby/object:Gem::Dependency
|
114
|
+
name: redcarpet
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ! '>='
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
type: :development
|
121
|
+
prerelease: false
|
122
|
+
version_requirements: !ruby/object:Gem::Requirement
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: simplecov
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - ~>
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0.7'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
requirements:
|
138
|
+
- - ~>
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0.7'
|
141
|
+
- !ruby/object:Gem::Dependency
|
142
|
+
name: recursive-open-struct
|
143
|
+
requirement: !ruby/object:Gem::Requirement
|
144
|
+
requirements:
|
145
|
+
- - ~>
|
146
|
+
- !ruby/object:Gem::Version
|
147
|
+
version: '0.5'
|
148
|
+
type: :runtime
|
149
|
+
prerelease: false
|
150
|
+
version_requirements: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ~>
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0.5'
|
155
|
+
- !ruby/object:Gem::Dependency
|
156
|
+
name: activesupport
|
157
|
+
requirement: !ruby/object:Gem::Requirement
|
158
|
+
requirements:
|
159
|
+
- - <
|
160
|
+
- !ruby/object:Gem::Version
|
161
|
+
version: '5.0'
|
162
|
+
type: :runtime
|
163
|
+
prerelease: false
|
164
|
+
version_requirements: !ruby/object:Gem::Requirement
|
165
|
+
requirements:
|
166
|
+
- - <
|
167
|
+
- !ruby/object:Gem::Version
|
168
|
+
version: '5.0'
|
169
|
+
description: Provides programatic access to config/config.yml
|
170
|
+
email:
|
171
|
+
- john.crimmins@opower.com
|
172
|
+
executables: []
|
173
|
+
extensions: []
|
174
|
+
extra_rdoc_files: []
|
175
|
+
files:
|
176
|
+
- .gitignore
|
177
|
+
- .rspec
|
178
|
+
- .rubocop.yml
|
179
|
+
- .travis.yml
|
180
|
+
- .yardopts
|
181
|
+
- CHANGELOG.md
|
182
|
+
- Gemfile
|
183
|
+
- LICENSE
|
184
|
+
- README.md
|
185
|
+
- Rakefile
|
186
|
+
- build.sh
|
187
|
+
- clean_config.gemspec
|
188
|
+
- lib/clean_config.rb
|
189
|
+
- lib/clean_config/configurable.rb
|
190
|
+
- lib/clean_config/configuration.rb
|
191
|
+
- lib/clean_config/ext/recursive_open_struct.rb
|
192
|
+
- lib/clean_config/version.rb
|
193
|
+
- lib/tasks.rb
|
194
|
+
- spec/e2e/core/.gitignore
|
195
|
+
- spec/e2e/core/.rakeTasks
|
196
|
+
- spec/e2e/core/.rspec
|
197
|
+
- spec/e2e/core/.rubocop.yml
|
198
|
+
- spec/e2e/core/Gemfile
|
199
|
+
- spec/e2e/core/Rakefile
|
200
|
+
- spec/e2e/core/config/config.yml
|
201
|
+
- spec/e2e/core/core.gemspec
|
202
|
+
- spec/e2e/core/lib/core.rb
|
203
|
+
- spec/e2e/core/lib/core/core_one.rb
|
204
|
+
- spec/e2e/core/lib/core/version.rb
|
205
|
+
- spec/e2e/core/lib/tasks.rb
|
206
|
+
- spec/e2e/core/spec/spec_helper.rb
|
207
|
+
- spec/e2e/core/spec/unit/core_spec.rb
|
208
|
+
- spec/e2e/core_config_spec.rb
|
209
|
+
- spec/fixtures/config.yml
|
210
|
+
- spec/fixtures/empty.yml
|
211
|
+
- spec/spec_helper.rb
|
212
|
+
- spec/unit/clean_configuration_spec.rb
|
213
|
+
- spec/unit/configurable_spec.rb
|
214
|
+
- spec/unit/recursive_open_struct_spec.rb
|
215
|
+
homepage: http://github.com/opower/clean_config
|
216
|
+
licenses:
|
217
|
+
- Apache 2
|
218
|
+
metadata: {}
|
219
|
+
post_install_message:
|
220
|
+
rdoc_options: []
|
221
|
+
require_paths:
|
222
|
+
- lib
|
223
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
224
|
+
requirements:
|
225
|
+
- - ! '>='
|
226
|
+
- !ruby/object:Gem::Version
|
227
|
+
version: 1.9.3
|
228
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
229
|
+
requirements:
|
230
|
+
- - ! '>='
|
231
|
+
- !ruby/object:Gem::Version
|
232
|
+
version: '0'
|
233
|
+
requirements: []
|
234
|
+
rubyforge_project:
|
235
|
+
rubygems_version: 2.4.8
|
236
|
+
signing_key:
|
237
|
+
specification_version: 4
|
238
|
+
summary: A simple configuration library
|
239
|
+
test_files:
|
240
|
+
- spec/e2e/core/.gitignore
|
241
|
+
- spec/e2e/core/.rakeTasks
|
242
|
+
- spec/e2e/core/.rspec
|
243
|
+
- spec/e2e/core/.rubocop.yml
|
244
|
+
- spec/e2e/core/Gemfile
|
245
|
+
- spec/e2e/core/Rakefile
|
246
|
+
- spec/e2e/core/config/config.yml
|
247
|
+
- spec/e2e/core/core.gemspec
|
248
|
+
- spec/e2e/core/lib/core.rb
|
249
|
+
- spec/e2e/core/lib/core/core_one.rb
|
250
|
+
- spec/e2e/core/lib/core/version.rb
|
251
|
+
- spec/e2e/core/lib/tasks.rb
|
252
|
+
- spec/e2e/core/spec/spec_helper.rb
|
253
|
+
- spec/e2e/core/spec/unit/core_spec.rb
|
254
|
+
- spec/e2e/core_config_spec.rb
|
255
|
+
- spec/fixtures/config.yml
|
256
|
+
- spec/fixtures/empty.yml
|
257
|
+
- spec/spec_helper.rb
|
258
|
+
- spec/unit/clean_configuration_spec.rb
|
259
|
+
- spec/unit/configurable_spec.rb
|
260
|
+
- spec/unit/recursive_open_struct_spec.rb
|
261
|
+
has_rdoc:
|