greenpeace 0.0.2 → 0.1.0

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.
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