greenpeace 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +111 -0
  3. data/lib/greenpeace/configuration/config.rb +102 -39
  4. data/lib/greenpeace/configuration/default.rb +48 -12
  5. data/lib/greenpeace/configuration/doc.rb +16 -13
  6. data/lib/greenpeace/configuration/key.rb +32 -27
  7. data/lib/greenpeace/configuration/option.rb +31 -21
  8. data/lib/greenpeace/configuration/requirement.rb +42 -18
  9. data/lib/greenpeace/configuration/type.rb +45 -40
  10. data/lib/greenpeace/environment.rb +4 -7
  11. data/lib/greenpeace/railtie.rb +9 -6
  12. data/lib/greenpeace/version.rb +2 -1
  13. data/lib/greenpeace.rb +67 -11
  14. data/spec/integration/simple_requirement_spec.rb +61 -0
  15. data/spec/spec_helper.rb +9 -0
  16. data/spec/unit/configuration/config_spec.rb +45 -0
  17. data/spec/unit/configuration/default_spec.rb +83 -0
  18. data/spec/unit/configuration/doc_spec.rb +40 -0
  19. data/spec/unit/configuration/key_spec.rb +54 -0
  20. data/spec/unit/configuration/option_spec.rb +45 -0
  21. data/spec/unit/configuration/requirement_spec.rb +85 -0
  22. data/spec/unit/configuration/type_spec.rb +96 -0
  23. data/spec/unit/environment_spec.rb +49 -0
  24. metadata +88 -76
  25. data/lib/greenpeace/configuration/environment.rb +0 -0
  26. data/test/dummy/Rakefile +0 -6
  27. data/test/dummy/app/assets/javascripts/application.js +0 -13
  28. data/test/dummy/app/assets/stylesheets/application.css +0 -15
  29. data/test/dummy/app/controllers/application_controller.rb +0 -5
  30. data/test/dummy/app/helpers/application_helper.rb +0 -2
  31. data/test/dummy/app/views/layouts/application.html.erb +0 -13
  32. data/test/dummy/bin/bundle +0 -3
  33. data/test/dummy/bin/rails +0 -4
  34. data/test/dummy/bin/rake +0 -4
  35. data/test/dummy/config/application.rb +0 -29
  36. data/test/dummy/config/boot.rb +0 -5
  37. data/test/dummy/config/environment.rb +0 -5
  38. data/test/dummy/config/environments/development.rb +0 -34
  39. data/test/dummy/config/environments/production.rb +0 -79
  40. data/test/dummy/config/environments/test.rb +0 -39
  41. data/test/dummy/config/greenpeace.rb +0 -6
  42. data/test/dummy/config/initializers/assets.rb +0 -8
  43. data/test/dummy/config/initializers/backtrace_silencers.rb +0 -7
  44. data/test/dummy/config/initializers/cookies_serializer.rb +0 -3
  45. data/test/dummy/config/initializers/filter_parameter_logging.rb +0 -4
  46. data/test/dummy/config/initializers/inflections.rb +0 -16
  47. data/test/dummy/config/initializers/mime_types.rb +0 -4
  48. data/test/dummy/config/initializers/session_store.rb +0 -3
  49. data/test/dummy/config/initializers/wrap_parameters.rb +0 -9
  50. data/test/dummy/config/locales/en.yml +0 -23
  51. data/test/dummy/config/routes.rb +0 -56
  52. data/test/dummy/config/secrets.yml +0 -22
  53. data/test/dummy/config.ru +0 -4
  54. data/test/dummy/public/404.html +0 -67
  55. data/test/dummy/public/422.html +0 -67
  56. data/test/dummy/public/500.html +0 -66
  57. data/test/dummy/public/favicon.ico +0 -0
@@ -1,22 +1,19 @@
1
1
  module Greenpeace
2
+ # Environment accessor object
2
3
  class Environment
3
4
  attr_reader :values
4
5
 
5
6
  def initialize(config)
6
7
  @values = {}
7
8
 
8
- config.requirements.each do |requirement|
9
- @values[requirement.identifier] = requirement.value
10
- end
11
-
12
- config.options.each do |option|
13
- @values[option.identifier] = option.value
9
+ config.settings.each do |setting|
10
+ @values[setting.identifier] = setting.value
14
11
  end
15
12
  end
16
13
 
17
14
  def method_missing(method)
18
15
  value = method.to_s
19
- if @values.has_key?(value)
16
+ if @values.key?(value)
20
17
  @values[value]
21
18
  else
22
19
  super
@@ -1,10 +1,13 @@
1
- module Greenpeace
2
- class Railtie < ::Rails::Railtie
3
- config.before_configuration do
4
- path = ::Rails.root.join("config", "greenpeace.rb")
1
+ if defined?(Rails)
2
+ module Greenpeace
3
+ # Railtie which hooks into the Rails initialization process to load the
4
+ # greenpeace configuration file and check for the environment before
5
+ # starting the rest of the application
6
+ class Railtie < ::Rails::Railtie
7
+ config.before_configuration do
8
+ path = ::Rails.root.join('config', 'greenpeace.rb')
5
9
 
6
- if File.exists?(path)
7
- require path
10
+ require path if File.exist?(path)
8
11
  end
9
12
  end
10
13
  end
@@ -1,3 +1,4 @@
1
+ #:nodoc:
1
2
  module Greenpeace
2
- VERSION = "0.0.2"
3
+ VERSION = '0.1.0'
3
4
  end
data/lib/greenpeace.rb CHANGED
@@ -1,16 +1,72 @@
1
- require "greenpeace/railtie" if defined?(Rails)
2
- require "greenpeace/configuration/config"
3
- require "greenpeace/environment"
1
+ require 'greenpeace/railtie'
2
+ require 'greenpeace/version'
3
+ require 'greenpeace/configuration/config'
4
+ require 'greenpeace/environment'
4
5
 
6
+ #
7
+ # = Greenpeace
8
+ #
9
+ # Greenpeace is an environment checker for validating the environment
10
+ # configuration values before starting your application. The Greenpeace module
11
+ # works as the only point of contact and API with users of the library, for
12
+ # both defining environment requirements and accessing the environment values
13
+ # on runtime.
14
+ #
15
+ # == Configuring requirements
16
+ #
17
+ # Before starting your application, you need to define what you need in your
18
+ # environment. To do this, you call the `configure` method, using the
19
+ # requirements API to define what is needed (called requirements in Greenpeace
20
+ # docs) and what may be provided (called options in Greenpeace docs):
21
+ #
22
+ # Greenpeace.configure do |env|
23
+ # # Here you define your environment values
24
+ # end
25
+ #
26
+ # You can also pass in an optional environment which represents the current
27
+ # runtime mode the application is running into. This is useful for defining
28
+ # runtime mode-specific defaults, such as default values which are applied only
29
+ # in development mode.
30
+ #
31
+ # Greenpeace.configure(ENV['RAILS_ENV']) do |env|
32
+ # # Here you define your environment values. Any defaults which you define
33
+ # # here that match with the runtime mode in the RAILS_ENV value will be
34
+ # # applied.
35
+ # end
36
+ #
37
+ # Check the grenpeace/configuration/config file for additional documentation on
38
+ # how the requirements and option API is used.
39
+ #
40
+ # == Accessing environment values
41
+ #
42
+ # You can access the environment values directly through the `Greenpeace.env`
43
+ # object. This will provide accessor methods according to what you defined in
44
+ # the configuration block above.
45
+ #
46
+ # For example, if you had a configuration block like the following:
47
+ #
48
+ # Greenpeace.configure do |env|
49
+ # env.requires :database_url
50
+ #
51
+ # env.requires :port, type: :int
52
+ # end
53
+ #
54
+ # Then you could access the following variables:
55
+ #
56
+ # Greenpeace.env.database_url
57
+ # Greenpeace.env.port
58
+ #
59
+ # The main advantage over using the standard `ENV` hash is that Greenpeace
60
+ # performs type conversion. In the previous example, the `Greenpeace.env.port`
61
+ # method returns an integer, not a string.
5
62
  module Greenpeace
6
- def self.configure
7
- configuration = Greenpeace::Configuration::Config.new
8
- yield configuration
9
- @@env = Greenpeace::Environment.new(configuration)
10
- end
63
+ class << self
64
+ attr_reader :env
11
65
 
12
- def self.env
13
- @@env
66
+ def configure(environment = 'production')
67
+ configuration = Greenpeace::Configuration::Config.new(environment)
68
+ yield configuration
69
+ @env = Greenpeace::Environment.new(configuration)
70
+ end
14
71
  end
15
72
  end
16
-
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace'
3
+
4
+ describe Greenpeace do
5
+ it 'allows the user to define a simple requirement' do
6
+ ENV['KEY'] = 'value'
7
+
8
+ Greenpeace.configure do |env|
9
+ env.requires :key
10
+ end
11
+
12
+ expect(Greenpeace.env.key).to eq('value')
13
+ end
14
+
15
+ it 'allows the user to define a simple option' do
16
+ ENV['KEY'] = 'value'
17
+
18
+ Greenpeace.configure do |env|
19
+ env.may_have :key
20
+ end
21
+
22
+ expect(Greenpeace.env.key).to eq('value')
23
+ end
24
+
25
+ it 'allows the user to define a defaulted simple option' do
26
+ ENV['KEY'] = ''
27
+
28
+ Greenpeace.configure do |env|
29
+ env.may_have :key, default: 'somevalue'
30
+ end
31
+
32
+ expect(Greenpeace.env.key).to eq('somevalue')
33
+ end
34
+
35
+ it 'allows the user to define a typed requirement' do
36
+ ENV['KEY'] = '10'
37
+
38
+ Greenpeace.configure do |env|
39
+ env.requires :key, type: :int
40
+ end
41
+
42
+ expect(Greenpeace.env.key).to eq(10)
43
+ end
44
+
45
+ it 'allows the user to define a documented requirement' do
46
+ ENV['KEY'] = ''
47
+
48
+ expect { Greenpeace.configure { |env| env.requires :key, doc: 'DOC' } }
49
+ .to raise_error(/DOC/)
50
+ end
51
+
52
+ it 'allows the user to define a environment-defaulted requirement' do
53
+ ENV['KEY'] = ''
54
+
55
+ Greenpeace.configure('development') do |env|
56
+ env.requires :key, defaults: { development: 'value' }
57
+ end
58
+
59
+ expect(Greenpeace.env.key).to eq('value')
60
+ end
61
+ end
@@ -0,0 +1,9 @@
1
+ require 'simplecov'
2
+
3
+ SimpleCov.start do
4
+ add_filter '/spec/'
5
+ end
6
+
7
+ def configure_env_value(value)
8
+ ENV['KEY'] = value
9
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/config'
3
+
4
+ describe Greenpeace::Configuration::Config do
5
+ describe '#requires' do
6
+ it 'adds a new setting' do
7
+ expect { subject.requires(:key) }
8
+ .to change { subject.settings.size }.from(0).to(1)
9
+ end
10
+
11
+ it 'adds a requirement' do
12
+ subject.requires(:key)
13
+
14
+ expect(subject.settings.first)
15
+ .to be_kind_of(Greenpeace::Configuration::Requirement)
16
+ end
17
+
18
+ it 'disallows duplicating keys' do
19
+ subject.requires(:key)
20
+
21
+ expect { subject.requires(:key) }.to raise_error
22
+ end
23
+ end
24
+
25
+ describe '#may_have' do
26
+ it 'adds a new setting' do
27
+ expect { subject.may_have(:key) }
28
+ .to change { subject.settings.size }.from(0).to(1)
29
+ end
30
+
31
+ it 'adds a requirement' do
32
+ subject.may_have(:key)
33
+
34
+ expect(subject.settings.first)
35
+ .to be_kind_of(Greenpeace::Configuration::Option)
36
+ end
37
+
38
+ it 'disallows duplicating keys' do
39
+ subject.may_have(:key)
40
+
41
+ expect { subject.may_have(:key) }.to raise_error
42
+ end
43
+ end
44
+
45
+ end
@@ -0,0 +1,83 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/default'
3
+
4
+ describe Greenpeace::Configuration::Default do
5
+ let(:test_class) { Greenpeace::Configuration::Default }
6
+ let(:type) { double('type') }
7
+
8
+ describe '#initialize' do
9
+ context 'when no default is provided' do
10
+ subject { test_class.new(type, {}, :a, :as) }
11
+
12
+ it 'provides a default nil value' do
13
+ expect(subject.value('development')).to be_nil
14
+ end
15
+ end
16
+
17
+ context 'when a valid value is provided directly' do
18
+ subject { test_class.new(type, { a: 'a' }, :a, :as) }
19
+
20
+ it 'provides the value in the entry' do
21
+ allow(type).to receive(:valid_value?).and_return(true)
22
+
23
+ expect(subject.value('development')).to eq('a')
24
+ end
25
+ end
26
+
27
+ context 'when an invalid value is provided directly' do
28
+ subject { test_class.new(type, { a: 'a' }, :a) }
29
+
30
+ it 'raises an error' do
31
+ allow(type).to receive(:valid_value?).and_return(false)
32
+
33
+ expect { subject.value('development') }.to raise_error
34
+ end
35
+ end
36
+
37
+ context 'when a valid value is provided for an environment' do
38
+ subject { test_class.new(type, { as: { development: 'a' } }, :a, :as) }
39
+
40
+ before(:each) { allow(type).to receive(:valid_value?).and_return(true) }
41
+
42
+ it 'provides the value for the environment' do
43
+ expect(subject.value('development')).to eq('a')
44
+ end
45
+
46
+ it 'provides the value for the environment as a symbol' do
47
+ expect(subject.value(:development)).to eq('a')
48
+ end
49
+
50
+ it 'provides a default nil value for other environments' do
51
+ expect(subject.value('production')).to be_nil
52
+ end
53
+ end
54
+
55
+ context 'when an invalid value is provided for an environment' do
56
+ subject { test_class.new(type, { as: { development: 'a' } }, :a, :as) }
57
+
58
+ it 'raises an error' do
59
+ allow(type).to receive(:valid_value?).and_return(false)
60
+
61
+ expect { subject.value }.to raise_error
62
+ end
63
+ end
64
+ end
65
+
66
+ describe '#environment_value?' do
67
+ subject { test_class.new(type, { as: { development: 'a' } }, :a, :as) }
68
+
69
+ before(:each) { allow(type).to receive(:valid_value?).and_return(true) }
70
+
71
+ it 'returns true for the environment which has a value' do
72
+ expect(subject).to be_environment_value('development')
73
+ end
74
+
75
+ it 'returns true for the environment which has a value as a symbol' do
76
+ expect(subject).to be_environment_value(:development)
77
+ end
78
+
79
+ it 'returns false for other environments do' do
80
+ expect(subject).not_to be_environment_value('production')
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/doc'
3
+
4
+ describe Greenpeace::Configuration::Doc do
5
+ let(:test_class) { Greenpeace::Configuration::Doc }
6
+
7
+ describe '#initialize' do
8
+ context 'when no doc string is provided' do
9
+ subject { test_class.new({}, :a) }
10
+
11
+ it 'provides an "Undefined" documentation' do
12
+ expect(subject.to_s).to eq('Undefined')
13
+ end
14
+ end
15
+
16
+ context 'when a nil doc string is provided' do
17
+ subject { test_class.new({ a: nil }, :a) }
18
+
19
+ it 'raises an error' do
20
+ expect { subject }.to raise_error
21
+ end
22
+ end
23
+
24
+ context 'when a non-string doc is provided' do
25
+ subject { test_class.new({ a: 1 }, :a) }
26
+
27
+ it 'raises an error' do
28
+ expect { subject }.to raise_error
29
+ end
30
+ end
31
+
32
+ context 'when a valid string doc is provided' do
33
+ subject { test_class.new({ a: 'a' }, :a) }
34
+
35
+ it 'provides the given string doc' do
36
+ expect(subject.to_s).to eq('a')
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/key'
3
+
4
+ describe Greenpeace::Configuration::Key do
5
+ let(:test_class) { Greenpeace::Configuration::Key }
6
+
7
+ describe '#initialize' do
8
+ context 'when a nil key is provided' do
9
+ subject { test_class.new(nil) }
10
+
11
+ it 'raises an error' do
12
+ expect { subject }.to raise_error
13
+ end
14
+ end
15
+
16
+ context 'when a non-symbol key is provided' do
17
+ subject { test_class.new('a') }
18
+
19
+ it 'raises an error' do
20
+ expect { subject }.to raise_error
21
+ end
22
+ end
23
+ end
24
+
25
+ subject { test_class.new(:a) }
26
+
27
+ describe '#==' do
28
+ it 'returns true for equal instances' do
29
+ expect(subject).to eq(test_class.new(:a))
30
+ end
31
+
32
+ it 'returns false for different instances' do
33
+ expect(subject).not_to eq(test_class.new(:b))
34
+ end
35
+ end
36
+
37
+ describe '#to_s' do
38
+ it 'returns the key' do
39
+ expect(subject.to_s).to eq('a')
40
+ end
41
+ end
42
+
43
+ describe '#identifier' do
44
+ it 'returns the downcased key' do
45
+ expect(subject.identifier).to eq('a')
46
+ end
47
+ end
48
+
49
+ describe '#env_identifier' do
50
+ it 'returns the upcased key' do
51
+ expect(subject.env_identifier).to eq('A')
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,45 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/option'
3
+
4
+ describe Greenpeace::Configuration::Option do
5
+ subject do
6
+ Greenpeace::Configuration::Option.new(
7
+ :key,
8
+ { type: :int, doc: 'DOC', default: 5 },
9
+ 'development')
10
+ end
11
+
12
+ describe '#identifier' do
13
+ it 'returns the stringified key' do
14
+ expect(subject.identifier).to eq('key')
15
+ end
16
+ end
17
+
18
+ describe '#value' do
19
+ context 'when an empty value is in the ENV' do
20
+ before(:each) { configure_env_value '' }
21
+
22
+ it 'returns the default value' do
23
+ expect(subject.value).to eq(5)
24
+ end
25
+ end
26
+
27
+ context 'when a nil value is in the ENV' do
28
+ before(:each) { configure_env_value nil }
29
+
30
+ it 'returns the default value' do
31
+ expect(subject.value).to eq(5)
32
+ end
33
+ end
34
+
35
+ context 'when a valid value is in the ENV' do
36
+ before(:each) { configure_env_value '10' }
37
+
38
+ it 'returns the value' do
39
+ expect(subject.value).to eq(10)
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ end
@@ -0,0 +1,85 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/requirement'
3
+
4
+ describe Greenpeace::Configuration::Requirement do
5
+ subject do
6
+ Greenpeace::Configuration::Requirement.new(
7
+ :key,
8
+ { type: :int, doc: 'DOC', defaults: { development: 5 } },
9
+ 'development')
10
+ end
11
+
12
+ describe '#identifier' do
13
+ it 'returns the stringified key' do
14
+ expect(subject.identifier).to eq('key')
15
+ end
16
+ end
17
+
18
+ describe '#value' do
19
+ context 'when the environment does not match the default' do
20
+ subject do
21
+ Greenpeace::Configuration::Requirement.new(
22
+ :key,
23
+ { type: :int, doc: 'DOC', defaults: { development: 5 } },
24
+ 'production')
25
+ end
26
+
27
+ context 'when an empty value is in the ENV' do
28
+ before(:each) { configure_env_value '' }
29
+
30
+ it 'raises an error' do
31
+ expect { subject.value }.to raise_error
32
+ end
33
+ end
34
+
35
+ context 'when a nil value is in the ENV' do
36
+ before(:each) { configure_env_value nil }
37
+
38
+ it 'raises an error' do
39
+ expect { subject.value }.to raise_error
40
+ end
41
+ end
42
+
43
+ context 'when a valid value is in the ENV' do
44
+ before(:each) { configure_env_value '10' }
45
+
46
+ it 'returns the value' do
47
+ expect(subject.value).to eq(10)
48
+ end
49
+ end
50
+ end
51
+
52
+ context 'when the environment matches the default' do
53
+ subject do
54
+ Greenpeace::Configuration::Requirement.new(
55
+ :key,
56
+ { type: :int, doc: 'DOC', defaults: { development: 5 } },
57
+ 'development')
58
+ end
59
+
60
+ context 'when an empty value is in the ENV' do
61
+ before(:each) { configure_env_value '' }
62
+
63
+ it 'returns the default value' do
64
+ expect(subject.value).to eq(5)
65
+ end
66
+ end
67
+
68
+ context 'when a nil value is in the ENV' do
69
+ before(:each) { configure_env_value nil }
70
+
71
+ it 'returns the default value' do
72
+ expect(subject.value).to eq(5)
73
+ end
74
+ end
75
+
76
+ context 'when a valid value is in the ENV' do
77
+ before(:each) { configure_env_value '10' }
78
+
79
+ it 'returns the value' do
80
+ expect(subject.value).to eq(10)
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'greenpeace/configuration/type'
3
+
4
+ describe Greenpeace::Configuration::Type do
5
+ let(:test_class) { Greenpeace::Configuration::Type }
6
+
7
+ describe '#initialize' do
8
+ context 'when no type is provided' do
9
+ subject { test_class.new({}, :a) }
10
+
11
+ it 'provides a default string type' do
12
+ expect(subject.to_s).to eq('string')
13
+ end
14
+ end
15
+
16
+ context 'when a nil type is provided' do
17
+ subject { test_class.new({ a: nil }, :a) }
18
+
19
+ it 'raises an error' do
20
+ expect { subject }.to raise_error
21
+ end
22
+ end
23
+
24
+ context 'when a non-symbol type is provided' do
25
+ subject { test_class.new({ a: 'string' }, :a) }
26
+
27
+ it 'raises an error' do
28
+ expect { subject }.to raise_error
29
+ end
30
+ end
31
+
32
+ context 'when an invalid type is provided' do
33
+ subject { test_class.new({ a: :invalid }, :a) }
34
+
35
+ it 'raises an error' do
36
+ expect { subject }.to raise_error
37
+ end
38
+ end
39
+ end
40
+
41
+ context 'for the string type' do
42
+ subject { test_class.new({ a: :string }, :a) }
43
+
44
+ describe '#valid_value?' do
45
+ it 'returns true for any string' do
46
+ expect(subject).to be_valid_value('anything')
47
+ end
48
+
49
+ it 'returns true for nil' do
50
+ expect(subject).to be_valid_value(nil)
51
+ end
52
+ end
53
+
54
+ describe '#convert' do
55
+ it 'converts the string to itself' do
56
+ expect(subject.convert('anything')).to eq('anything')
57
+ end
58
+ end
59
+
60
+ describe '#to_s' do
61
+ it 'returns string' do
62
+ expect(subject.to_s).to eq('string')
63
+ end
64
+ end
65
+ end
66
+
67
+ context 'for the int type' do
68
+ subject { test_class.new({ a: :int }, :a) }
69
+
70
+ describe '#valid_value?' do
71
+ it 'returns false for any non-number' do
72
+ expect(subject).not_to be_valid_value('a50')
73
+ end
74
+
75
+ it 'returns true for any number' do
76
+ expect(subject).to be_valid_value(50)
77
+ end
78
+ end
79
+
80
+ describe '#convert' do
81
+ it 'converts the string to a number' do
82
+ expect(subject.convert('50')).to eq(50)
83
+ end
84
+
85
+ it 'raises an error if the string is not a number' do
86
+ expect { subject.convert('a50') }.to raise_error
87
+ end
88
+ end
89
+
90
+ describe '#to_s' do
91
+ it 'returns int' do
92
+ expect(subject.to_s).to eq('int')
93
+ end
94
+ end
95
+ end
96
+ end