clean_config 0.0.2
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 +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:
|