has_configuration 0.2.2

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: 95d950812e279b6c249386d5daa7f8bf1ea8b610
4
+ data.tar.gz: 73a4c8ae615450b07d3d04f1ce19489b272f0870
5
+ SHA512:
6
+ metadata.gz: 77e674cf3d7418efde319a083aa03ba30b3f729d0e984979caad995f0e0807b45a2136427173f3d01f8921e19c3dc1848d565106230d4b68d0c4ea652c2b505c
7
+ data.tar.gz: 502ffce5cf4bd8d5b2a5c7d72b87565a7201b441e2db704057ad8bee97d0938b41f0c8b6eb9a5638a77bd98b56dc801b0a1a553acea098542a0ac39383dc586b
data/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Martin Spickermann
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in
11
+ all copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ THE SOFTWARE.
@@ -0,0 +1,90 @@
1
+ require 'active_support/core_ext/hash/indifferent_access'
2
+ require 'ostruct'
3
+
4
+ module HasConfiguration #:nodoc:all
5
+ class Configuration
6
+
7
+ def initialize(klass, options = {})
8
+ @class_name = klass.name
9
+ @options = options
10
+
11
+ load_file
12
+ init_hash
13
+ end
14
+
15
+ def to_h(type = nil)
16
+ case type
17
+ when :symbolized then deep_symbolized_hash
18
+ when :stringify then deep_stringified_hash
19
+ else @hash
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def method_missing(sym, *args, &block)
26
+ configuration.send(sym, *args, &block)
27
+ end
28
+
29
+ def load_file
30
+ @raw = YAML.load(ERB.new(raw_file(filename)).result)
31
+ end
32
+
33
+ def init_hash
34
+ @hash = (@raw || {}).with_indifferent_access
35
+ @hash = @hash[environment] if environment
36
+ end
37
+
38
+ def raw_file(filename)
39
+ File.read(filename)
40
+ end
41
+
42
+ def configuration
43
+ @configuration ||= deep_structify(@hash)
44
+ end
45
+
46
+ def filename
47
+ if @options[:file]
48
+ @options[:file]
49
+ elsif @class_name
50
+ filename = "#{@class_name.downcase}.yml"
51
+ defined?(Rails) ? Rails.root.join('config', filename).to_s : filename
52
+ else
53
+ raise ArgumentError, "Unable to resolve filename, please add :file parameter to has_configuration"
54
+ end
55
+ end
56
+
57
+ def environment
58
+ case
59
+ when @options.keys.include?(:env) then @options[:env]
60
+ when defined?(Rails) then Rails.env.to_s
61
+ end
62
+ end
63
+
64
+ def deep_structify(hash)
65
+ result = {}
66
+ hash.each do |key, value|
67
+ result[key] = value.is_a?(Hash) ? deep_structify(value) : value
68
+ end if hash
69
+ OpenStruct.new(result)
70
+ end
71
+
72
+ def deep_symbolized_hash
73
+ @deep_symbolized_hash ||= deep_transform_keys(@hash) { |key| key.to_sym rescue key }
74
+ end
75
+
76
+ def deep_stringified_hash
77
+ @deep_stringified_hash ||= deep_transform_keys(@hash) { |key| key.to_s }
78
+ end
79
+
80
+ # from Rails 4.0 (/active_support/core_ext/hash/keys.rb)
81
+ def deep_transform_keys(hash, &block)
82
+ result = {}
83
+ hash.each do |key, value|
84
+ result[yield(key)] = value.is_a?(Hash) ? deep_transform_keys(value, &block) : value
85
+ end if hash
86
+ result
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,99 @@
1
+ require 'has_configuration/configuration'
2
+
3
+ module HasConfiguration #:nodoc:
4
+
5
+ def self.included(base)
6
+ base.extend(ClassMethods)
7
+ end
8
+
9
+ module ClassMethods
10
+
11
+ # Load configuration settings from a yaml file and adds a class and an instance
12
+ # method +configuration+ to the object.
13
+ #
14
+ # ==== options
15
+ #
16
+ # [+file+] The yml file to load:
17
+ # Defaults to <tt>config/classname.yml</tt> if Rails is defined,
18
+ # <tt>classname.yml</tt> otherwise.
19
+ # [+env+] The environment to load from the file.
20
+ # Defaults to +Rails.env+ if Rails is defined, no default if not.
21
+ #
22
+ # ==== Integration Examples
23
+ #
24
+ # has_configuration
25
+ # # => loads setting without environment processing from the file #{self.class.name.downcase}.yml
26
+ #
27
+ # has_configuration :file => Rails.root.join('config', 'example.yml'), :env => 'staging'
28
+ # # => loads settings for staging environment from RAILS_ROOT/config/example.yml file
29
+ #
30
+ # ==== YAML File Example
31
+ #
32
+ # The yaml file may contain defaults. Nesting is not limited. ERB in the yaml
33
+ # file is evaluated.
34
+ #
35
+ # defaults: &defaults
36
+ # user: root
37
+ # some:
38
+ # nested: value
39
+ #
40
+ # development:
41
+ # <<: *defaults
42
+ # password: secret
43
+ #
44
+ # production:
45
+ # <<: *defaults
46
+ # password: <%= ENV[:secret] &>
47
+ #
48
+ # ==== Configuration Retrieval
49
+ #
50
+ # If the example above was loaded into a class +Foo+ in +production+ environment:
51
+ #
52
+ # Foo.configuration # => <HasConfiguration::Configuration:0x00...>
53
+ # foo.new.configuration # => <HasConfiguration::Configuration:0x00...>
54
+ #
55
+ # # convenient getter methods
56
+ # Foo.configuration.some.nested # => "value"
57
+ #
58
+ # # to_h returns a HashWithIndifferentAccess
59
+ # Foo.configuration.to_h # => { :user => "root", :password => "prod-secret"
60
+ # # :some => { :nested => "value" } }
61
+ # Foo.configuration.to_h[:some][:nested] # => "value"
62
+ # Foo.configuration.to_h[:some]['nested'] # => "value"
63
+ #
64
+ # # force a special key type (when merging with other hashes)
65
+ # Foo.configuration.to_h(:symbolized) # => { :user => "root", :password => "prod-secret"
66
+ # # :some => { :nested => "value" } }
67
+ # Foo.configuration.to_h(:stringify) # => { 'user' => "root", 'password' => "prod-secret"
68
+ # # 'some' => { 'nested' => "value" } }
69
+ #
70
+ def has_configuration(options = {})
71
+ @configuration = Configuration.new(self, options)
72
+ include Getter
73
+ end
74
+
75
+ module Getter #:nodoc:all
76
+
77
+ def self.included(base)
78
+ base.extend(ClassMethods)
79
+ end
80
+
81
+ module ClassMethods
82
+ def configuration
83
+ @configuration
84
+ end
85
+ end
86
+
87
+ def configuration
88
+ self.class.configuration
89
+ end
90
+
91
+ end
92
+
93
+ end
94
+
95
+ end
96
+
97
+ class Object #:nodoc:
98
+ include HasConfiguration
99
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,9 @@
1
+ module HasConfiguration #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 2
5
+ BUILD = 2
6
+
7
+ STRING = [MAJOR, MINOR, BUILD].join('.')
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ development:
2
+ env: development
3
+
4
+ production:
5
+ env: production
@@ -0,0 +1,6 @@
1
+ defaults: &defaults
2
+ default: default
3
+
4
+ development:
5
+ <<: *defaults
6
+ development: development
@@ -0,0 +1,2 @@
1
+ development:
2
+ erb: <%= Rails.env %>
@@ -0,0 +1,5 @@
1
+ development:
2
+ development: development
3
+ nested:
4
+ foo: bar
5
+ baz: true
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe HasConfiguration::Configuration do
4
+
5
+ let(:klass) { Class }
6
+
7
+ describe ".new" do
8
+
9
+ before { mock_file('spec/fixtures/class.yml') }
10
+
11
+ context "when no filename provided" do
12
+
13
+ let(:file) { "/RAILS_ROOT/config/class.yml" }
14
+
15
+ it "loads default file" do
16
+ expect_any_instance_of(Configuration).to receive(:raw_file).with(file)
17
+ HasConfiguration::Configuration.new(klass)
18
+ end
19
+
20
+ end
21
+
22
+ context "when filename provided" do
23
+
24
+ let(:file) { "foo/bar.yml" }
25
+
26
+ it "loads provided file" do
27
+ expect_any_instance_of(Configuration).to receive(:raw_file).with(file)
28
+ HasConfiguration::Configuration.new(klass, :file => file)
29
+ end
30
+
31
+ end
32
+
33
+ end
34
+
35
+ context "when initialized" do
36
+
37
+ context "environment" do
38
+
39
+ before { mock_file('spec/fixtures/class.yml') }
40
+
41
+ context "without env option" do
42
+
43
+ subject { HasConfiguration::Configuration.new(klass) }
44
+ its(:to_h) { should eq('env' => 'development') }
45
+
46
+ end
47
+
48
+ context "with env option" do
49
+
50
+ let(:environment) { 'production' }
51
+ subject { HasConfiguration::Configuration.new(klass, :env => environment) }
52
+ its(:to_h) { should eq('env' => environment) }
53
+
54
+ end
55
+
56
+ end
57
+
58
+ context "yaml defaults" do
59
+
60
+ before { mock_file('spec/fixtures/with_defaults.yml') }
61
+
62
+ subject { HasConfiguration::Configuration.new(klass) }
63
+ its(:to_h) { should eq('default' => 'default', 'development' => 'development') }
64
+
65
+ end
66
+
67
+ context "with erb" do
68
+
69
+ before { mock_file('spec/fixtures/with_erb.yml') }
70
+
71
+ subject { HasConfiguration::Configuration.new(klass) }
72
+ its(:to_h) { should eq('erb' => Rails.env) }
73
+
74
+ end
75
+
76
+ end
77
+
78
+ describe "#to_h" do
79
+
80
+ before { mock_file('spec/fixtures/with_nested_attributes.yml') }
81
+
82
+ context "#to_h" do
83
+ subject { HasConfiguration::Configuration.new(klass).to_h }
84
+ it { should be_a(HashWithIndifferentAccess) }
85
+ end
86
+
87
+ context "#to_h(:stringify)" do
88
+ subject { HasConfiguration::Configuration.new(klass).to_h(:stringify) }
89
+ it { should eq('development' => 'development', 'nested' => { 'foo' => 'bar', 'baz' => true }) }
90
+ end
91
+
92
+ context "#to_h(:symbolized)" do
93
+ subject { HasConfiguration::Configuration.new(klass).to_h(:symbolized) }
94
+ it { should eq(:development => 'development', :nested => { :foo => 'bar', :baz => true }) }
95
+ end
96
+
97
+ end
98
+
99
+ describe "struct methods" do
100
+
101
+ before { mock_file('spec/fixtures/with_nested_attributes.yml') }
102
+
103
+ let(:configuration) { HasConfiguration::Configuration.new(klass) }
104
+
105
+ it "is structified" do
106
+ expect(configuration.to_h[:development] ).to eql('development')
107
+ expect(configuration.development ).to eql('development')
108
+
109
+ expect(configuration.to_h[:nested]['foo'] ).to eql('bar')
110
+ expect(configuration.nested.foo ).to eql('bar')
111
+ end
112
+
113
+ end
114
+
115
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ describe HasConfiguration do
4
+
5
+ context "when declared" do
6
+
7
+ before(:all) do
8
+ Dummy = Class.new do
9
+ has_configuration :file => 'spec/fixtures/class.yml'
10
+ end
11
+ end
12
+
13
+ context "the class" do
14
+ subject { Dummy }
15
+ it { should respond_to(:configuration) }
16
+ its(:configuration) { should be }
17
+ end
18
+
19
+ context "an instance" do
20
+ subject { Dummy.new }
21
+ it { should respond_to(:configuration) }
22
+ its(:configuration) { should be }
23
+ end
24
+
25
+ end
26
+
27
+ end
@@ -0,0 +1,29 @@
1
+ require 'yaml'
2
+
3
+ require 'has_configuration'
4
+ require 'has_configuration/configuration'
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :rspec
8
+
9
+ config.expect_with :rspec do |c|
10
+ c.syntax = :expect
11
+ end
12
+ end
13
+
14
+ def mock_file(filename)
15
+ Configuration.any_instance.stub(:raw_file).and_return(File.read(filename))
16
+ end
17
+
18
+ # Mocks Rails Environment
19
+ Rails = Class.new do
20
+
21
+ def self.root
22
+ Pathname.new("/RAILS_ROOT")
23
+ end
24
+
25
+ def self.env
26
+ 'development'
27
+ end
28
+
29
+ end
metadata ADDED
@@ -0,0 +1,99 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: has_configuration
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.2
5
+ platform: ruby
6
+ authors:
7
+ - Martin Spickermann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-19 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: 2.3.5
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 2.3.5
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
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: rspec
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
+ description: Loads configuration setting from a yml file and adds a configuation method
56
+ to class and instances
57
+ email:
58
+ - spickermann@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - MIT-LICENSE
64
+ - lib/has_configuration/configuration.rb
65
+ - lib/has_configuration.rb
66
+ - lib/version.rb
67
+ - spec/fixtures/class.yml
68
+ - spec/fixtures/with_defaults.yml
69
+ - spec/fixtures/with_erb.yml
70
+ - spec/fixtures/with_nested_attributes.yml
71
+ - spec/has_configuration/configuration_spec.rb
72
+ - spec/has_configuration_spec.rb
73
+ - spec/spec_helper.rb
74
+ homepage: https://github.com/spickermann/has_configuration
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - '>='
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.0.14
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: Simple configuration handling
98
+ test_files: []
99
+ has_rdoc: