dionysus 0.0.0.pre1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|