caesars 0.7.0 → 0.7.1
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/CHANGES.txt +7 -0
- data/caesars.gemspec +4 -1
- data/lib/caesars.rb +8 -233
- data/lib/caesars/config.rb +190 -0
- data/lib/caesars/exceptions.rb +17 -0
- data/lib/caesars/hash.rb +31 -0
- metadata +5 -2
data/CHANGES.txt
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
CAESARS -- CHANGES
|
2
2
|
|
3
3
|
|
4
|
+
#### 0.7.1 (2009-06-08) ###############################
|
5
|
+
|
6
|
+
* FIXED: Updated file manifest in gemspec
|
7
|
+
* FIXED: Correct mistake in rdocs for Caesars::Config.new
|
8
|
+
* CHANGE: Caesars::** classes moved into separate files.
|
9
|
+
|
10
|
+
|
4
11
|
#### 0.7.0 (2009-06-03) ###############################
|
5
12
|
|
6
13
|
* CHANGE: Post-processing for Caesars::Config classes now occurs
|
data/caesars.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = "caesars"
|
3
3
|
s.rubyforge_project = "caesars"
|
4
|
-
s.version = "0.7.
|
4
|
+
s.version = "0.7.1"
|
5
5
|
s.specification_version = 1 if s.respond_to? :specification_version=
|
6
6
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
7
7
|
|
@@ -22,6 +22,9 @@
|
|
22
22
|
bin/party.conf
|
23
23
|
caesars.gemspec
|
24
24
|
lib/caesars.rb
|
25
|
+
lib/caesars/config.rb
|
26
|
+
lib/caesars/exceptions.rb
|
27
|
+
lib/caesars/hash.rb
|
25
28
|
lib/caesars/orderedhash.rb
|
26
29
|
)
|
27
30
|
|
data/lib/caesars.rb
CHANGED
@@ -8,9 +8,12 @@
|
|
8
8
|
# See bin/example
|
9
9
|
#
|
10
10
|
class Caesars
|
11
|
+
|
11
12
|
require 'caesars/orderedhash'
|
12
|
-
|
13
|
-
|
13
|
+
require 'caesars/exceptions'
|
14
|
+
require 'caesars/config'
|
15
|
+
|
16
|
+
VERSION = "0.7.1"
|
14
17
|
@@debug = false
|
15
18
|
@@chilled = {}
|
16
19
|
@@forced_array = {}
|
@@ -18,7 +21,9 @@ class Caesars
|
|
18
21
|
@@known_symbols = []
|
19
22
|
@@known_symbols_by_glass = {}
|
20
23
|
HASH_TYPE = (RUBY_VERSION =~ /1.9/) ? ::Hash : Caesars::OrderedHash
|
21
|
-
|
24
|
+
|
25
|
+
require 'caesars/hash'
|
26
|
+
|
22
27
|
def Caesars.enable_debug; @@debug = true; end
|
23
28
|
def Caesars.disable_debug; @@debug = false; end
|
24
29
|
def Caesars.debug?; @@debug; end
|
@@ -59,52 +64,9 @@ class Caesars
|
|
59
64
|
@@known_symbols_by_glass[g].member?(s.to_sym)
|
60
65
|
end
|
61
66
|
|
62
|
-
# A subclass of ::Hash that provides method names for hash parameters.
|
63
|
-
# It's like a lightweight OpenStruct.
|
64
|
-
# ch = Caesars::Hash[:tabasco => :lots!]
|
65
|
-
# puts ch.tabasco # => lots!
|
66
|
-
#
|
67
|
-
class Hash < HASH_TYPE
|
68
|
-
def method_missing(meth)
|
69
|
-
self[meth] if self.has_key?(meth)
|
70
|
-
end
|
71
|
-
|
72
|
-
# Returns a clone of itself and all children cast as ::Hash objects
|
73
|
-
def to_hash(hash=self)
|
74
|
-
return hash unless hash.is_a?(Caesars::Hash) # nothing to do
|
75
|
-
target = (Caesars::HASH_TYPE)[dup]
|
76
|
-
hash.keys.each do |key|
|
77
|
-
if hash[key].is_a? Caesars::Hash
|
78
|
-
target[key] = hash[key].to_hash
|
79
|
-
next
|
80
|
-
elsif hash[key].is_a? Array
|
81
|
-
target[key] = hash[key].collect { |h| to_hash(h) }
|
82
|
-
next
|
83
|
-
end
|
84
|
-
target[key] = hash[key]
|
85
|
-
end
|
86
|
-
target
|
87
|
-
end
|
88
|
-
|
89
|
-
end
|
90
|
-
|
91
67
|
# An instance of Caesars::Hash which contains the data specified by your DSL
|
92
68
|
attr_accessor :caesars_properties
|
93
69
|
|
94
|
-
class Error < RuntimeError
|
95
|
-
attr_accessor :backtrace
|
96
|
-
def initialize(obj=nil); @obj = obj; end
|
97
|
-
def message; "#{self.class}: #{@obj}"; end
|
98
|
-
end
|
99
|
-
class SyntaxError < Caesars::Error
|
100
|
-
def message
|
101
|
-
msg = "Syntax error in #{@obj}"
|
102
|
-
bt = @backtrace
|
103
|
-
msg << " in " << bt.first.scan(/\`(.+?)'/).flatten.first if bt
|
104
|
-
msg
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
70
|
def initialize(name=nil)
|
109
71
|
@caesars_name = name if name
|
110
72
|
@caesars_properties = Caesars::Hash.new
|
@@ -576,191 +538,4 @@ class Caesars
|
|
576
538
|
end
|
577
539
|
|
578
540
|
|
579
|
-
# A helper for loading a DSL from a config file.
|
580
|
-
#
|
581
|
-
# Usage:
|
582
|
-
#
|
583
|
-
# class Staff < Caesars; end;
|
584
|
-
# class StaffConfig < Caesars::Config
|
585
|
-
# dsl Staff::DSL
|
586
|
-
# end
|
587
|
-
# @config = StaffConfig.new(:path => '/path/2/staff_dsl.rb')
|
588
|
-
# p @config.staff # => <Staff:0x7ea450 ... >
|
589
|
-
#
|
590
|
-
class Caesars::Config
|
591
|
-
attr_accessor :paths
|
592
|
-
attr_reader :options
|
593
|
-
attr_reader :verbose
|
594
|
-
|
595
|
-
@@glasses = []
|
596
|
-
|
597
|
-
# Used by postprocess to tell refresh to reload all configs.
|
598
|
-
class ForceRefresh < RuntimeError
|
599
|
-
# The list of config types that need to be refreshed. This is currently
|
600
|
-
# for informational-purposes only. It does not affect which files/config
|
601
|
-
# types are refreshed. See Caesars::Config::ForcedRefresh
|
602
|
-
attr_reader :glasses
|
603
|
-
def initialize(*glasses); @glasses = glasses; end
|
604
|
-
def message; "Force refresh of: #{@glasses.join(',')}"; end
|
605
|
-
end
|
606
|
-
|
607
|
-
# +args+ is a last of config file paths to load into this instance.
|
608
|
-
# If the last argument is a hash, it's assumed to be a list of
|
609
|
-
# options. The available options are:
|
610
|
-
#
|
611
|
-
# <li>:verbose => true or false</li>
|
612
|
-
#
|
613
|
-
def initialize(*args)
|
614
|
-
# We store the options hash b/c we reapply them when we refresh.
|
615
|
-
@options = args.last.kind_of?(Hash) ? args.pop : {}
|
616
|
-
@paths = args.empty? ? [] : args
|
617
|
-
@options = {}
|
618
|
-
@forced_refreshes = 0
|
619
|
-
refresh
|
620
|
-
end
|
621
|
-
|
622
|
-
def verbose=(enable)
|
623
|
-
@verbose = enable == true
|
624
|
-
@options[:verbose] = @verbose
|
625
|
-
end
|
626
|
-
|
627
|
-
# Reset all config instance variables to nil.
|
628
|
-
def caesars_init
|
629
|
-
# Remove instance variables used to populate DSL data
|
630
|
-
keys.each { |confname| instance_variable_set("@#{confname}", nil) }
|
631
|
-
# Re-apply options
|
632
|
-
@options.each_pair do |n,v|
|
633
|
-
self.send("#{n}=", v) if respond_to?("#{n}=")
|
634
|
-
end
|
635
|
-
check_paths # make sure files exist
|
636
|
-
end
|
637
|
-
|
638
|
-
# This method is a stub. It gets called by refresh after each
|
639
|
-
# config file has be loaded. You can use it to run file specific
|
640
|
-
# processing on the configuration before it's used elsewhere.
|
641
|
-
def postprocess
|
642
|
-
end
|
643
|
-
|
644
|
-
# Clear all current configuration (sets all config instance
|
645
|
-
# variables to nil) and reload all config files in +@paths+.
|
646
|
-
# After each path is loaded, Caesars::Config.postprocess is
|
647
|
-
# called. If a ForceRefresh exception is raise, refresh is
|
648
|
-
# run again from the start. This is useful in the case
|
649
|
-
# where one DSL can affect the parsing of another. Note that
|
650
|
-
# refresh only clears the instance variables, the class vars
|
651
|
-
# for each of the DSLs are not affected so all calls to
|
652
|
-
# +forced_array+, +forced_hash+, +chill+ and +forced_ignore+
|
653
|
-
# are unaffected.
|
654
|
-
#
|
655
|
-
# Rudy has an example of forced refreshing in action. See
|
656
|
-
# the files (http://github.com/solutious/rudy):
|
657
|
-
#
|
658
|
-
# * +lib/rudy/config.rb+
|
659
|
-
# * +lib/rudy/config/objects.rb+.
|
660
|
-
#
|
661
|
-
def refresh
|
662
|
-
caesars_init # Delete all current configuration
|
663
|
-
@@glasses.each { |glass| extend glass }
|
664
|
-
|
665
|
-
begin
|
666
|
-
current_path = nil # used in error messages
|
667
|
-
@paths.each do |path|
|
668
|
-
current_path = path
|
669
|
-
puts "Loading config from #{path}" if @verbose || Caesars.debug?
|
670
|
-
dsl = File.read path
|
671
|
-
# eval so the DSL code can be executed in this namespace.
|
672
|
-
eval dsl, binding, __FILE__, __LINE__
|
673
|
-
end
|
674
|
-
|
675
|
-
# Execute Caesars::Config.postprocesses after all files are loaded.
|
676
|
-
postprocess # Can raise ForceRefresh
|
677
|
-
|
678
|
-
rescue Caesars::Config::ForceRefresh => ex
|
679
|
-
@forced_refreshes += 1
|
680
|
-
if @forced_refreshes > 3
|
681
|
-
STDERR.puts "Too many forced refreshes (#{@forced_refreshes})"
|
682
|
-
exit 9
|
683
|
-
end
|
684
|
-
STDERR.puts ex.message if @verbose || Caesars.debug?
|
685
|
-
refresh
|
686
|
-
|
687
|
-
#rescue Caesars::Error => ex
|
688
|
-
# STDERR.puts ex.message
|
689
|
-
# STDERR.puts ex.backtrace if Caesars.debug?
|
690
|
-
rescue ArgumentError, SyntaxError => ex
|
691
|
-
newex = Caesars::SyntaxError.new(current_path)
|
692
|
-
newex.backtrace = ex.backtrace
|
693
|
-
raise newex
|
694
|
-
end
|
695
|
-
end
|
696
|
-
|
697
|
-
# Checks all values of +@paths+, raises an exception for nil
|
698
|
-
# values and file paths that don't exist.
|
699
|
-
def check_paths
|
700
|
-
@paths.each do |path|
|
701
|
-
raise "You provided a nil value" unless path
|
702
|
-
raise "Config file #{path} does not exist!" unless File.exists?(path)
|
703
|
-
end
|
704
|
-
end
|
705
|
-
|
706
|
-
# Do any of the known DSLs have config data?
|
707
|
-
def empty?
|
708
|
-
keys.each do |obj|
|
709
|
-
return false if self.respond_to?(obj.to_sym)
|
710
|
-
end
|
711
|
-
true
|
712
|
-
end
|
713
|
-
|
714
|
-
# Specify a DSL class (+glass+) to include in this config.
|
715
|
-
#
|
716
|
-
# class CoolDrink < Caesars::Config
|
717
|
-
# dsl CoolDrink::Flavours::DSL
|
718
|
-
# end
|
719
|
-
#
|
720
|
-
def self.dsl(glass)
|
721
|
-
@@glasses << glass
|
722
|
-
end
|
723
|
-
|
724
|
-
# Provide a hash-like interface for Config classes.
|
725
|
-
# +name+ is the name of a DSL config.
|
726
|
-
#
|
727
|
-
# class CoolDrink < Caesars::Config
|
728
|
-
# dsl CoolDrink::Flavours::DSL
|
729
|
-
# end
|
730
|
-
#
|
731
|
-
# cd = CoolDrink.new('/path/2/config')
|
732
|
-
# cd[:flavours] # => {}
|
733
|
-
#
|
734
|
-
def [](name)
|
735
|
-
self.send(name) if respond_to?(name)
|
736
|
-
end
|
737
|
-
|
738
|
-
# Returns the list of known DSL config names.
|
739
|
-
# class CoolDrink < Caesars::Config
|
740
|
-
# dsl CoolDrink::Flavours::DSL
|
741
|
-
# end
|
742
|
-
#
|
743
|
-
# cd = CoolDrink.new('/path/2/config')
|
744
|
-
# cd.keys # => [:flavours]
|
745
|
-
#
|
746
|
-
def keys
|
747
|
-
@@glasses.collect { |glass| glass.methname }
|
748
|
-
end
|
749
|
-
|
750
|
-
# Is +name+ a known configuration type?
|
751
|
-
#
|
752
|
-
# class CoolDrink < Caesars::Config
|
753
|
-
# dsl CoolDrink::Flavours::DSL
|
754
|
-
# end
|
755
|
-
#
|
756
|
-
# cd = CoolDrink.new('/path/2/config')
|
757
|
-
# cd.has_key?(:taste) # => false
|
758
|
-
# cd.has_key?(:flavours) # => true
|
759
|
-
#
|
760
|
-
def has_key?(name)
|
761
|
-
respond_to?(name)
|
762
|
-
end
|
763
|
-
end
|
764
|
-
|
765
|
-
|
766
541
|
|
@@ -0,0 +1,190 @@
|
|
1
|
+
|
2
|
+
# A helper for loading a DSL from a config file.
|
3
|
+
#
|
4
|
+
# Usage:
|
5
|
+
#
|
6
|
+
# class Staff < Caesars; end;
|
7
|
+
# class StaffConfig < Caesars::Config
|
8
|
+
# dsl Staff::DSL
|
9
|
+
# end
|
10
|
+
# @config = StaffConfig.new('/path/2/staff_dsl.rb')
|
11
|
+
# p @config.staff # => <Staff:0x7ea450 ... >
|
12
|
+
#
|
13
|
+
class Caesars
|
14
|
+
class Config
|
15
|
+
attr_accessor :paths
|
16
|
+
attr_reader :options
|
17
|
+
attr_reader :verbose
|
18
|
+
|
19
|
+
@@glasses = []
|
20
|
+
|
21
|
+
# Used by postprocess to tell refresh to reload all configs.
|
22
|
+
class ForceRefresh < RuntimeError
|
23
|
+
# The list of config types that need to be refreshed. This is currently
|
24
|
+
# for informational-purposes only. It does not affect which files/config
|
25
|
+
# types are refreshed. See Caesars::Config::ForcedRefresh
|
26
|
+
attr_reader :glasses
|
27
|
+
def initialize(*glasses); @glasses = glasses; end
|
28
|
+
def message; "Force refresh of: #{@glasses.join(',')}"; end
|
29
|
+
end
|
30
|
+
|
31
|
+
# +args+ is a last of config file paths to load into this instance.
|
32
|
+
# If the last argument is a hash, it's assumed to be a list of
|
33
|
+
# options. The available options are:
|
34
|
+
#
|
35
|
+
# <li>:verbose => true or false</li>
|
36
|
+
#
|
37
|
+
def initialize(*args)
|
38
|
+
# We store the options hash b/c we reapply them when we refresh.
|
39
|
+
@options = args.last.kind_of?(Hash) ? args.pop : {}
|
40
|
+
@paths = args.empty? ? [] : args
|
41
|
+
@options = {}
|
42
|
+
@forced_refreshes = 0
|
43
|
+
refresh
|
44
|
+
end
|
45
|
+
|
46
|
+
def verbose=(enable)
|
47
|
+
@verbose = enable == true
|
48
|
+
@options[:verbose] = @verbose
|
49
|
+
end
|
50
|
+
|
51
|
+
# Reset all config instance variables to nil.
|
52
|
+
def caesars_init
|
53
|
+
# Remove instance variables used to populate DSL data
|
54
|
+
keys.each { |confname| instance_variable_set("@#{confname}", nil) }
|
55
|
+
# Re-apply options
|
56
|
+
@options.each_pair do |n,v|
|
57
|
+
self.send("#{n}=", v) if respond_to?("#{n}=")
|
58
|
+
end
|
59
|
+
check_paths # make sure files exist
|
60
|
+
end
|
61
|
+
|
62
|
+
# This method is a stub. It gets called by refresh after each
|
63
|
+
# config file has be loaded. You can use it to run file specific
|
64
|
+
# processing on the configuration before it's used elsewhere.
|
65
|
+
def postprocess
|
66
|
+
end
|
67
|
+
|
68
|
+
# Clear all current configuration (sets all config instance
|
69
|
+
# variables to nil) and reload all config files in +@paths+.
|
70
|
+
# After each path is loaded, Caesars::Config.postprocess is
|
71
|
+
# called. If a ForceRefresh exception is raise, refresh is
|
72
|
+
# run again from the start. This is useful in the case
|
73
|
+
# where one DSL can affect the parsing of another. Note that
|
74
|
+
# refresh only clears the instance variables, the class vars
|
75
|
+
# for each of the DSLs are not affected so all calls to
|
76
|
+
# +forced_array+, +forced_hash+, +chill+ and +forced_ignore+
|
77
|
+
# are unaffected.
|
78
|
+
#
|
79
|
+
# Rudy has an example of forced refreshing in action. See
|
80
|
+
# the files (http://github.com/solutious/rudy):
|
81
|
+
#
|
82
|
+
# * +lib/rudy/config.rb+
|
83
|
+
# * +lib/rudy/config/objects.rb+.
|
84
|
+
#
|
85
|
+
def refresh
|
86
|
+
caesars_init # Delete all current configuration
|
87
|
+
@@glasses.each { |glass| extend glass }
|
88
|
+
|
89
|
+
begin
|
90
|
+
current_path = nil # used in error messages
|
91
|
+
@paths.each do |path|
|
92
|
+
current_path = path
|
93
|
+
puts "Loading config from #{path}" if @verbose || Caesars.debug?
|
94
|
+
dsl = File.read path
|
95
|
+
# eval so the DSL code can be executed in this namespace.
|
96
|
+
eval dsl, binding, __FILE__, __LINE__
|
97
|
+
end
|
98
|
+
|
99
|
+
# Execute Caesars::Config.postprocesses after all files are loaded.
|
100
|
+
postprocess # Can raise ForceRefresh
|
101
|
+
|
102
|
+
rescue Caesars::Config::ForceRefresh => ex
|
103
|
+
@forced_refreshes += 1
|
104
|
+
if @forced_refreshes > 3
|
105
|
+
STDERR.puts "Too many forced refreshes (#{@forced_refreshes})"
|
106
|
+
exit 9
|
107
|
+
end
|
108
|
+
STDERR.puts ex.message if @verbose || Caesars.debug?
|
109
|
+
refresh
|
110
|
+
|
111
|
+
#rescue Caesars::Error => ex
|
112
|
+
# STDERR.puts ex.message
|
113
|
+
# STDERR.puts ex.backtrace if Caesars.debug?
|
114
|
+
rescue ArgumentError, SyntaxError => ex
|
115
|
+
newex = Caesars::SyntaxError.new(current_path)
|
116
|
+
newex.backtrace = ex.backtrace
|
117
|
+
raise newex
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Checks all values of +@paths+, raises an exception for nil
|
122
|
+
# values and file paths that don't exist.
|
123
|
+
def check_paths
|
124
|
+
@paths.each do |path|
|
125
|
+
raise "You provided a nil value" unless path
|
126
|
+
raise "Config file #{path} does not exist!" unless File.exists?(path)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# Do any of the known DSLs have config data?
|
131
|
+
def empty?
|
132
|
+
keys.each do |obj|
|
133
|
+
return false if self.respond_to?(obj.to_sym)
|
134
|
+
end
|
135
|
+
true
|
136
|
+
end
|
137
|
+
|
138
|
+
# Specify a DSL class (+glass+) to include in this config.
|
139
|
+
#
|
140
|
+
# class CoolDrink < Caesars::Config
|
141
|
+
# dsl CoolDrink::Flavours::DSL
|
142
|
+
# end
|
143
|
+
#
|
144
|
+
def self.dsl(glass)
|
145
|
+
@@glasses << glass
|
146
|
+
end
|
147
|
+
|
148
|
+
# Provide a hash-like interface for Config classes.
|
149
|
+
# +name+ is the name of a DSL config.
|
150
|
+
#
|
151
|
+
# class CoolDrink < Caesars::Config
|
152
|
+
# dsl CoolDrink::Flavours::DSL
|
153
|
+
# end
|
154
|
+
#
|
155
|
+
# cd = CoolDrink.new('/path/2/config')
|
156
|
+
# cd[:flavours] # => {}
|
157
|
+
#
|
158
|
+
def [](name)
|
159
|
+
self.send(name) if respond_to?(name)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns the list of known DSL config names.
|
163
|
+
# class CoolDrink < Caesars::Config
|
164
|
+
# dsl CoolDrink::Flavours::DSL
|
165
|
+
# end
|
166
|
+
#
|
167
|
+
# cd = CoolDrink.new('/path/2/config')
|
168
|
+
# cd.keys # => [:flavours]
|
169
|
+
#
|
170
|
+
def keys
|
171
|
+
@@glasses.collect { |glass| glass.methname }
|
172
|
+
end
|
173
|
+
|
174
|
+
# Is +name+ a known configuration type?
|
175
|
+
#
|
176
|
+
# class CoolDrink < Caesars::Config
|
177
|
+
# dsl CoolDrink::Flavours::DSL
|
178
|
+
# end
|
179
|
+
#
|
180
|
+
# cd = CoolDrink.new('/path/2/config')
|
181
|
+
# cd.has_key?(:taste) # => false
|
182
|
+
# cd.has_key?(:flavours) # => true
|
183
|
+
#
|
184
|
+
def has_key?(name)
|
185
|
+
respond_to?(name)
|
186
|
+
end
|
187
|
+
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
class Caesars
|
4
|
+
class Error < RuntimeError
|
5
|
+
attr_accessor :backtrace
|
6
|
+
def initialize(obj=nil); @obj = obj; end
|
7
|
+
def message; "#{self.class}: #{@obj}"; end
|
8
|
+
end
|
9
|
+
class SyntaxError < Caesars::Error
|
10
|
+
def message
|
11
|
+
msg = "Syntax error in #{@obj}"
|
12
|
+
bt = @backtrace
|
13
|
+
msg << " in " << bt.first.scan(/\`(.+?)'/).flatten.first if bt
|
14
|
+
msg
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
data/lib/caesars/hash.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
|
2
|
+
# A subclass of ::Hash that provides method names for hash parameters.
|
3
|
+
# It's like a lightweight OpenStruct.
|
4
|
+
# ch = Caesars::Hash[:tabasco => :lots!]
|
5
|
+
# puts ch.tabasco # => lots!
|
6
|
+
#
|
7
|
+
class Caesars
|
8
|
+
class Hash < HASH_TYPE
|
9
|
+
def method_missing(meth)
|
10
|
+
self[meth] if self.has_key?(meth)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Returns a clone of itself and all children cast as ::Hash objects
|
14
|
+
def to_hash(hash=self)
|
15
|
+
return hash unless hash.is_a?(Caesars::Hash) # nothing to do
|
16
|
+
target = (Caesars::HASH_TYPE)[dup]
|
17
|
+
hash.keys.each do |key|
|
18
|
+
if hash[key].is_a? Caesars::Hash
|
19
|
+
target[key] = hash[key].to_hash
|
20
|
+
next
|
21
|
+
elsif hash[key].is_a? Array
|
22
|
+
target[key] = hash[key].collect { |h| to_hash(h) }
|
23
|
+
next
|
24
|
+
end
|
25
|
+
target[key] = hash[key]
|
26
|
+
end
|
27
|
+
target
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: caesars
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Delano Mandelbaum
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-06-
|
12
|
+
date: 2009-06-08 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,6 +33,9 @@ files:
|
|
33
33
|
- bin/party.conf
|
34
34
|
- caesars.gemspec
|
35
35
|
- lib/caesars.rb
|
36
|
+
- lib/caesars/config.rb
|
37
|
+
- lib/caesars/exceptions.rb
|
38
|
+
- lib/caesars/hash.rb
|
36
39
|
- lib/caesars/orderedhash.rb
|
37
40
|
has_rdoc: true
|
38
41
|
homepage: http://github.com/delano/caesars
|