dc-settingslogic 2.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.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 3b99784f5ea316afb0a97ad07755540a89bf0e55
4
+ data.tar.gz: ccdfb941953d43fa57d70236807ab6fa5f548f92
5
+ SHA512:
6
+ metadata.gz: c04822d02195eb8c005167b8a7cb0630060c0413ee6b686ad918da5e5bdcbf099f9b6bbb72ab39057a1966286e175da50df05bf20227dafbc5ce151ca669417f
7
+ data.tar.gz: 4733c6ddca69d39aa9434e20cdbcd07bfefb94e16efddb07aeb608b484f69eb1584bef0d5a040321be400e42050995ee0d22d2d92668e1ccee3e7c04e5a75867
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ .DS_Store
2
+ *.log
3
+ *.sqlite3
4
+ pkg/*
5
+ coverage/*
6
+ doc/*
7
+ benchmarks/*
8
+ .bundle
9
+ vendor/bundle
10
+ .rvmrc
11
+ .ruby-version
12
+ .ruby-gemset
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,30 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ dc-settingslogic (2.1.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ diff-lcs (1.2.5)
10
+ rake (10.3.2)
11
+ rspec (3.0.0)
12
+ rspec-core (~> 3.0.0)
13
+ rspec-expectations (~> 3.0.0)
14
+ rspec-mocks (~> 3.0.0)
15
+ rspec-core (3.0.2)
16
+ rspec-support (~> 3.0.0)
17
+ rspec-expectations (3.0.2)
18
+ diff-lcs (>= 1.2.0, < 2.0)
19
+ rspec-support (~> 3.0.0)
20
+ rspec-mocks (3.0.2)
21
+ rspec-support (~> 3.0.0)
22
+ rspec-support (3.0.2)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ dc-settingslogic!
29
+ rake
30
+ rspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 Ben Johnson of Binary Logic (binarylogic.com)
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.rdoc ADDED
@@ -0,0 +1,157 @@
1
+ = Settingslogic
2
+
3
+ Settingslogic is a simple configuration / settings solution that uses an ERB enabled YAML file. It has been great for
4
+ our apps, maybe you will enjoy it too. Settingslogic works with Rails, Sinatra, or any Ruby project.
5
+
6
+ == Helpful links
7
+
8
+ * <b>Documentation:</b> http://rdoc.info/projects/binarylogic/settingslogic
9
+ * <b>Repository:</b> http://github.com/binarylogic/settingslogic/tree/master
10
+ * <b>Issues:</b> http://github.com/binarylogic/settingslogic/issues
11
+
12
+ == Installation
13
+
14
+ gem install settingslogic
15
+
16
+ == Usage
17
+
18
+ === 1. Define your class
19
+
20
+ Instead of defining a Settings constant for you, that task is left to you. Simply create a class in your application
21
+ that looks like:
22
+
23
+ class Settings < Settingslogic
24
+ source "#{Rails.root}/config/application.yml"
25
+ namespace Rails.env
26
+ end
27
+
28
+ Name it Settings, name it Config, name it whatever you want. Add as many or as few as you like. A good place to put
29
+ this file in a rails app is app/models/settings.rb
30
+
31
+ I felt adding a settings file in your app was more straightforward, less tricky, and more flexible.
32
+
33
+ === 2. Create your settings
34
+
35
+ Notice above we specified an absolute path to our settings file called "application.yml". This is just a typical YAML file.
36
+ Also notice above that we specified a namespace for our environment. A namespace is just an optional string that corresponds
37
+ to a key in the YAML file.
38
+
39
+ Using a namespace allows us to change our configuration depending on our environment:
40
+
41
+ # config/application.yml
42
+ defaults: &defaults
43
+ cool:
44
+ saweet: nested settings
45
+ neat_setting: 24
46
+ awesome_setting: <%= "Did you know 5 + 5 = #{5 + 5}?" %>
47
+
48
+ development:
49
+ <<: *defaults
50
+ neat_setting: 800
51
+
52
+ test:
53
+ <<: *defaults
54
+
55
+ production:
56
+ <<: *defaults
57
+
58
+ _Note_: Certain Ruby/Bundler versions include a version of the Psych YAML parser which incorrectly handles merges (the `<<` in the example above.)
59
+ If your default settings seem to be overwriting your environment-specific settings, including the following lines in your config/boot.rb file may solve the problem:
60
+
61
+ require 'yaml'
62
+ YAML::ENGINE.yamler= 'syck'
63
+
64
+ === 3. Access your settings
65
+
66
+ >> Rails.env
67
+ => "development"
68
+
69
+ >> Settings.cool
70
+ => "#<Settingslogic::Settings ... >"
71
+
72
+ >> Settings.cool.saweet
73
+ => "nested settings"
74
+
75
+ >> Settings.neat_setting
76
+ => 800
77
+
78
+ >> Settings.awesome_setting
79
+ => "Did you know 5 + 5 = 10?"
80
+
81
+ You can use these settings anywhere, for example in a model:
82
+
83
+ class Post < ActiveRecord::Base
84
+ self.per_page = Settings.pagination.posts_per_page
85
+ end
86
+
87
+ === 4. Optional / dynamic settings
88
+
89
+ Often, you will want to handle defaults in your application logic itself, to reduce the number of settings
90
+ you need to put in your YAML file. You can access an optional setting by using Hash notation:
91
+
92
+ >> Settings.messaging.queue_name
93
+ => Exception: Missing setting 'queue_name' in 'message' section in 'application.yml'
94
+
95
+ >> Settings.messaging['queue_name']
96
+ => nil
97
+
98
+ >> Settings.messaging['queue_name'] ||= 'user_mail'
99
+ => "user_mail"
100
+
101
+ >> Settings.messaging.queue_name
102
+ => "user_mail"
103
+
104
+ Modifying our model example:
105
+
106
+ class Post < ActiveRecord::Base
107
+ self.per_page = Settings.posts['per_page'] || Settings.pagination.per_page
108
+ end
109
+
110
+ This would allow you to specify a custom value for per_page just for posts, or
111
+ to fall back to your default value if not specified.
112
+
113
+ === 5. Suppressing Exceptions Conditionally
114
+
115
+ Raising exceptions for missing settings helps highlight configuration problems. However, in a
116
+ Rails app it may make sense to suppress this in production and return nil for missing settings.
117
+ While it's useful to stop and highlight an error in development or test environments, this is
118
+ often not the right answer for production.
119
+
120
+ class Settings < Settingslogic
121
+ source "#{Rails.root}/config/application.yml"
122
+ namespace Rails.env
123
+ suppress_errors Rails.env.production?
124
+ end
125
+
126
+ >> Settings.non_existent_key
127
+ => nil
128
+
129
+ == Note on Sinatra / Capistrano / Vlad
130
+
131
+ Each of these frameworks uses a +set+ convention for settings, which actually defines methods
132
+ in the global Object namespace:
133
+
134
+ set :application, "myapp" # does "def application" globally
135
+
136
+ This can cause collisions with Settingslogic, since those methods are global. Luckily, the
137
+ solution is to just add a call to load! in your class:
138
+
139
+ class Settings < Settingslogic
140
+ source "#{Rails.root}/config/application.yml"
141
+ namespace Rails.env
142
+ load!
143
+ end
144
+
145
+ It's probably always safest to add load! to your class, since this guarantees settings will be
146
+ loaded at that time, rather than lazily later via method_missing.
147
+
148
+ Finally, you can reload all your settings later as well:
149
+
150
+ Settings.reload!
151
+
152
+ This is useful if you want to support changing your settings YAML without restarting your app.
153
+
154
+ == Author
155
+
156
+ Copyright (c) 2008-2010 {Ben Johnson}[http://github.com/binarylogic] of {Binary Logic}[http://www.binarylogic.com],
157
+ released under the MIT license. Support for optional settings and reloading by {Nate Wiger}[http://nate.wiger.org].
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new
6
+
7
+ task :default => :spec
@@ -0,0 +1,196 @@
1
+ require "yaml"
2
+ require "erb"
3
+ require 'open-uri'
4
+
5
+ # A simple settings solution using a YAML file. See README for more information.
6
+ class Settingslogic < Hash
7
+ class MissingSetting < StandardError; end
8
+
9
+ class << self
10
+ def name # :nodoc:
11
+ self.superclass != Hash && instance.key?("name") ? instance.name : super
12
+ end
13
+
14
+ # Enables Settings.get('nested.key.name') for dynamic access
15
+ def get(key)
16
+ parts = key.split('.')
17
+ curs = self
18
+ while p = parts.shift
19
+ curs = curs.send(p)
20
+ end
21
+ curs
22
+ end
23
+
24
+ def source(value = nil)
25
+ @source ||= []
26
+ @source << value
27
+ end
28
+
29
+ def namespace(value = nil)
30
+ @namespace ||= value
31
+ end
32
+
33
+ def suppress_errors(value = nil)
34
+ @suppress_errors ||= value
35
+ end
36
+
37
+ def [](key)
38
+ instance.fetch(key.to_s, nil)
39
+ end
40
+
41
+ def []=(key, val)
42
+ # Setting[:key][:key2] = 'value' for dynamic settings
43
+ val = new(val, source) if val.is_a? Hash
44
+ instance.store(key.to_s, val)
45
+ instance.create_accessor_for(key, val)
46
+ end
47
+
48
+ def load!
49
+ instance
50
+ true
51
+ end
52
+
53
+ def reload!
54
+ @instance = nil
55
+ load!
56
+ end
57
+
58
+ private
59
+ def instance
60
+ return @instance if @instance
61
+ @instance = new
62
+ create_accessors!
63
+ @instance
64
+ end
65
+
66
+ def method_missing(name, *args, &block)
67
+ instance.send(name, *args, &block)
68
+ end
69
+
70
+ # It would be great to DRY this up somehow, someday, but it's difficult because
71
+ # of the singleton pattern. Basically this proxies Setting.foo to Setting.instance.foo
72
+ def create_accessors!
73
+ instance.each do |key,val|
74
+ create_accessor_for(key)
75
+ end
76
+ end
77
+
78
+ def create_accessor_for(key)
79
+ return unless key.to_s =~ /^\w+$/ # could have "some-setting:" which blows up eval
80
+ instance_eval "def #{key}; instance.send(:#{key}); end"
81
+ end
82
+
83
+ end
84
+
85
+ # Initializes a new settings object. You can initialize an object in any of the following ways:
86
+ #
87
+ # Settings.new(:application) # will look for config/application.yml
88
+ # Settings.new("application.yaml") # will look for application.yaml
89
+ # Settings.new("/var/configs/application.yml") # will look for /var/configs/application.yml
90
+ # Settings.new(:config1 => 1, :config2 => 2)
91
+ #
92
+ # Basically if you pass a symbol it will look for that file in the configs directory of your rails app,
93
+ # if you are using this in rails. If you pass a string it should be an absolute path to your settings file.
94
+ # Then you can pass a hash, and it just allows you to access the hash via methods.
95
+ def initialize(hash_or_file = self.class.source, section = nil)
96
+ #puts "new! #{hash_or_file}"
97
+ case hash_or_file
98
+ when nil
99
+ raise Errno::ENOENT, "No file specified as Settingslogic source"
100
+ when Hash
101
+ self.replace hash_or_file
102
+ else
103
+ hash = {}
104
+ files = hash_or_file.reject { |file| file.nil? }
105
+ files.each do |file|
106
+ next unless File.exist? file
107
+
108
+ file_contents = open(file).read
109
+ single_hash = file_contents.empty? ? {} : YAML.load(ERB.new(file_contents).result).to_hash
110
+ hash.merge! single_hash
111
+ end
112
+ if self.class.namespace
113
+ hash = hash[self.class.namespace] or return missing_key("Missing setting '#{self.class.namespace}' in #{files.join(', ')}")
114
+ end
115
+ self.replace hash
116
+ end
117
+ @section = section || self.class.source.reject { |file| file.nil? }.join(', ') # so end of error says "in application.yml"
118
+ create_accessors!
119
+ end
120
+
121
+ # Called for dynamically-defined keys, and also the first key deferenced at the top-level, if load! is not used.
122
+ # Otherwise, create_accessors! (called by new) will have created actual methods for each key.
123
+ def method_missing(name, *args, &block)
124
+ key = name.to_s
125
+ return missing_key("Missing setting '#{key}' in #{@section}") unless has_key? key
126
+ value = fetch(key)
127
+ create_accessor_for(key)
128
+ value.is_a?(Hash) ? self.class.new(value, "'#{key}' section in #{@section}") : value
129
+ end
130
+
131
+ def [](key)
132
+ fetch(key.to_s, nil)
133
+ end
134
+
135
+ def []=(key,val)
136
+ # Setting[:key][:key2] = 'value' for dynamic settings
137
+ val = self.class.new(val, @section) if val.is_a? Hash
138
+ store(key.to_s, val)
139
+ create_accessor_for(key, val)
140
+ end
141
+
142
+ # Returns an instance of a Hash object
143
+ def to_hash
144
+ Hash[self]
145
+ end
146
+
147
+ # This handles naming collisions with Sinatra/Vlad/Capistrano. Since these use a set()
148
+ # helper that defines methods in Object, ANY method_missing ANYWHERE picks up the Vlad/Sinatra
149
+ # settings! So settings.deploy_to title actually calls Object.deploy_to (from set :deploy_to, "host"),
150
+ # rather than the app_yml['deploy_to'] hash. Jeezus.
151
+ def create_accessors!
152
+ self.each do |key,val|
153
+ create_accessor_for(key)
154
+ end
155
+ end
156
+
157
+ # Use instance_eval/class_eval because they're actually more efficient than define_method{}
158
+ # http://stackoverflow.com/questions/185947/ruby-definemethod-vs-def
159
+ # http://bmorearty.wordpress.com/2009/01/09/fun-with-rubys-instance_eval-and-class_eval/
160
+ def create_accessor_for(key, val=nil)
161
+ return unless key.to_s =~ /^\w+$/ # could have "some-setting:" which blows up eval
162
+ instance_variable_set("@#{key}", val)
163
+ self.class.class_eval <<-EndEval
164
+ def #{key}
165
+ return @#{key} if @#{key}
166
+ return missing_key("Missing setting '#{key}' in #{@section}") unless has_key? '#{key}'
167
+ value = fetch('#{key}')
168
+ @#{key} = if value.is_a?(Hash)
169
+ self.class.new(value, "'#{key}' section in #{@section}")
170
+ elsif value.is_a?(Array) && value.all?{|v| v.is_a? Hash}
171
+ value.map{|v| self.class.new(v)}
172
+ else
173
+ value
174
+ end
175
+ end
176
+ EndEval
177
+ end
178
+
179
+ def symbolize_keys
180
+ inject({}) do |memo, tuple|
181
+ k = (tuple.first.to_sym rescue tuple.first) || tuple.first
182
+
183
+ v = k.is_a?(Symbol) ? send(k) : tuple.last # make sure the value is accessed the same way Settings.foo.bar works
184
+
185
+ memo[k] = v && v.respond_to?(:symbolize_keys) ? v.symbolize_keys : v #recurse for nested hashes
186
+
187
+ memo
188
+ end
189
+ end
190
+
191
+ def missing_key(msg)
192
+ return nil if self.class.suppress_errors
193
+
194
+ raise MissingSetting, msg
195
+ end
196
+ end
@@ -0,0 +1,21 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "dc-settingslogic"
6
+ s.version = "2.1.0"
7
+ s.platform = Gem::Platform::RUBY
8
+ s.authors = ["Ben Johnson", "Jeong, Jiung"]
9
+ s.email = ["bjohnson@binarylogic.com", "ethernuiel@sanultari.com"]
10
+ s.homepage = "http://github.com/sanultari/settingslogic"
11
+ s.summary = %q{A simple and straightforward settings solution that uses an ERB enabled YAML file and a singleton design pattern.}
12
+ s.description = %q{A simple and straightforward settings solution that uses an ERB enabled YAML file and a singleton design pattern.}
13
+
14
+ s.add_development_dependency 'rake'
15
+ s.add_development_dependency 'rspec'
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+ end
@@ -0,0 +1,4 @@
1
+ class MultiSourceConfig < Settingslogic
2
+ source "#{File.dirname(__FILE__)}/settings.yml"
3
+ source "#{File.dirname(__FILE__)}/override.yml"
4
+ end
data/spec/override.yml ADDED
@@ -0,0 +1,3 @@
1
+ setting2: 10
2
+
3
+ override: true
data/spec/settings.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Settings < Settingslogic
2
+ source "#{File.dirname(__FILE__)}/settings.yml"
3
+ end
4
+
5
+ class SettingsInst < Settingslogic
6
+ end
data/spec/settings.yml ADDED
@@ -0,0 +1,28 @@
1
+ setting1:
2
+ setting1_child: saweet
3
+ deep:
4
+ another: my value
5
+ child:
6
+ value: 2
7
+
8
+ setting2: 5
9
+ setting3: <%= 5 * 5 %>
10
+ name: test
11
+
12
+ language:
13
+ haskell:
14
+ paradigm: functional
15
+ smalltalk:
16
+ paradigm: object oriented
17
+
18
+ collides:
19
+ does: not
20
+ nested:
21
+ collides:
22
+ does: not either
23
+
24
+ array:
25
+ -
26
+ name: first
27
+ -
28
+ name: second
data/spec/settings2.rb ADDED
@@ -0,0 +1,4 @@
1
+ class Settings2 < Settingslogic
2
+ source "#{File.dirname(__FILE__)}/settings.yml"
3
+ namespace "setting1"
4
+ end
data/spec/settings3.rb ADDED
@@ -0,0 +1,4 @@
1
+ class Settings3 < Settingslogic
2
+ source "#{File.dirname(__FILE__)}/settings.yml"
3
+ load! # test of load
4
+ end
data/spec/settings4.rb ADDED
@@ -0,0 +1,4 @@
1
+ class Settings4 < Settingslogic
2
+ source "#{File.dirname(__FILE__)}/settings.yml"
3
+ suppress_errors true
4
+ end
@@ -0,0 +1,3 @@
1
+ class SettingsEmpty < Settingslogic
2
+ source "#{File.dirname(__FILE__)}/settings_empty.yml"
3
+ end
File without changes
@@ -0,0 +1,184 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/spec_helper")
2
+
3
+ describe "Settingslogic" do
4
+ it "should access settings" do
5
+ expect(Settings.setting2).to eq(5)
6
+ end
7
+
8
+ it "should access nested settings" do
9
+ expect(Settings.setting1.setting1_child).to eq("saweet")
10
+ end
11
+
12
+ it "should access settings in nested arrays" do
13
+ expect(Settings.array.first.name).to eq("first")
14
+ end
15
+
16
+ it "should access deep nested settings" do
17
+ expect(Settings.setting1.deep.another).to eq("my value")
18
+ end
19
+
20
+ it "should access extra deep nested settings" do
21
+ expect(Settings.setting1.deep.child.value).to eq(2)
22
+ end
23
+
24
+ it "should enable erb" do
25
+ expect(Settings.setting3).to eq(25)
26
+ end
27
+
28
+ it "should namespace settings" do
29
+ expect(Settings2.setting1_child).to eq("saweet")
30
+ expect(Settings2.deep.another).to eq("my value")
31
+ end
32
+
33
+ it "should return the namespace" do
34
+ expect(Settings.namespace).to be_nil
35
+ expect(Settings2.namespace).to eq('setting1')
36
+ end
37
+
38
+ it "should distinguish nested keys" do
39
+ expect(Settings.language.haskell.paradigm).to eq('functional')
40
+ expect(Settings.language.smalltalk.paradigm).to eq('object oriented')
41
+ end
42
+
43
+ it "should not collide with global methods" do
44
+ expect(Settings3.nested.collides.does).to eq('not either')
45
+ Settings3[:nested] = 'fooey'
46
+ expect(Settings3[:nested]).to eq('fooey')
47
+ expect(Settings3.nested).to eq('fooey')
48
+ expect(Settings3.collides.does).to eq('not')
49
+ end
50
+
51
+ it "should raise a helpful error message" do
52
+ expect { Settings.missing }.to raise_error(Settingslogic::MissingSetting, /Missing setting 'missing' in/)
53
+ expect { Settings.language.missing }.to raise_error(Settingslogic::MissingSetting, /Missing setting 'missing' in 'language' section/)
54
+ end
55
+
56
+ it "should handle optional / dynamic settings" do
57
+ expect { Settings.language.erlang }.to raise_error(Settingslogic::MissingSetting, /Missing setting 'erlang' in 'language' section/)
58
+
59
+ expect(Settings.language['erlang']).to be_nil
60
+ Settings.language['erlang'] = 5
61
+ expect(Settings.language['erlang']).to eq(5)
62
+
63
+ Settings.language['erlang'] = {'paradigm' => 'functional'}
64
+ expect(Settings.language.erlang.paradigm).to eq('functional')
65
+ expect(Settings).not_to respond_to :erlang
66
+
67
+ Settings.reload!
68
+ expect(Settings.language['erlang']).to be_nil
69
+
70
+ Settings.language[:erlang] ||= 5
71
+ expect(Settings.language[:erlang]).to eq(5)
72
+
73
+ Settings.language[:erlang] = {}
74
+ Settings.language[:erlang][:paradigm] = 'functional'
75
+ expect(Settings.language.erlang.paradigm).to eq('functional')
76
+
77
+ Settings[:toplevel] = '42'
78
+ expect(Settings.toplevel).to eq('42')
79
+ end
80
+
81
+ it "should raise an error on a nil source argument" do
82
+ class NoSource < Settingslogic; end
83
+
84
+ expect { NoSource.foo.bar }.to raise_error Settingslogic::MissingSetting
85
+ end
86
+
87
+ it "should allow suppressing errors" do
88
+ expect(Settings4.non_existent_key).to be_nil
89
+ end
90
+
91
+ # This one edge case currently does not pass, because it requires very
92
+ # esoteric code in order to make it pass. It was judged not worth fixing,
93
+ # as it introduces significant complexity for minor gain.
94
+ # it "should handle reloading top-level settings"
95
+ # Settings[:inspect] = 'yeah baby'
96
+ # Settings.inspect.should == 'yeah baby'
97
+ # Settings.reload!
98
+ # Settings.inspect.should == 'Settings'
99
+ # end
100
+
101
+ it "should handle oddly-named settings" do
102
+ Settings.language['some-dash-setting#'] = 'dashtastic'
103
+ expect(Settings.language['some-dash-setting#']).to eq('dashtastic')
104
+ end
105
+
106
+ it "should handle settings with nil value" do
107
+ Settings["flag"] = true
108
+ Settings["flag"] = nil
109
+ expect(Settings.flag).to be_nil
110
+ end
111
+
112
+ it "should handle settings with false value" do
113
+ Settings["flag"] = true
114
+ Settings["flag"] = false
115
+ expect(Settings.flag).to eq(false)
116
+ end
117
+
118
+ it "should support instance usage as well" do
119
+ settings = SettingsInst.new(Settings.source)
120
+ expect(settings.setting1.setting1_child).to eq("saweet")
121
+ end
122
+
123
+ it "should be able to get() a key with dot.notation" do
124
+ expect(Settings.get('setting1.setting1_child')).to eq("saweet")
125
+ expect(Settings.get('setting1.deep.another')).to eq("my value")
126
+ expect(Settings.get('setting1.deep.child.value')).to eq(2)
127
+ end
128
+
129
+ # If .name is not a property, delegate to superclass
130
+ it "should respond with Module.name" do
131
+ expect(Settings2.name).to eq("Settings2")
132
+ end
133
+
134
+ # If .name is called on Settingslogic itself, handle appropriately
135
+ # by delegating to Hash
136
+ it "should have the parent class always respond with Module.name" do
137
+ expect(Settingslogic.name).to eq('Settingslogic')
138
+ end
139
+
140
+ # If .name is a property, respond with that instead of delegating to superclass
141
+ it "should allow a name setting to be overriden" do
142
+ expect(Settings.name).to eq('test')
143
+ end
144
+
145
+ it "should allow symbolize_keys" do
146
+ Settings.reload!
147
+ result = Settings.language.haskell.symbolize_keys
148
+ expect(result).to be_a Hash
149
+ expect(result).to eq({:paradigm => "functional"})
150
+ end
151
+
152
+ it "should allow symbolize_keys on nested hashes" do
153
+ Settings.reload!
154
+ result = Settings.language.symbolize_keys
155
+ expect(result).to be_a Hash
156
+ expect(result).to eq({
157
+ :haskell => {:paradigm => "functional"},
158
+ :smalltalk => {:paradigm => "object oriented"}
159
+ })
160
+ end
161
+
162
+ it "should handle empty file" do
163
+ expect(SettingsEmpty.keys).to be_empty
164
+ end
165
+
166
+ # Put this test last or else call to .instance will load @instance,
167
+ # masking bugs.
168
+ it "should be a hash" do
169
+ expect(Settings.send(:instance)).to be_a Hash
170
+ end
171
+
172
+ it "should override configuration from multiple source" do
173
+ expect(MultiSourceConfig.setting2).to eq(10)
174
+ expect(MultiSourceConfig.override).to eq(true)
175
+ expect(MultiSourceConfig.name).to eq("test")
176
+ end
177
+
178
+ describe "#to_hash" do
179
+ it "should return a new instance of a Hash object" do
180
+ expect(Settings.to_hash).to be_a Hash
181
+ expect(Settings.to_hash.object_id).not_to eq(Settings.object_id)
182
+ end
183
+ end
184
+ end
@@ -0,0 +1,17 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ require 'rspec'
3
+ require 'settingslogic'
4
+ require_relative 'settings'
5
+ require_relative 'settings2'
6
+ require_relative 'settings3'
7
+ require_relative 'settings4'
8
+ require_relative 'multi_source_config'
9
+ require_relative 'settings_empty'
10
+
11
+ # Needed to test Settings3
12
+ Object.send :define_method, 'collides' do
13
+ 'collision'
14
+ end
15
+
16
+ RSpec.configure do |config|
17
+ end
metadata ADDED
@@ -0,0 +1,105 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dc-settingslogic
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Ben Johnson
8
+ - Jeong, Jiung
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-07-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rake
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rspec
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: A simple and straightforward settings solution that uses an ERB enabled
43
+ YAML file and a singleton design pattern.
44
+ email:
45
+ - bjohnson@binarylogic.com
46
+ - ethernuiel@sanultari.com
47
+ executables: []
48
+ extensions: []
49
+ extra_rdoc_files: []
50
+ files:
51
+ - ".gitignore"
52
+ - Gemfile
53
+ - Gemfile.lock
54
+ - LICENSE
55
+ - README.rdoc
56
+ - Rakefile
57
+ - lib/settingslogic.rb
58
+ - settingslogic.gemspec
59
+ - spec/multi_source_config.rb
60
+ - spec/override.yml
61
+ - spec/settings.rb
62
+ - spec/settings.yml
63
+ - spec/settings2.rb
64
+ - spec/settings3.rb
65
+ - spec/settings4.rb
66
+ - spec/settings_empty.rb
67
+ - spec/settings_empty.yml
68
+ - spec/settingslogic_spec.rb
69
+ - spec/spec_helper.rb
70
+ homepage: http://github.com/sanultari/settingslogic
71
+ licenses: []
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubyforge_project:
89
+ rubygems_version: 2.2.2
90
+ signing_key:
91
+ specification_version: 4
92
+ summary: A simple and straightforward settings solution that uses an ERB enabled YAML
93
+ file and a singleton design pattern.
94
+ test_files:
95
+ - spec/multi_source_config.rb
96
+ - spec/override.yml
97
+ - spec/settings.rb
98
+ - spec/settings.yml
99
+ - spec/settings2.rb
100
+ - spec/settings3.rb
101
+ - spec/settings4.rb
102
+ - spec/settings_empty.rb
103
+ - spec/settings_empty.yml
104
+ - spec/settingslogic_spec.rb
105
+ - spec/spec_helper.rb