settings-tree 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/.rspec +2 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +32 -0
- data/LICENSE.txt +7 -0
- data/README.rdoc +111 -0
- data/Rakefile +54 -0
- data/VERSION +1 -0
- data/lib/settings_tree.rb +21 -0
- data/lib/settings_tree/settings_holder.rb +194 -0
- data/settings-tree.gemspec +75 -0
- data/spec/settings-tree_spec.rb +56 -0
- data/spec/settings_holder_spec.rb +122 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/test_files/another_config.yml +11 -0
- data/spec/test_files/config.yml +42 -0
- data/spec/test_files/config_complement.yml +17 -0
- metadata +143 -0
data/.document
ADDED
data/.rspec
ADDED
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
|
data/Gemfile.lock
ADDED
@@ -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
|
data/LICENSE.txt
ADDED
@@ -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/
|
data/README.rdoc
ADDED
@@ -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
|
+
|
data/Rakefile
ADDED
@@ -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
|
data/spec/spec_helper.rb
ADDED
@@ -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: []
|