dionysus 0.0.0.pre1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.md +5 -0
- data/VERSION +1 -1
- data/dionysus.gemspec +60 -0
- data/lib/dionysus.rb +1 -1
- data/lib/dionysus/configuration.rb +193 -0
- data/spec/configuration_spec.rb +176 -0
- metadata +10 -9
data/README.md
CHANGED
@@ -17,6 +17,11 @@ Installation
|
|
17
17
|
|
18
18
|
gem install dionysus
|
19
19
|
|
20
|
+
Usage
|
21
|
+
-----
|
22
|
+
|
23
|
+
First, add "dionysus" to your Gemfile or whatever other dependency system you're using. Then, you'll need to require each file as you need them. Dionysus is setup *à la carte* since parts are bound to conflict with something you're using at some point.
|
24
|
+
|
20
25
|
Resources
|
21
26
|
---------
|
22
27
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.1.0
|
data/dionysus.gemspec
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{dionysus}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Travis D. Warlick, Jr."]
|
12
|
+
s.date = %q{2010-03-15}
|
13
|
+
s.email = %q{warlickt@operissystems.com}
|
14
|
+
s.extra_rdoc_files = [
|
15
|
+
"LICENSE",
|
16
|
+
"README.md"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
".document",
|
20
|
+
".gitignore",
|
21
|
+
"LICENSE",
|
22
|
+
"README.md",
|
23
|
+
"Rakefile",
|
24
|
+
"VERSION",
|
25
|
+
"dionysus.gemspec",
|
26
|
+
"lib/dionysus.rb",
|
27
|
+
"lib/dionysus/configuration.rb",
|
28
|
+
"spec/configuration_spec.rb",
|
29
|
+
"spec/dionysus_spec.rb",
|
30
|
+
"spec/spec.opts",
|
31
|
+
"spec/spec_helper.rb"
|
32
|
+
]
|
33
|
+
s.homepage = %q{http://github.com/tekwiz/dionysus}
|
34
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
35
|
+
s.require_paths = ["lib"]
|
36
|
+
s.rubygems_version = %q{1.3.6}
|
37
|
+
s.summary = %q{A helpful set of utility classes, generators, and command-line tools.}
|
38
|
+
s.test_files = [
|
39
|
+
"spec/configuration_spec.rb",
|
40
|
+
"spec/dionysus_spec.rb",
|
41
|
+
"spec/spec_helper.rb"
|
42
|
+
]
|
43
|
+
|
44
|
+
if s.respond_to? :specification_version then
|
45
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_runtime_dependency(%q<activesupport>, ["= 3.0.0.beta"])
|
50
|
+
s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
|
51
|
+
else
|
52
|
+
s.add_dependency(%q<activesupport>, ["= 3.0.0.beta"])
|
53
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
54
|
+
end
|
55
|
+
else
|
56
|
+
s.add_dependency(%q<activesupport>, ["= 3.0.0.beta"])
|
57
|
+
s.add_dependency(%q<rspec>, [">= 1.2.9"])
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
data/lib/dionysus.rb
CHANGED
@@ -0,0 +1,193 @@
|
|
1
|
+
##
|
2
|
+
# = Configuration
|
3
|
+
#
|
4
|
+
# require 'dionysus/configuration'
|
5
|
+
#
|
6
|
+
# A simple configuration system that can work in a "hard-keys" or "soft-keys"
|
7
|
+
# mode. In the "hard-keys" mode, the configuration will only allow a specific
|
8
|
+
# set of keys given on initialization. In "soft-keys" mode, the configuration
|
9
|
+
# will accept any keys, at any time, as long as they are valid.
|
10
|
+
#
|
11
|
+
# == Soft Keys Example:
|
12
|
+
#
|
13
|
+
# config = Configuration.new(false, :a_key => 'some value')
|
14
|
+
# config.soft_keys? #=> true
|
15
|
+
# config.hard_keys? #=> false
|
16
|
+
# config.a_key = 'new value'
|
17
|
+
# config.a_key #=> 'new value'
|
18
|
+
# config.another_key = 'some value'
|
19
|
+
# config.anoter_key #=> 'some value'
|
20
|
+
#
|
21
|
+
# == Hard Keys Example:
|
22
|
+
#
|
23
|
+
# config = Configuration.new(:foo, :bar, {:wowsers => 'wow', :foo => 'fooey'})
|
24
|
+
# config.hard_keys? #=> true
|
25
|
+
# config.soft_keys? #=> false
|
26
|
+
# config.a_key #=> raises NoMethodError
|
27
|
+
# config[:a_key] #=> raises ArgumentError
|
28
|
+
# config.foo = 'fooey'
|
29
|
+
# config.bar #=> nil
|
30
|
+
# config.wowsers #=> 'wow'
|
31
|
+
#
|
32
|
+
# == Multi Access
|
33
|
+
#
|
34
|
+
# Values are accessible through the "magic" methods, get() and set() methods,
|
35
|
+
# and hash brackets. These will all give the same result:
|
36
|
+
# config.a_key
|
37
|
+
# config[:a_key]
|
38
|
+
# config['a_key']
|
39
|
+
# config.get(:a_key)
|
40
|
+
# config.get('a_key')
|
41
|
+
#
|
42
|
+
# == Object Keys
|
43
|
+
#
|
44
|
+
# All keys are converted to strings and then to symbols:
|
45
|
+
# o = Object.new
|
46
|
+
# config.set(o, 'foo')
|
47
|
+
# config.get(o) #=> 'foo'
|
48
|
+
# config.keys #=> [:'#<Object:0x190544c>']
|
49
|
+
class Configuration
|
50
|
+
# Regex to define a valid key
|
51
|
+
VALID_KEY = '[A-Za-z0-9\-_]+'
|
52
|
+
|
53
|
+
##
|
54
|
+
# Create the configuration.
|
55
|
+
#
|
56
|
+
# Soft Keys mode:: Pass +false+ as the first argument.
|
57
|
+
# Hard Keys mode:: Default, or pass +true+ as the first argument.
|
58
|
+
def initialize( *args )
|
59
|
+
defaults = (args.last.is_a?(Hash) ? args.pop : {})
|
60
|
+
|
61
|
+
if _hard_keys?(defaults, args)
|
62
|
+
@keys = _normalize_hard_keys(defaults, args)
|
63
|
+
raise ArgumentError, 'Cannot have a hard keys configuration with no keys' if @keys.empty?
|
64
|
+
else
|
65
|
+
@keys = nil
|
66
|
+
raise ArgumentError, 'Cannot define hard keys in soft keys mode' if args.any?
|
67
|
+
end
|
68
|
+
|
69
|
+
_initialize_config(defaults)
|
70
|
+
end
|
71
|
+
|
72
|
+
##
|
73
|
+
# +true+ if the configuration is limited to a specific set of keys.
|
74
|
+
def hard_keys?() !!@keys; end
|
75
|
+
|
76
|
+
##
|
77
|
+
# +true+ if the configuration is NOT limited to a specific set of keys.
|
78
|
+
# (Inverse) of +hard_keys?+
|
79
|
+
def soft_keys?() !@keys; end
|
80
|
+
|
81
|
+
##
|
82
|
+
# The set of keys for the configuration. If this is a hard keys
|
83
|
+
# configuration, it returns the possible keys. Otherwise, it returns the
|
84
|
+
# set keys.
|
85
|
+
def keys() @keys || @config.keys; end
|
86
|
+
|
87
|
+
##
|
88
|
+
# +false+ if there are any values set.
|
89
|
+
def empty?() @config.empty?; end
|
90
|
+
|
91
|
+
##
|
92
|
+
# The number of configurations set.
|
93
|
+
def size() @config.size; end
|
94
|
+
|
95
|
+
##
|
96
|
+
# Set the configuration key to the given value.
|
97
|
+
def set(key, value) validate_key(key); @config[_normalize_key(key)] = value; end
|
98
|
+
alias_method :'[]=', :set
|
99
|
+
|
100
|
+
##
|
101
|
+
# Get the configuration value.
|
102
|
+
def get(key) validate_key(key); @config[_normalize_key(key)]; end
|
103
|
+
alias_method :'[]', :get
|
104
|
+
|
105
|
+
##
|
106
|
+
# Delete the configuration value.
|
107
|
+
def delete(key) @config.delete(key); end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Convert the configuration to a hash.
|
111
|
+
def to_hash() @config.to_hash; end
|
112
|
+
|
113
|
+
##
|
114
|
+
# +true+ if the key is valid.
|
115
|
+
def valid_key?( key )
|
116
|
+
return false if key.blank?
|
117
|
+
key = _normalize_key(key).to_s
|
118
|
+
key =~ /^#{VALID_KEY}$/ and !self.methods.include?(key)
|
119
|
+
end
|
120
|
+
|
121
|
+
##
|
122
|
+
# +true+ if the key is allowed.
|
123
|
+
def allowed_key?( key )
|
124
|
+
@keys.nil? ? true : @keys.include?(_normalize_key(key))
|
125
|
+
end
|
126
|
+
|
127
|
+
private
|
128
|
+
|
129
|
+
##
|
130
|
+
# If the key is invalid, it raises an error.
|
131
|
+
def validate_key( key )
|
132
|
+
return true if valid_key?(key) and allowed_key?(key)
|
133
|
+
raise ArgumentError, "Invalid key: #{key}"
|
134
|
+
end
|
135
|
+
|
136
|
+
##
|
137
|
+
# Determine if the set of arguments is requesting a hard keys configuration.
|
138
|
+
#
|
139
|
+
# This is a hard key configuration set if
|
140
|
+
# 1) the first argument is NOT false
|
141
|
+
# 2) there are explicit keys defined
|
142
|
+
# 3) there is a default set of arguments
|
143
|
+
def _hard_keys?( defaults, args )
|
144
|
+
if args.first == true or args.first == false
|
145
|
+
args.shift
|
146
|
+
else
|
147
|
+
args.any? or (defaults and defaults.any?)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
##
|
152
|
+
# Normalize the keys and keys from the defaults hash into the hard keys
|
153
|
+
# array.
|
154
|
+
def _normalize_hard_keys( defaults, keys )
|
155
|
+
returning [] do |keys_|
|
156
|
+
(keys + defaults.keys).uniq.collect {|k| k.to_s}.sort.each do |key|
|
157
|
+
raise ArgumentError, "Invalid key: '#{key}'" unless valid_key?(key)
|
158
|
+
keys_ << _normalize_key(key)
|
159
|
+
end
|
160
|
+
end.freeze
|
161
|
+
end
|
162
|
+
|
163
|
+
##
|
164
|
+
# Normalize a key by converting it to a string and then a symbol.
|
165
|
+
def _normalize_key( key )
|
166
|
+
key.to_s.to_sym
|
167
|
+
end
|
168
|
+
|
169
|
+
##
|
170
|
+
# Initialize the default config hash
|
171
|
+
def _initialize_config( defaults )
|
172
|
+
@config = {}
|
173
|
+
defaults.each { |key, value| set(key, value) }
|
174
|
+
@config
|
175
|
+
end
|
176
|
+
|
177
|
+
##
|
178
|
+
# The magic. Enables +config.foo+ and +config.foo=+ to map to the getters
|
179
|
+
# and setters.
|
180
|
+
def method_missing( method_name, *args, &block )
|
181
|
+
match = method_name.to_s.match(/^(#{VALID_KEY})(=)??\Z/)
|
182
|
+
key, setter = _normalize_key(match[1]), (match[2] == '=')
|
183
|
+
|
184
|
+
if allowed_key?(key) and !block_given?
|
185
|
+
if setter and args.length == 1
|
186
|
+
return set(key, args.first)
|
187
|
+
elsif match[1] and match[2].nil? and args.length == 0
|
188
|
+
return get(key)
|
189
|
+
end
|
190
|
+
end
|
191
|
+
super
|
192
|
+
end
|
193
|
+
end
|
@@ -0,0 +1,176 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
|
2
|
+
require 'dionysus/configuration'
|
3
|
+
|
4
|
+
describe Configuration do
|
5
|
+
describe "basics" do
|
6
|
+
before(:each) { @c = Configuration.new(false) }
|
7
|
+
|
8
|
+
it "should be empty when no defaults" do
|
9
|
+
@c.size.should == 0
|
10
|
+
@c.should be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be accessible by hash brackets" do
|
14
|
+
@c[:something] = 'a value'
|
15
|
+
@c['something-else'] = 'b value'
|
16
|
+
@c.should_not be_empty
|
17
|
+
@c[:something].should == 'a value'
|
18
|
+
@c['something'].should == 'a value'
|
19
|
+
@c[:'something-else'].should == 'b value'
|
20
|
+
@c['something-else'].should == 'b value'
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be accessible by method name" do
|
24
|
+
@c.something = 'a value'
|
25
|
+
@c.should_not be_empty
|
26
|
+
@c.something.should == 'a value'
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should be accessible by get/set methods" do
|
30
|
+
@c.set(:something, 'a value')
|
31
|
+
@c.set('something-else', 'b value')
|
32
|
+
@c.should_not be_empty
|
33
|
+
@c.get(:something).should == 'a value'
|
34
|
+
@c.get('something').should == 'a value'
|
35
|
+
@c.get(:'something-else').should == 'b value'
|
36
|
+
@c.get('something-else').should == 'b value'
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should not allow keys with the same name as defined methods." do
|
40
|
+
lambda { @c.set(:set, 'wowsers') }.should raise_error(ArgumentError, "Invalid key: set")
|
41
|
+
@c.to_hash[:set].should be_nil
|
42
|
+
lambda { @c[:set] = 'wowsers' }.should raise_error(ArgumentError, "Invalid key: set")
|
43
|
+
@c.to_hash[:set].should be_nil
|
44
|
+
lambda { @c.set = 'wowsers' }.should raise_error(ArgumentError, "Invalid key: set")
|
45
|
+
@c.to_hash[:set].should be_nil
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should not allow keys that do not conform to the allowed regex." do
|
49
|
+
lambda { @c.set('^&^&*^&*', 'wowsers') }.should raise_error(ArgumentError, "Invalid key: ^&^&*^&*")
|
50
|
+
lambda { @c.set('', 'wowsers') }.should raise_error(ArgumentError, "Invalid key: ")
|
51
|
+
lambda { @c.set(nil, 'wowsers') }.should raise_error(ArgumentError, "Invalid key: ")
|
52
|
+
lambda { @c.set(Object.new, 'wowsers') }.should raise_error(ArgumentError, /^Invalid key: #<Object:0x[a-fA-F0-9]+>$/)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should revert to the normal method_missing with a block" do
|
56
|
+
lambda { @c.not_a_key { 1+1 } }.should raise_error(NoMethodError)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should revert to the normal method_missing with any arguments" do
|
60
|
+
lambda { @c.not_a_key('fooey') }.should raise_error(NoMethodError)
|
61
|
+
lambda { @c.not_a_key(nil) }.should raise_error(NoMethodError)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should revert to normal method_missing with a setter and more than 1 argument" do
|
65
|
+
lambda { @c.send(:not_a_key=, 'fooey', nil) }.should raise_error(NoMethodError)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "with soft keys" do
|
70
|
+
before(:each) { @c = Configuration.new(false) }
|
71
|
+
|
72
|
+
it 'should be soft keys' do
|
73
|
+
@c.should be_soft_keys
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should initialize empty' do
|
77
|
+
@c.size.should == 0
|
78
|
+
@c.should be_empty
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should take defaults" do
|
82
|
+
@c = Configuration.new(false, :a_val => 'some value')
|
83
|
+
@c.should be_soft_key
|
84
|
+
@c.a_val.should == 'some value'
|
85
|
+
@c.size.should == 1
|
86
|
+
@c.should_not be_empty
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should remove the key on delete" do
|
90
|
+
@c.foo = 'fooey'
|
91
|
+
@c.keys.should == [:foo]
|
92
|
+
|
93
|
+
@c.delete :foo
|
94
|
+
@c.foo.should be_nil
|
95
|
+
@c.keys.should be_empty
|
96
|
+
end
|
97
|
+
|
98
|
+
it "should not remove the key on set nil" do
|
99
|
+
@c.foo = 'fooey'
|
100
|
+
@c.keys.should == [:foo]
|
101
|
+
|
102
|
+
@c.foo = nil
|
103
|
+
@c.foo.should be_nil
|
104
|
+
@c.keys.should == [:foo]
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should allow any key" do
|
108
|
+
@c.allowed_key?('fjdasfiodsaifo').should be_true
|
109
|
+
@c.allowed_key?('^&*%^*9789').should be_true
|
110
|
+
@c.allowed_key?(Object.new).should be_true
|
111
|
+
end
|
112
|
+
|
113
|
+
it "should not allow setting hard keys" do
|
114
|
+
lambda { @c = Configurat.new(false, :a_hard_key, :a_val => 'some_value') }.should
|
115
|
+
raise_error(ArgumentError, 'Cannot define hard keys in soft keys mode')
|
116
|
+
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "with hard keys" do
|
121
|
+
before(:each) { @c = Configuration.new(:foo, :bar) }
|
122
|
+
|
123
|
+
it "should be hard keys" do
|
124
|
+
@c.should be_hard_keys
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should initialize empty" do
|
128
|
+
@c.size.should == 0
|
129
|
+
@c.should be_empty
|
130
|
+
@c.keys.should == [:bar, :foo]
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should take defaults" do
|
134
|
+
@c = Configuration.new(:foo, :bar, {'wowsers' => 'wow', :bar => 'fooey'})
|
135
|
+
@c.keys.should == [:bar, :foo, :wowsers]
|
136
|
+
@c.size.should == 2
|
137
|
+
@c.foo.should == nil
|
138
|
+
@c.bar.should == 'fooey'
|
139
|
+
@c[:wowsers].should == 'wow'
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should not remove the key on delete" do
|
143
|
+
@c.foo = 'fooey'
|
144
|
+
@c.keys.should include(:foo)
|
145
|
+
@c.size.should == 1
|
146
|
+
|
147
|
+
@c.delete :foo
|
148
|
+
@c.foo.should be_nil
|
149
|
+
@c.keys.should include(:foo)
|
150
|
+
@c.size.should == 0
|
151
|
+
end
|
152
|
+
|
153
|
+
it "should not remove the key on set nil" do
|
154
|
+
@c.foo = 'fooey'
|
155
|
+
@c.keys.should include(:foo)
|
156
|
+
@c.size.should == 1
|
157
|
+
|
158
|
+
@c.foo = nil
|
159
|
+
@c.foo.should be_nil
|
160
|
+
@c.keys.should include(:foo)
|
161
|
+
@c.size.should == 1
|
162
|
+
end
|
163
|
+
|
164
|
+
it "should allow only the hard keys" do
|
165
|
+
@c.allowed_key?('fjdasfiodsaifo').should be_false
|
166
|
+
@c.allowed_key?('^&*%^*9789').should be_false
|
167
|
+
@c.allowed_key?(Object.new).should be_false
|
168
|
+
@c.allowed_key?(:foo).should be_true
|
169
|
+
@c.allowed_key?('foo').should be_true
|
170
|
+
end
|
171
|
+
|
172
|
+
it "should revert to the normal method_missing an unallowed key" do
|
173
|
+
lambda { @c.not_a_key }.should raise_error(NoMethodError)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dionysus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
+
- 1
|
7
8
|
- 0
|
8
|
-
|
9
|
-
- pre1
|
10
|
-
version: 0.0.0.pre1
|
9
|
+
version: 0.1.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Travis D. Warlick, Jr.
|
@@ -63,7 +62,10 @@ files:
|
|
63
62
|
- README.md
|
64
63
|
- Rakefile
|
65
64
|
- VERSION
|
65
|
+
- dionysus.gemspec
|
66
66
|
- lib/dionysus.rb
|
67
|
+
- lib/dionysus/configuration.rb
|
68
|
+
- spec/configuration_spec.rb
|
67
69
|
- spec/dionysus_spec.rb
|
68
70
|
- spec/spec.opts
|
69
71
|
- spec/spec_helper.rb
|
@@ -85,13 +87,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
85
87
|
version: "0"
|
86
88
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
87
89
|
requirements:
|
88
|
-
- - "
|
90
|
+
- - ">="
|
89
91
|
- !ruby/object:Gem::Version
|
90
92
|
segments:
|
91
|
-
-
|
92
|
-
|
93
|
-
- 1
|
94
|
-
version: 1.3.1
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
95
|
requirements: []
|
96
96
|
|
97
97
|
rubyforge_project:
|
@@ -100,5 +100,6 @@ signing_key:
|
|
100
100
|
specification_version: 3
|
101
101
|
summary: A helpful set of utility classes, generators, and command-line tools.
|
102
102
|
test_files:
|
103
|
+
- spec/configuration_spec.rb
|
103
104
|
- spec/dionysus_spec.rb
|
104
105
|
- spec/spec_helper.rb
|