flexible-config 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 6ca26fc729ad030745058cbb8a429e8dcc673beb
4
+ data.tar.gz: 9d55e6bbc819b243a515e2064c54669113db26e9
5
+ SHA512:
6
+ metadata.gz: 4039b9ee15390d0813973f0651a4d9946949f36bada242ae60ab5ccb1b733a692cc384697258cc1f132cf0b6bf2c1fec090be1efd342c03e38540e73afa5adcb
7
+ data.tar.gz: 2e816cf6fd3d2bd5bcbdf0a49ff6005c24cb75dd635aaccc3e4a9e5a6b7372e7975393555c78f9053e871daad4cb63c199ce908176f3427188aa12d40b2ce542
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,14 @@
1
+ guard 'bundler' do
2
+ watch 'Gemfile'
3
+ watch /^.+\.gemspec/
4
+ end
5
+
6
+ guard(
7
+ :rspec, cmd: "bundle exec rspec", failed_mode: :keep,
8
+ all_after_pass: true, all_on_start: true
9
+ ) do
10
+ watch %r{^spec/.+_spec\.rb$}
11
+ watch %r{^spec/fixtures/.+\.rb$}
12
+ watch(%r{^lib/.+\.rb$}) { 'spec' }
13
+ watch('spec/spec_helper.rb') { 'spec' }
14
+ end
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011, 2012, 2013 by Grouper
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ [![Build Status](https://travis-ci.org/Grouper/flexible-config.png?branch=master)](https://travis-ci.org/Grouper/flexible-config)
2
+
3
+
4
+ FlexibleConfig
5
+ ==============
6
+
7
+ FlexibleConfig promotes good OOP design, and the separation of logic and
8
+ configuration in your Ruby classes.
9
+
10
+ FlexibleConfig allows you to set class constants cleanly in ruby with the
11
+ heirarchical structure and clean workflow of YML config, without sacrificing
12
+ the flexibility and immediacy of ENVironment variables.
13
+
14
+ ### Here is how your class constants could look like using FlexibleConfig:
15
+
16
+ ```ruby
17
+ module Bidding
18
+ class Calculator
19
+ FlexibleConfig.use 'auction.bidding' do |config|
20
+ BASE_RATE = config['base_rate']
21
+ TIME_DECAY = config['time_decay']
22
+ WIGGLE_ROOM = config['wiggle_room']
23
+ end
24
+ end
25
+ end
26
+ ```
27
+
28
+ Or the more safer, (but more verbose) syntax:
29
+
30
+ ```ruby
31
+ module Bidding
32
+ class Calculator
33
+ FlexibleConfig.use 'auction.bidding' do |cfg|
34
+ BIDDING_ENABLED = cfg.fetch('enabled') { true }
35
+ BIDDER_EMAIL = cfg.to_s('email_from')
36
+ BASE_RATE = cfg.to_f('base_rate') { 1.0 }
37
+ TIME_DECAY = cfg.to_f('time_decay') { 3.0 }
38
+ ATTEMPTS = cfg.to_i('wiggle_room') { 2 }
39
+ end
40
+ end
41
+ end
42
+ ```
43
+
44
+ ### Then config as follows:
45
+
46
+ #### In YAML:
47
+
48
+ `config/settings/auction.yml`
49
+
50
+ ```yml
51
+ default:
52
+ base_rate: 1.0
53
+ time_decay: 3.0
54
+ wiggle_room: 0.2
55
+
56
+ development:
57
+ wiggle_room: 0.6
58
+
59
+ production:
60
+ wiggle_room: 0.2
61
+ ```
62
+
63
+ #### Using ENV variables to override:
64
+
65
+ ```
66
+ AUCTION_BIDDING_BASE_RATE=1.0
67
+ AUCTION_BIDDING_TIME_DECAY=3.0
68
+ AUCTION_BIDDING_WIGGLE_ROOM=0.2
69
+ ```
70
+
71
+ #### Casting Booleans from ENV
72
+
73
+ If your ENV variable is equal to the string 'true' or 'false' then
74
+ using the default `#fetch` method on the config object will cast it to the
75
+ Ruby `TrueClass` or `FalseClass` automatically.
76
+
77
+ #### Casting of Other Types
78
+
79
+ Casting to any Ruby type will work as long as the Ruby object and its string
80
+ representation are safely interchangable:
81
+
82
+ ```
83
+ example.yml
84
+
85
+ default:
86
+ safe: '123'
87
+ unsafe: '123oops'
88
+ ```
89
+
90
+ ```ruby
91
+ FlexibleConfig.use 'example' do |cfg|
92
+ BASE_RATE = cfg.to_i('safe') # => 123
93
+ TIME_DECAY = cfg.to_i('unsafe') # => raises UnsafeConversion
94
+ end
95
+ ```
96
+
97
+ #### Viewing actual config variables in an environment
98
+
99
+ Add this to the `Rakefile` of your project:
100
+
101
+ ```
102
+ # Load flexible config tasks
103
+ spec = Gem::Specification.find_by_name 'flexible-config'
104
+ load "#{spec.gem_dir}/lib/tasks/flexible_config.rake"
105
+ ```
106
+
107
+ Type into the command line:
108
+ ```
109
+ bundle exec rake flexible_config:print
110
+ ```
111
+
112
+ - - - - -
113
+
114
+ ## Contributing
115
+
116
+ If you'd like to become a contributor, the easiest way it to fork this repo, make your changes, run the specs and submit a pull request once they pass.
117
+
118
+ To run specs, run `bundle install && bundle exec rspec`
119
+
120
+ If your changes seem reasonable and the specs pass I'll give you commit rights to this repo and add you to the list of people who can push the gem.
121
+
122
+
123
+ ## Copyright
124
+
125
+ Copyright (c) 2015 Grouper. See LICENSE for details.
@@ -0,0 +1,16 @@
1
+ require 'active_support'
2
+ require 'yaml'
3
+
4
+ module FlexibleConfig
5
+ module_function
6
+
7
+ def use(config_key = '', &block)
8
+ yield Builder.new config_key
9
+ end
10
+ end
11
+
12
+ require 'flexible_config/overview'
13
+ require 'flexible_config/not_found'
14
+ require 'flexible_config/builder'
15
+ require 'flexible_config/wrapped_env'
16
+ require 'flexible_config/wrapped_yaml'
@@ -0,0 +1,36 @@
1
+ module FlexibleConfig
2
+ UnsafeConversion = Class.new(RuntimeError)
3
+
4
+ class Builder
5
+ def initialize(base_key = '')
6
+ @base_key = base_key
7
+ end
8
+
9
+ def fetch(additional_key, default = nil)
10
+ key = "#{base_key}.#{additional_key}"
11
+ item = [WrappedEnv[key], WrappedYaml[key], default].detect { |i| !i.nil? }
12
+
13
+ return item unless item.nil?
14
+ return yield if block_given?
15
+
16
+ raise NotFound.new key
17
+ end
18
+ alias_method :[], :fetch
19
+
20
+ def method_missing(method, *args, &block)
21
+ value = fetch(*args, &block)
22
+ return super unless value.respond_to? method
23
+
24
+ result = value.send method
25
+
26
+ raise UnsafeConversion.new(
27
+ "Tried to convert #{value} to int #{result} but was deemed unsafe."
28
+ ) unless result.to_s == value.to_s
29
+
30
+ result
31
+ end
32
+
33
+ private
34
+ attr_reader :base_key
35
+ end
36
+ end
@@ -0,0 +1,22 @@
1
+ module FlexibleConfig
2
+ class NotFound < RuntimeError
3
+ def initialize(key = 'unknown.key')
4
+ super error_message_from key
5
+ end
6
+
7
+ private
8
+
9
+ def error_message_from(key)
10
+ file_base_name, *yml_keys = key.split '.'
11
+
12
+ env_var = key.upcase.gsub '.', '_'
13
+ environment = WrappedEnv.fetch('RAILS_ENV') { 'default' }
14
+ yml_key = "#{environment}.#{yml_keys.join '.'}"
15
+ file_name = "./config/settings/#{file_base_name}.yml"
16
+
17
+ "#{self.class} Exception. Configuration value not found. Consider " \
18
+ "setting the #{env_var} environment variable, or setting the " \
19
+ "#{yml_key} property in the following file: #{file_name}"
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ module FlexibleConfig
2
+ class Overview
3
+ def call
4
+ available_files.reduce({}) do |memo, i|
5
+ memo[i] = config_lines_for_file i
6
+ memo
7
+ end
8
+ end
9
+
10
+ def print
11
+ call.each do |key, value|
12
+ Kernel.puts "#===== #{key.upcase} (#{key}.yml) ====="
13
+ value.each { |v| Kernel.puts v }
14
+ Kernel.puts "\n"
15
+ end
16
+ end
17
+
18
+ private
19
+
20
+ def available_files
21
+ WrappedYaml.config_data.keys
22
+ end
23
+
24
+ def config_lines_for_file(category)
25
+ builder = FlexibleConfig::Builder.new category
26
+ keys = []
27
+
28
+ WrappedYaml.config_data[category].values.each do |env|
29
+ keys += flat_hash(env).keys
30
+ end
31
+
32
+ keys.uniq.sort.map do |keys|
33
+ value = begin
34
+ builder[keys.join '.']
35
+ rescue FlexibleConfig::NotFound => e
36
+ "### NO VALUE ###"
37
+ end
38
+
39
+ combined_keys = [category] + keys
40
+ dotted_key = keys.join '.'
41
+ env_key = combined_keys.map(&:upcase).join '_'
42
+ from_env = !WrappedEnv[env_key].nil? ? 'ENV OVERRIDE' : ''
43
+
44
+ sprintf("%-40s|%-12s| %-45s = %s",
45
+ dotted_key, from_env, env_key, value
46
+ )
47
+ end
48
+ end
49
+
50
+ def flat_hash(h, f = [], g = {})
51
+ return g.update(f => h) unless h.is_a? Hash
52
+ h.each { |k, r| flat_hash r, f+[k], g }
53
+ g
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,3 @@
1
+ module FlexibleConfig
2
+ VERSION = '1.1.0'
3
+ end
@@ -0,0 +1,55 @@
1
+ module FlexibleConfig
2
+ module WrappedEnv
3
+ class << self
4
+ def [](generic_key)
5
+ key = normalize_key generic_key
6
+ normalize(overrides.key?(key) ? overrides[key] : ENV[key])
7
+ end
8
+
9
+ def fetch(generic_key, &block)
10
+ key = normalize_key generic_key
11
+ return overrides[key] if overrides.key?(key)
12
+
13
+ normalize ENV.fetch(key, &block)
14
+ rescue KeyError => e
15
+ raise NotFound.new key
16
+ end
17
+
18
+ def int(generic_key, &block)
19
+ key = normalize_key generic_key
20
+ val = fetch(key)
21
+ return block.call if val.nil? && block_given?
22
+
23
+ raise NotFound.new if val.nil?
24
+ val.to_i
25
+ end
26
+
27
+ def normalize(val)
28
+ case val.to_s.downcase
29
+ when 'true' then true
30
+ when 'false' then false
31
+ when '' then nil
32
+ else val
33
+ end
34
+ end
35
+
36
+ def override(key, value)
37
+ overrides[key] = value
38
+ end
39
+
40
+ def reset
41
+ @overrides = {}
42
+ end
43
+
44
+ private
45
+
46
+ def overrides
47
+ @overrides ||= {}
48
+ end
49
+
50
+ def normalize_key(key)
51
+ key.upcase.gsub('.', '_')
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,39 @@
1
+ module FlexibleConfig
2
+ class WrappedYaml
3
+ CONFIG_PATH = "config/settings/**/*.yml"
4
+
5
+ class << self
6
+ def [](key)
7
+ environment_specific = get_config(key, env: app_environment)
8
+ environment_specific.nil? ? get_config(key) : environment_specific
9
+ end
10
+
11
+ def config_data
12
+ @config_data ||= Dir[CONFIG_PATH].reduce({}) do |memo, file|
13
+ category = File.basename(file, '.yml')
14
+ memo[category] = YAML.load File.open file
15
+ memo
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def get_config(key, env: 'default')
22
+ keys_with_injected_env = key.sub('.', ".#{env}.").split '.'
23
+
24
+ keys_with_injected_env.reduce(config_data) do |memo, i|
25
+ memo[i] unless memo.nil?
26
+ end
27
+ end
28
+
29
+ def app_environment
30
+ (
31
+ ENV['CONFIG_ENV'] ||
32
+ ENV['RAILS_ENV'] ||
33
+ ENV['RACK_ENV'] ||
34
+ 'development'
35
+ )
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,6 @@
1
+ namespace :flexible_config do
2
+ task :print do
3
+ require 'flexible-config'
4
+ FlexibleConfig::Overview.new.print
5
+ end
6
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flexible-config
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Brett Richardson
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-10-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: guard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: guard-rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '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'
83
+ - !ruby/object:Gem::Dependency
84
+ name: guard-bundler
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: growl
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: pry
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Use environment-specific YAML for configuration while allowing for ENV
126
+ variables to override
127
+ email:
128
+ - brett.richardson.nz@gmail.com
129
+ executables: []
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - Gemfile
134
+ - Guardfile
135
+ - MIT-LICENSE
136
+ - README.md
137
+ - lib/flexible-config.rb
138
+ - lib/flexible_config/builder.rb
139
+ - lib/flexible_config/not_found.rb
140
+ - lib/flexible_config/overview.rb
141
+ - lib/flexible_config/version.rb
142
+ - lib/flexible_config/wrapped_env.rb
143
+ - lib/flexible_config/wrapped_yaml.rb
144
+ - lib/tasks/flexible_config.rake
145
+ homepage: https://github.com/brett-richardson/flexible-config
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.5.1
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: Flexible Configuration for Ruby constants
169
+ test_files: []
170
+ has_rdoc: