settings-tree 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --drb
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Add dependencies required to use your gem here.
4
+ # Example:
5
+ # gem "activesupport", ">= 2.3.5"
6
+
7
+ gem 'recursive-open-struct'
8
+ gem 'hash-deep-merge'
9
+
10
+ # Add dependencies to develop your gem here.
11
+ # Include everything needed to run rake, tests, features, etc.
12
+ group :development do
13
+ gem 'rspec' #, "~> 2.3.0"
14
+ gem 'bundler' #, "~> 1.0.0"
15
+ gem 'jeweler' #, "~> 1.6.0"
16
+ gem 'rcov' #, ">= 0"
17
+ end
@@ -0,0 +1,32 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ hash-deep-merge (0.1.1)
7
+ jeweler (1.6.0)
8
+ bundler (~> 1.0.0)
9
+ git (>= 1.2.5)
10
+ rake
11
+ rake (0.9.0)
12
+ rcov (0.9.9)
13
+ recursive-open-struct (0.1.0)
14
+ rspec (2.6.0)
15
+ rspec-core (~> 2.6.0)
16
+ rspec-expectations (~> 2.6.0)
17
+ rspec-mocks (~> 2.6.0)
18
+ rspec-core (2.6.3)
19
+ rspec-expectations (2.6.0)
20
+ diff-lcs (~> 1.1.2)
21
+ rspec-mocks (2.6.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ bundler
28
+ hash-deep-merge
29
+ jeweler
30
+ rcov
31
+ recursive-open-struct
32
+ rspec
@@ -0,0 +1,7 @@
1
+ No Copyright
2
+
3
+ The person who associated a work with this deed has dedicated the work to the public domain by waiving all of his or her rights to the work worldwide under copyright law, including all related and neighboring rights, to the extent allowed by law.
4
+
5
+ You can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission.
6
+
7
+ http://creativecommons.org/publicdomain/zero/1.0/
@@ -0,0 +1,111 @@
1
+ = settings-tree
2
+
3
+ == Introduction
4
+
5
+ This gem offers you a convenient settings structure for parameterizing your applications.
6
+
7
+ The good things over similar gems is the ability to have deep, recursive structures and the ability to have 'specialized' config according to the environment.
8
+
9
+ Example :
10
+
11
+ Settings.web_app.infos.company_name => 'Acme'
12
+ Settings.web_app.infos.app_name => 'Coffe maker'
13
+ Settings.web_app.engine.workers_count => 3
14
+
15
+ Those settings are read from a YAML file, like this one :
16
+
17
+ # YAML private config file
18
+ # XXX Beware ! This YAML : indention with spaces only ! XXX
19
+
20
+ ####### Common / default values #######
21
+ defaults:
22
+ root_url: localhost:3000
23
+ public_access: true
24
+
25
+ infos:
26
+ company_name: 'Acme'
27
+ app_name: 'Coffe maker'
28
+ copyright_starting_year: 2011
29
+ legend: 'A superb app which does ...'
30
+
31
+ engine:
32
+ workers_count: 3
33
+ auto_manage_workers: true
34
+ auto_manage_workers_redirect_output: true
35
+
36
+ ####### production environment #######
37
+ production:
38
+ # nothing special
39
+
40
+ ####### development environment #######
41
+ development:
42
+ engine:
43
+ auto_manage_workers_redirect_output: false
44
+
45
+ ####### test environment #######
46
+ test:
47
+ engine:
48
+ workers_count: 0
49
+
50
+ Note : the settings must reside under a root named 'defaults'. Other roots ('production', 'development'...) will be picked depending on the environment. (more about thet later)
51
+
52
+ This gem has more good features, keep reading for more.
53
+
54
+ Ideas taken from : http://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/
55
+
56
+ == Installation
57
+ Available as a gem
58
+ gem 'settings-tree'
59
+
60
+ Isn't it easy ?
61
+
62
+ == Use
63
+ Just register a settings group from a file :
64
+ Settings.register_settings_file('web_app', File.join(File.dirname(__FILE__), "config/config.yml"))
65
+ or for ruby on rails :
66
+ Settings.register_settings_file('web_app', File.join(::Rails.root.to_s, "config/config.yml"))
67
+
68
+ And now you can access your settings from anywhere :
69
+ puts Settings.web_app.infos.company_name
70
+
71
+ Note : of course, the group name must be a valid keyword, able to be converted to a sym.
72
+
73
+ You can register any number of group you want :
74
+ Settings.register_settings_file('web_game', File.join(File.dirname(__FILE__), "config/another_config.yml"))
75
+ And then :
76
+ puts Settings.web_game.guild_name.should == 'gang'
77
+
78
+ It's common to have settings that you don't want to stay under version control (accounts, passwords).
79
+ A solution is to use a complementary file not under version control. Just use :
80
+ Settings.register_settings_file('web_app', File.join(File.dirname(__FILE__), "config/config_complement.yml"))
81
+ And data will be merged, the new one taking precedence in case of conflicts.
82
+
83
+ In case you want to reload the settings, you have two functions for that :
84
+ Settings.reload_all
85
+ Settings.reload_group('web_app')
86
+
87
+ == Advanced use
88
+ Note : since those functions are rarely used, they don't have 'Settings.' shortcuts. Don't mind, it's the same.
89
+ === Environment
90
+ In a rails app, the environment will be taken automatically from 'Rails.env'. If not under a rails app or if the environment is not available, set it manually :
91
+ SettingsHolder.instance.environment = 'test'
92
+ The files will automatically be reloaded to take that into account.
93
+
94
+ You may also want to reset all the settings (everything will be forgotten) :
95
+ SettingsHolder.instance.reset
96
+
97
+ == Contributing to settings-tree
98
+
99
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
100
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
101
+ * Fork the project
102
+ * Start a feature/bugfix branch
103
+ * Commit and push until you are happy with your contribution
104
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
105
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
106
+
107
+ == Copyright
108
+
109
+ Copyright (c) 2011 Offirmo. See LICENSE.txt for
110
+ further details.
111
+
@@ -0,0 +1,54 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rubygems'
4
+ require 'bundler'
5
+ begin
6
+ Bundler.setup(:default, :development)
7
+ rescue Bundler::BundlerError => e
8
+ $stderr.puts e.message
9
+ $stderr.puts "Run `bundle install` to install missing gems"
10
+ exit e.status_code
11
+ end
12
+ require 'rake'
13
+
14
+ require 'jeweler'
15
+ Jeweler::Tasks.new do |gem|
16
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
17
+ gem.name = "settings-tree"
18
+ gem.homepage = "http://github.com/Offirmo/settings-tree"
19
+ gem.license = "CC0 1.0"
20
+ gem.summary = "Simple, arborescent settings structure from a YAML file."
21
+ gem.description = <<-EOF
22
+ This gem offers you a convenient settings structure for parameterizing your application.
23
+ Those settings are read from a YAML file.
24
+ Inheritance of settings (like in development modes) and multiple settings groups are available.
25
+ Great for a rails app but can be used for any ruby app.
26
+ EOF
27
+ gem.email = "offirmo.net@gmail.com"
28
+ gem.authors = ["Offirmo"]
29
+ # dependencies defined in Gemfile
30
+ end
31
+ Jeweler::RubygemsDotOrgTasks.new
32
+
33
+ require 'rspec/core'
34
+ require 'rspec/core/rake_task'
35
+ RSpec::Core::RakeTask.new(:spec) do |spec|
36
+ spec.pattern = FileList['spec/**/*_spec.rb']
37
+ end
38
+
39
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
40
+ spec.pattern = 'spec/**/*_spec.rb'
41
+ spec.rcov = true
42
+ end
43
+
44
+ task :default => :spec
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "settings-tree #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,21 @@
1
+ require 'settings_tree/settings_holder'
2
+
3
+ module Settings
4
+
5
+ ### Convenient shortcuts to the SettingsHolder class
6
+ def self.register_settings_file(name, file)
7
+ SettingsHolder.instance.register_settings_file(name, file)
8
+ end
9
+ def self.reload_all
10
+ return SettingsHolder.instance.reload_all
11
+ end
12
+ def self.reload_group(name)
13
+ return SettingsHolder.instance.reload_group(name)
14
+ end
15
+
16
+ # automatic access to settings groups
17
+ def self.method_missing(method, *args, &block)
18
+ return SettingsHolder.instance.get_settings(method)
19
+ end
20
+
21
+ end
@@ -0,0 +1,194 @@
1
+ require 'singleton'
2
+ require 'recursive_open_struct'
3
+ require 'hash_deep_merge'
4
+ require 'yaml'
5
+
6
+ ##
7
+ # Part of the "rails-settings" gem, this class is designed
8
+ # to store several OpenStruct representing 'settings'.
9
+ # It can load them from a YAML file, reload them, and accept queries.
10
+ #
11
+ # This class is usually not used directly but through the 'settings' module, offering shortcuts.
12
+ # ---
13
+ #
14
+ class SettingsHolder
15
+
16
+ # We want this class to be a singleton.
17
+ # This is on of the cases where singletons are acceptable.
18
+ include Singleton
19
+
20
+ ### Variables
21
+ @settings_list = nil
22
+
23
+ @environment = nil
24
+ attr_accessor :environment
25
+
26
+ ### Implementation
27
+
28
+ # a convenience function which reset the settings,
29
+ # forgetting about all the groups, files, etc.
30
+ def reset
31
+ initialize
32
+ end
33
+
34
+ #
35
+ def register_settings_file(name, file)
36
+
37
+ group_just_created = false
38
+
39
+ # create the group if not already here
40
+ unless has_group?(name)
41
+ register_new_group(name) unless has_group?(name)
42
+ group_just_created = true
43
+ end
44
+
45
+ # add this file as source
46
+ res = false
47
+ begin
48
+ res = register_new_src_file_for_group(name, file)
49
+ rescue Exception => e
50
+ # delete group if just created ? Not for now.
51
+ # proceed with exception
52
+ raise e
53
+ end
54
+
55
+ return res
56
+ end
57
+
58
+ def get_settings(name)
59
+ #puts name.inspect
60
+ #puts @settings_list.inspect
61
+ if !@settings_list.has_key?(name) then
62
+ raise ArgumentError, "Settings : unknown settings group '#{name.to_s}'"
63
+ else
64
+ return @settings_list[name][:data]
65
+ end
66
+ end
67
+
68
+ def environment=(env)
69
+ @environment = env
70
+
71
+ # need to reload all
72
+ reload_all
73
+ end
74
+
75
+ def reload_all
76
+ @settings_list.each do |key, value|
77
+ reload_group(key)
78
+ end
79
+ end
80
+
81
+ def reload_group(name)
82
+
83
+ res = false
84
+
85
+ if !has_group?(name) then
86
+ raise ArgumentError, "This group doesn't exist !"
87
+ else
88
+ data = Hash.new
89
+
90
+ @settings_list[name.to_sym][:src].each do |src|
91
+ data.deep_merge!(hash_data_for_src(src))
92
+ end
93
+
94
+ @settings_list[name.to_sym][:data] = RecursiveOpenStruct.new(data)
95
+ res = true
96
+ end # check parameters
97
+
98
+ return res
99
+ end
100
+
101
+ protected
102
+
103
+ def initialize
104
+ @settings_list = Hash.new
105
+
106
+ if defined? Rails then
107
+ @environment = Rails.env
108
+ end
109
+ end
110
+
111
+ def has_group?(name)
112
+ #puts @settings_list.inspect
113
+ return @settings_list.has_key?(name.to_sym)
114
+ end
115
+
116
+ def register_new_group(name)
117
+
118
+ if has_group?(name) then
119
+ raise ArgumentError, "This group already exists !"
120
+ else
121
+ @settings_list[name.to_sym] = {:data => nil, :src => Array.new }
122
+ end # check parameters
123
+
124
+ true
125
+ end
126
+
127
+ def group_has_src?(name, type, value)
128
+
129
+ if !has_group?(name) then
130
+ raise ArgumentError, "This group doesn't exist !"
131
+ else
132
+ @settings_list[name.to_sym][:src].any? {|src| src[:type] == type && src[:value] == value}
133
+ end # check parameters
134
+ end
135
+
136
+ def register_new_src_file_for_group(name, file)
137
+
138
+ res = false
139
+
140
+ if !has_group?(name) then
141
+ raise ArgumentError, "This group doesn't exist !"
142
+ elsif group_has_src?(name, :file, file) then
143
+ # this source is already registered. Ignore.
144
+ # should signal it ?
145
+ # res stays false, like in 'require'
146
+ else
147
+ @settings_list[name.to_sym][:src] << { :type => :file, :value => file}
148
+ # don't forget to update to take the new infos into account
149
+ begin
150
+ res = reload_group(name)
151
+ rescue Exception => e
152
+ # remove the src, since it's invalid
153
+ @settings_list[name.to_sym][:src].each_with_index do |item, index|
154
+ if item[:type] == :file && item[:value] == file then
155
+ @settings_list[name.to_sym][:src].delete_at(index)
156
+ break
157
+ end
158
+ end
159
+ # proceed with exception
160
+ raise e
161
+ end
162
+ end # check parameters
163
+
164
+ return res
165
+ end
166
+
167
+ def hash_data_for_src(src)
168
+ data = nil
169
+
170
+ case src[:type]
171
+ when :file
172
+ begin
173
+ complete_config = YAML.load_file( src[:value] ) || {}
174
+ default_config = complete_config['defaults'] || {}
175
+ specialized_config = @environment.nil? ? {} : (complete_config[@environment] || {})
176
+
177
+ data = default_config.deep_merge(specialized_config)
178
+ rescue Errno::ENOENT => e
179
+ # no file, classic error.
180
+ # resend
181
+ raise e
182
+ rescue Exception => e
183
+ #puts e.inspect
184
+ raise RuntimeError, "XXX There was a problem in parsing the file #{src[:value]}. Please investigate... #{e.message}"
185
+ end
186
+ else
187
+ raise RuntimeError, "Unknown source type : #{src[:type]}"
188
+ end
189
+
190
+ return data
191
+ end
192
+
193
+
194
+ end
@@ -0,0 +1,75 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{settings-tree}
8
+ s.version = "0.1.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = [%q{Offirmo}]
12
+ s.date = %q{2011-05-25}
13
+ s.description = %q{This gem offers you a convenient settings structure for parameterizing your application.
14
+ Those settings are read from a YAML file.
15
+ Inheritance of settings (like in development modes) and multiple settings groups are available.
16
+ Great for a rails app but can be used for any ruby app.
17
+ }
18
+ s.email = %q{offirmo.net@gmail.com}
19
+ s.extra_rdoc_files = [
20
+ "LICENSE.txt",
21
+ "README.rdoc"
22
+ ]
23
+ s.files = [
24
+ ".document",
25
+ ".rspec",
26
+ "Gemfile",
27
+ "Gemfile.lock",
28
+ "LICENSE.txt",
29
+ "README.rdoc",
30
+ "Rakefile",
31
+ "VERSION",
32
+ "lib/settings_tree.rb",
33
+ "lib/settings_tree/settings_holder.rb",
34
+ "settings-tree.gemspec",
35
+ "spec/settings-tree_spec.rb",
36
+ "spec/settings_holder_spec.rb",
37
+ "spec/spec_helper.rb",
38
+ "spec/test_files/another_config.yml",
39
+ "spec/test_files/config.yml",
40
+ "spec/test_files/config_complement.yml"
41
+ ]
42
+ s.homepage = %q{http://github.com/Offirmo/settings-tree}
43
+ s.licenses = [%q{CC0 1.0}]
44
+ s.require_paths = [%q{lib}]
45
+ s.rubygems_version = %q{1.8.3}
46
+ s.summary = %q{Simple, arborescent settings structure from a YAML file.}
47
+
48
+ if s.respond_to? :specification_version then
49
+ s.specification_version = 3
50
+
51
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
52
+ s.add_runtime_dependency(%q<recursive-open-struct>, [">= 0"])
53
+ s.add_runtime_dependency(%q<hash-deep-merge>, [">= 0"])
54
+ s.add_development_dependency(%q<rspec>, [">= 0"])
55
+ s.add_development_dependency(%q<bundler>, [">= 0"])
56
+ s.add_development_dependency(%q<jeweler>, [">= 0"])
57
+ s.add_development_dependency(%q<rcov>, [">= 0"])
58
+ else
59
+ s.add_dependency(%q<recursive-open-struct>, [">= 0"])
60
+ s.add_dependency(%q<hash-deep-merge>, [">= 0"])
61
+ s.add_dependency(%q<rspec>, [">= 0"])
62
+ s.add_dependency(%q<bundler>, [">= 0"])
63
+ s.add_dependency(%q<jeweler>, [">= 0"])
64
+ s.add_dependency(%q<rcov>, [">= 0"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<recursive-open-struct>, [">= 0"])
68
+ s.add_dependency(%q<hash-deep-merge>, [">= 0"])
69
+ s.add_dependency(%q<rspec>, [">= 0"])
70
+ s.add_dependency(%q<bundler>, [">= 0"])
71
+ s.add_dependency(%q<jeweler>, [">= 0"])
72
+ s.add_dependency(%q<rcov>, [">= 0"])
73
+ end
74
+ end
75
+
@@ -0,0 +1,56 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'settings_tree'
3
+
4
+ describe "SettingsTree" do
5
+
6
+ before(:all) do
7
+ #puts "Reseting settings before the suite..."
8
+ SettingsHolder.instance.reset
9
+ end
10
+
11
+ it "should be able to load settings from a file" do
12
+ res = Settings.register_settings_file('web_app', File.join(File.dirname(__FILE__), "test_files/config.yml"))
13
+ res.should be_true
14
+ end
15
+
16
+ it "should provide a convenient way to access settings" do
17
+ Settings.web_app.root_url.should == 'localhost:3000'
18
+ Settings.web_app.public_access.should be_true
19
+
20
+ Settings.web_app.infos.company_name.should == 'Acme'
21
+ Settings.web_app.infos.app_name.should == 'Coffe maker'
22
+ Settings.web_app.infos.copyright_starting_year.should == 2011
23
+ Settings.web_app.infos.legend.should == 'A superb app which does ...'
24
+
25
+ Settings.web_app.engine.workers_count.should == 3
26
+ Settings.web_app.engine.auto_manage_workers.should == true
27
+ Settings.web_app.engine.auto_manage_workers_redirect_output.should == true
28
+
29
+ # now we'll query non-existent fields just to be sure
30
+ Settings.web_app.infos.foo.should be_nil
31
+ end
32
+
33
+ it "should be able to load settings from two files at once" do
34
+ res = Settings.register_settings_file('web_app', File.join(File.dirname(__FILE__), "test_files/config_complement.yml"))
35
+ res.should be_true
36
+
37
+ # now let's query the new/changed values
38
+ Settings.web_app.root_url.should == 'talkmap.testhost:3000'
39
+ Settings.web_app.engine.workers_count.should == 3 # cause no environment
40
+ Settings.web_app.foo.bar.should == 42
41
+ end
42
+
43
+ it "should be able to hold several groups of settings" do
44
+ res = Settings.register_settings_file('web_game', File.join(File.dirname(__FILE__), "test_files/another_config.yml"))
45
+ res.should be_true
46
+
47
+ # now let's query the new values
48
+ Settings.web_game.guild_name.should == 'gang'
49
+ Settings.web_game.party_size.should == 4
50
+ end
51
+
52
+ it "should provide a way to reload settings" do
53
+ res = Settings.reload_all
54
+ end
55
+
56
+ end
@@ -0,0 +1,122 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'settings_tree/settings_holder'
3
+
4
+ #
5
+ # XXX WARNING XXX
6
+ # Due to the singleton nature of the class tested
7
+ # It is *NOT* reset between individual tests.
8
+ # Keep it in mind.
9
+ #
10
+
11
+ describe "SettingsHolder" do
12
+
13
+ before(:all) do
14
+ #puts "Reseting settings before the suite..."
15
+ SettingsHolder.instance.reset
16
+ end
17
+
18
+ describe "basic use" do
19
+
20
+ it "should be instantiable" do
21
+ s = SettingsHolder.instance
22
+ s.should_not be_nil
23
+ end
24
+
25
+ it "should be able to load settings from a file" do
26
+ res = SettingsHolder.instance.register_settings_file(:web_app, File.join(File.dirname(__FILE__), "test_files/config.yml"))
27
+ res.should be_true
28
+ end
29
+
30
+ it "should load all settings" do
31
+ # and now let's query all the expected settings
32
+ SettingsHolder.instance.get_settings(:web_app).root_url.should == 'localhost:3000'
33
+ SettingsHolder.instance.get_settings(:web_app).public_access.should be_true
34
+
35
+ SettingsHolder.instance.get_settings(:web_app).infos.company_name.should == 'Acme'
36
+ SettingsHolder.instance.get_settings(:web_app).infos.app_name.should == 'Coffe maker'
37
+ SettingsHolder.instance.get_settings(:web_app).infos.copyright_starting_year.should == 2011
38
+ SettingsHolder.instance.get_settings(:web_app).infos.legend.should == 'A superb app which does ...'
39
+
40
+ SettingsHolder.instance.get_settings(:web_app).engine.workers_count.should == 3
41
+ SettingsHolder.instance.get_settings(:web_app).engine.auto_manage_workers.should == true
42
+ SettingsHolder.instance.get_settings(:web_app).engine.auto_manage_workers_redirect_output.should == true
43
+
44
+ # now we'll query non-existent fields just to be sure
45
+ SettingsHolder.instance.get_settings(:web_app).infos.foo.should be_nil
46
+ end
47
+
48
+ it "should load and merge specialized settings" do
49
+
50
+ # Since those tests are not run from a rails app, there is no environment.
51
+ # We'll set one manually.
52
+
53
+ # before
54
+ SettingsHolder.instance.environment.should be_nil
55
+ SettingsHolder.instance.get_settings(:web_app).engine.auto_manage_workers_redirect_output.should == true
56
+ # change environment (settings are automatically reloaded)
57
+ SettingsHolder.instance.environment = 'development'
58
+ # after
59
+ SettingsHolder.instance.environment.should == 'development'
60
+ SettingsHolder.instance.get_settings(:web_app).engine.auto_manage_workers_redirect_output.should == false
61
+
62
+ # OK, another one
63
+ # before
64
+ SettingsHolder.instance.environment.should == 'development'
65
+ SettingsHolder.instance.get_settings(:web_app).engine.auto_manage_workers_redirect_output.should == false
66
+ SettingsHolder.instance.get_settings(:web_app).engine.workers_count.should == 3
67
+ # change environment (settings are automatically reloaded)
68
+ SettingsHolder.instance.environment = 'test'
69
+ # after
70
+ SettingsHolder.instance.environment.should == 'test'
71
+ SettingsHolder.instance.get_settings(:web_app).engine.auto_manage_workers_redirect_output.should == true
72
+ SettingsHolder.instance.get_settings(:web_app).engine.workers_count.should == 0
73
+ end
74
+
75
+ it "should be able to load settings from two files at once" do
76
+ res = SettingsHolder.instance.register_settings_file(:web_app, File.join(File.dirname(__FILE__), "test_files/config_complement.yml"))
77
+ res.should be_true
78
+
79
+ # now let's query the new/changed values
80
+ SettingsHolder.instance.get_settings(:web_app).root_url.should == 'talkmap.testhost:3000'
81
+ SettingsHolder.instance.get_settings(:web_app).engine.workers_count.should == 27
82
+ SettingsHolder.instance.get_settings(:web_app).foo.bar.should == 42
83
+ end
84
+
85
+ end
86
+
87
+ describe "advanced use" do
88
+ it "should handle if a file is invalid" do
89
+
90
+ # default case : an exception is thrown
91
+ expect {
92
+ SettingsHolder.instance.register_settings_file(:web_app, File.join(File.dirname(__FILE__), "test_files/a_non_existing_file.yml"))
93
+ }.to raise_error(Errno::ENOENT)
94
+
95
+ # the file shouldn't have been registered, so an update shouldn't throw an exception
96
+ expect {
97
+ SettingsHolder.instance.reload_all
98
+ }.to_not raise_error
99
+
100
+ # now we have a special option to allow a file to not exist (yet)
101
+ # XXX TODO maybe some day
102
+ end
103
+
104
+ it "should act correctly if a file is already used" do
105
+ res = SettingsHolder.instance.register_settings_file(:web_app, File.join(File.dirname(__FILE__), "test_files/config.yml"))
106
+ res.should be_false # like in require
107
+ end
108
+
109
+ it "should be a singleton" do
110
+ expect {
111
+ SettingsHolder.new
112
+ }.to raise_error(NoMethodError)
113
+
114
+ SettingsHolder.should respond_to :instance
115
+
116
+ s = SettingsHolder.instance
117
+ SettingsHolder.instance.should == s
118
+ end
119
+
120
+ end
121
+
122
+ end
@@ -0,0 +1,22 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
3
+
4
+ # we need other gems : load them via bundler :
5
+ require "rubygems"
6
+ require "bundler/setup"
7
+ # now our dependencies are available.
8
+
9
+ require 'rspec'
10
+ require 'settings_tree'
11
+
12
+ # Requires supporting files with custom matchers and macros, etc,
13
+ # in ./support/ and its subdirectories.
14
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
15
+
16
+
17
+ # I add some display to clearly mark the beginning of the tests
18
+ puts "*\n"*12
19
+
20
+ RSpec.configure do |config|
21
+
22
+ end
@@ -0,0 +1,11 @@
1
+ # YAML private config file
2
+ # http://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/
3
+
4
+ # XXX Beware ! This YAML : indention with spaces only ! XXX
5
+
6
+
7
+ ####### Common / default values #######
8
+ defaults:
9
+ guild_name: 'gang'
10
+ party_size: 4
11
+
@@ -0,0 +1,42 @@
1
+ # YAML private config file
2
+ # http://kpumuk.info/ruby-on-rails/flexible-application-configuration-in-ruby-on-rails/
3
+
4
+ # XXX Beware ! This YAML : indention with spaces only ! XXX
5
+
6
+
7
+ ####### Common / default values #######
8
+ defaults:
9
+ root_url: localhost:3000
10
+ public_access: true
11
+
12
+ infos:
13
+ company_name: 'Acme'
14
+ app_name: 'Coffe maker'
15
+ copyright_starting_year: 2011
16
+ legend: 'A superb app which does ...'
17
+
18
+ engine:
19
+ # How many workers we want :
20
+ workers_count: 3
21
+ # Should workers be launched and stopped automatically when launching/stopping the application ?
22
+ # Workers sometimes need to be launched separately (ex. delayed_job). This remove the hassle.
23
+ auto_manage_workers: true
24
+ # Should the thread which will launch the workers output in a file or in the same standard output as the current application ?
25
+ # Should be usually set to true (in a file) to avoid trace confusion.
26
+ # Put this to "false" if you want to debug the workers automatic launch or see what happen.
27
+ auto_manage_workers_redirect_output: true
28
+
29
+
30
+ ####### production environment #######
31
+ production:
32
+ # nothing special
33
+
34
+ ####### development environment #######
35
+ development:
36
+ engine:
37
+ auto_manage_workers_redirect_output: false
38
+
39
+ ####### test environment #######
40
+ test:
41
+ engine:
42
+ workers_count: 0
@@ -0,0 +1,17 @@
1
+ # YAML private config file - complement for local adaptations
2
+
3
+ # XXX Beware ! This YAML : indention with spaces only ! XXX
4
+
5
+
6
+ ####### Common / default values #######
7
+ defaults:
8
+ root_url: talkmap.testhost:3000
9
+
10
+ # a new key
11
+ foo:
12
+ bar: 42
13
+
14
+ ####### test environment #######
15
+ test:
16
+ engine:
17
+ workers_count: 27
metadata ADDED
@@ -0,0 +1,143 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: settings-tree
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Offirmo
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-05-25 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: recursive-open-struct
16
+ requirement: &79882210 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *79882210
25
+ - !ruby/object:Gem::Dependency
26
+ name: hash-deep-merge
27
+ requirement: &79881970 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *79881970
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &79881730 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *79881730
47
+ - !ruby/object:Gem::Dependency
48
+ name: bundler
49
+ requirement: &79881490 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *79881490
58
+ - !ruby/object:Gem::Dependency
59
+ name: jeweler
60
+ requirement: &79881250 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *79881250
69
+ - !ruby/object:Gem::Dependency
70
+ name: rcov
71
+ requirement: &79881010 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *79881010
80
+ description: ! 'This gem offers you a convenient settings structure for parameterizing
81
+ your application.
82
+
83
+ Those settings are read from a YAML file.
84
+
85
+ Inheritance of settings (like in development modes) and multiple settings groups
86
+ are available.
87
+
88
+ Great for a rails app but can be used for any ruby app.
89
+
90
+ '
91
+ email: offirmo.net@gmail.com
92
+ executables: []
93
+ extensions: []
94
+ extra_rdoc_files:
95
+ - LICENSE.txt
96
+ - README.rdoc
97
+ files:
98
+ - .document
99
+ - .rspec
100
+ - Gemfile
101
+ - Gemfile.lock
102
+ - LICENSE.txt
103
+ - README.rdoc
104
+ - Rakefile
105
+ - VERSION
106
+ - lib/settings_tree.rb
107
+ - lib/settings_tree/settings_holder.rb
108
+ - settings-tree.gemspec
109
+ - spec/settings-tree_spec.rb
110
+ - spec/settings_holder_spec.rb
111
+ - spec/spec_helper.rb
112
+ - spec/test_files/another_config.yml
113
+ - spec/test_files/config.yml
114
+ - spec/test_files/config_complement.yml
115
+ homepage: http://github.com/Offirmo/settings-tree
116
+ licenses:
117
+ - CC0 1.0
118
+ post_install_message:
119
+ rdoc_options: []
120
+ require_paths:
121
+ - lib
122
+ required_ruby_version: !ruby/object:Gem::Requirement
123
+ none: false
124
+ requirements:
125
+ - - ! '>='
126
+ - !ruby/object:Gem::Version
127
+ version: '0'
128
+ segments:
129
+ - 0
130
+ hash: 228111425
131
+ required_rubygems_version: !ruby/object:Gem::Requirement
132
+ none: false
133
+ requirements:
134
+ - - ! '>='
135
+ - !ruby/object:Gem::Version
136
+ version: '0'
137
+ requirements: []
138
+ rubyforge_project:
139
+ rubygems_version: 1.8.3
140
+ signing_key:
141
+ specification_version: 3
142
+ summary: Simple, arborescent settings structure from a YAML file.
143
+ test_files: []