caesars 0.5.4 → 0.5.5
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 +10 -0
- data/bin/example +26 -2
- data/caesars.gemspec +2 -2
- data/lib/caesars.rb +128 -63
- metadata +2 -2
data/CHANGES.txt
CHANGED
@@ -1,6 +1,16 @@
|
|
1
1
|
CAESAR -- CHANGES
|
2
2
|
|
3
3
|
|
4
|
+
|
5
|
+
#### 0.5.5 (2009-04-27) ###############################
|
6
|
+
|
7
|
+
* CHANGE: Caesars.chill and Caesars.forced_hash can now be used together.
|
8
|
+
* ADDED: Print error to STDERR when a duplicate key found for forced_hash keys
|
9
|
+
* ADDED: Caesars.forced_array
|
10
|
+
* CHANGE: Caesars.method_missing now stores and returns an empty Caesars::Hash
|
11
|
+
for known methods that are called (currently only ones defined by forced_array)
|
12
|
+
|
13
|
+
|
4
14
|
#### 0.5.4 (2009-04-11) ###############################
|
5
15
|
|
6
16
|
* FIXED: find_deferred would abort early because the safety limit
|
data/bin/example
CHANGED
@@ -112,8 +112,6 @@ p @staff_fte.splashdown.sheila.salary.call(rand(100)) # => 549.77
|
|
112
112
|
# EXAMPLE 3 -- External Config file
|
113
113
|
#
|
114
114
|
|
115
|
-
require 'caesars'
|
116
|
-
|
117
115
|
class Food < Caesars
|
118
116
|
chill :order
|
119
117
|
end
|
@@ -137,3 +135,29 @@ p @config.keys # => [:food, :drink]
|
|
137
135
|
|
138
136
|
@config.refresh
|
139
137
|
|
138
|
+
|
139
|
+
# ------------------------------------------------------------------
|
140
|
+
# EXAMPLE 4 -- Forced Array
|
141
|
+
#
|
142
|
+
class Shift < Caesars
|
143
|
+
forced_array :peoples
|
144
|
+
end
|
145
|
+
|
146
|
+
include Shift::DSL
|
147
|
+
|
148
|
+
shift do
|
149
|
+
peoples :tom, :jeff, :al
|
150
|
+
compare :tom, :jeff, :al
|
151
|
+
peoples :ada, :gary, :bo
|
152
|
+
end
|
153
|
+
|
154
|
+
p @shift.peoples[0] # => [:tom, :jeff, :al]
|
155
|
+
p @shift.compare[0] # => :tom
|
156
|
+
p @shift.compare # => [:tom, :jeff, :al]
|
157
|
+
p @shift.peoples[1] # => [:ada, :gary, :bo]
|
158
|
+
p @shift.compare[1] # => :jeff
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
|
163
|
+
|
data/caesars.gemspec
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
@spec = Gem::Specification.new do |s|
|
2
2
|
s.name = %q{caesars}
|
3
|
-
s.version = "0.5.
|
4
|
-
s.date = %q{2009-04-
|
3
|
+
s.version = "0.5.5"
|
4
|
+
s.date = %q{2009-04-27}
|
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
|
|
data/lib/caesars.rb
CHANGED
@@ -7,12 +7,27 @@
|
|
7
7
|
# See bin/example
|
8
8
|
#
|
9
9
|
class Caesars
|
10
|
-
VERSION =
|
10
|
+
VERSION = 0.5
|
11
11
|
@@debug = false
|
12
|
-
|
12
|
+
@@chilled = {}
|
13
|
+
@@forced_array = {}
|
14
|
+
|
13
15
|
def Caesars.enable_debug; @@debug = true; end
|
14
16
|
def Caesars.disable_debug; @@debug = false; end
|
15
17
|
def Caesars.debug?; @@debug; end
|
18
|
+
# Is the given +name+ chilled?
|
19
|
+
# See Caesars.chill
|
20
|
+
def Caesars.chilled?(name)
|
21
|
+
return false unless name
|
22
|
+
@@chilled.has_key?(name.to_sym)
|
23
|
+
end
|
24
|
+
# Is the given +name+ a forced array?
|
25
|
+
# See Caesars.forced_array
|
26
|
+
def Caesars.forced_array?(name)
|
27
|
+
return false unless name
|
28
|
+
@@forced_array.has_key?(name.to_sym)
|
29
|
+
end
|
30
|
+
|
16
31
|
|
17
32
|
# A subclass of ::Hash that provides method names for hash parameters.
|
18
33
|
# It's like a lightweight OpenStruct.
|
@@ -46,6 +61,10 @@ class Caesars
|
|
46
61
|
# An instance of Caesars::Hash which contains the data specified by your DSL
|
47
62
|
attr_accessor :caesars_properties
|
48
63
|
|
64
|
+
class Error < RuntimeError
|
65
|
+
def initialize(obj=nil); @obj = obj; end
|
66
|
+
def message; "#{self.class}: #{@obj}"; end
|
67
|
+
end
|
49
68
|
|
50
69
|
def initialize(name=nil)
|
51
70
|
@caesars_name = name if name
|
@@ -207,81 +226,76 @@ class Caesars
|
|
207
226
|
@caesars_properties[name] = value
|
208
227
|
end
|
209
228
|
|
210
|
-
# This method handles all of the attributes that
|
229
|
+
# This method handles all of the attributes that are not forced hashes
|
211
230
|
# It's used in the DSL for handling attributes dyanamically (that weren't defined
|
212
|
-
# previously) and also in subclasses of
|
231
|
+
# previously) and also in subclasses of Caesars for returning the appropriate
|
213
232
|
# attribute values.
|
214
233
|
def method_missing(meth, *args, &b)
|
234
|
+
|
215
235
|
# Handle the setter, attribute=
|
216
236
|
if meth.to_s =~ /=$/ && @caesars_properties.has_key?(meth.to_s.chop.to_sym)
|
217
237
|
return @caesars_properties[meth.to_s.chop.to_sym] = (args.size == 1) ? args.first : args
|
218
238
|
end
|
219
239
|
|
220
240
|
return @caesars_properties[meth] if @caesars_properties.has_key?(meth) && args.empty? && b.nil?
|
221
|
-
|
241
|
+
|
242
|
+
# We there are no args and no block, we return nil. This is useful
|
243
|
+
# for calls to methods on a Caesars::Hash object that don't have a
|
244
|
+
# value (so we cam treat self[:someval] the same as self.someval).
|
245
|
+
if args.empty? && b.nil?
|
246
|
+
|
247
|
+
# We make an exception for methods that we are already expecting.
|
248
|
+
if Caesars.forced_array?(meth)
|
249
|
+
return @caesars_pointer[meth] ||= Caesars::Hash.new
|
250
|
+
else
|
251
|
+
return nil
|
252
|
+
end
|
253
|
+
end
|
222
254
|
|
223
255
|
if b
|
224
256
|
# Use the name of the bloody method if no name is supplied.
|
225
257
|
args << meth if args.empty?
|
258
|
+
|
226
259
|
args.each do |name|
|
227
260
|
prev = @caesars_pointer
|
228
|
-
#(@caesars_pointer[:"#{meth}_values"] ||= []) << name
|
229
261
|
@caesars_pointer[name] ||= Caesars::Hash.new
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
262
|
+
if Caesars.chilled?(meth)
|
263
|
+
@caesars_pointer[name] = b
|
264
|
+
else
|
265
|
+
@caesars_pointer = @caesars_pointer[name]
|
266
|
+
begin
|
267
|
+
b.call if b
|
268
|
+
rescue ArgumentError, SyntaxError => ex
|
269
|
+
STDERR.puts "CAESARS: error in #{meth} (#{args.join(', ')})"
|
270
|
+
raise ex
|
271
|
+
end
|
272
|
+
@caesars_pointer = prev
|
236
273
|
end
|
237
|
-
@caesars_pointer = prev
|
238
274
|
end
|
239
|
-
|
275
|
+
|
276
|
+
# We've seen this attribute before, add the valued to the existing element
|
240
277
|
elsif @caesars_pointer.kind_of?(Hash) && @caesars_pointer[meth]
|
241
278
|
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
# A class method which can be used by subclasses to specify which methods
|
251
|
-
# should delay execution of their blocks. Here's an example:
|
252
|
-
#
|
253
|
-
# class Food < Caesars
|
254
|
-
# chill :count
|
255
|
-
# end
|
256
|
-
#
|
257
|
-
# food do
|
258
|
-
# taste :delicious
|
259
|
-
# count do |items|
|
260
|
-
# puts items + 2
|
261
|
-
# end
|
262
|
-
# end
|
263
|
-
#
|
264
|
-
# @config.food.count.call(3) # => 5
|
265
|
-
#
|
266
|
-
def self.chill(caesars_meth)
|
267
|
-
module_eval %Q{
|
268
|
-
def #{caesars_meth}(*caesars_names,&b)
|
269
|
-
# caesars.toplevel.unnamed_chilled_attribute
|
270
|
-
return @caesars_properties[:'#{caesars_meth}'] if @caesars_properties.has_key?(:'#{caesars_meth}') && caesars_names.empty? && b.nil?
|
271
|
-
|
272
|
-
# Use the name of the chilled method if no name is supplied.
|
273
|
-
caesars_names << :'#{caesars_meth}' if caesars_names.empty?
|
274
|
-
|
275
|
-
caesars_names.each do |name|
|
276
|
-
@caesars_pointer[name] = b
|
279
|
+
if Caesars.forced_array?(meth)
|
280
|
+
@caesars_pointer[meth] ||= []
|
281
|
+
@caesars_pointer[meth] << args
|
282
|
+
else
|
283
|
+
# Make the element an Array once there's more than a single value
|
284
|
+
unless @caesars_pointer[meth].is_a?(Array)
|
285
|
+
@caesars_pointer[meth] = [@caesars_pointer[meth]]
|
277
286
|
end
|
287
|
+
@caesars_pointer[meth] += args
|
288
|
+
end
|
278
289
|
|
279
|
-
|
290
|
+
elsif !args.empty?
|
291
|
+
if Caesars.forced_array?(meth)
|
292
|
+
@caesars_pointer[meth] = [args]
|
293
|
+
else
|
294
|
+
@caesars_pointer[meth] = args.size == 1 ? args.first : args
|
280
295
|
end
|
281
|
-
|
282
|
-
nil
|
283
|
-
end
|
296
|
+
end
|
284
297
|
|
298
|
+
end
|
285
299
|
|
286
300
|
|
287
301
|
# Force the specified keyword to always be treated as a hash.
|
@@ -311,16 +325,64 @@ class Caesars
|
|
311
325
|
prev = @caesars_pointer
|
312
326
|
@caesars_pointer[:'#{caesars_meth}'] ||= Caesars::Hash.new
|
313
327
|
hash = Caesars::Hash.new
|
314
|
-
@caesars_pointer
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
328
|
+
if @caesars_pointer[:'#{caesars_meth}'].has_key?(caesars_name)
|
329
|
+
STDERR.puts "duplicate key ignored: \#{caesars_name}"
|
330
|
+
return
|
331
|
+
end
|
332
|
+
|
333
|
+
@caesars_pointer = hash # This is needed but I don't know why
|
334
|
+
if b
|
335
|
+
if Caesars.chilled?(:'#{caesars_meth}')
|
336
|
+
@caesars_pointer[:'#{caesars_meth}'][caesars_name] = b
|
337
|
+
else
|
338
|
+
b.call
|
339
|
+
@caesars_pointer = prev
|
340
|
+
@caesars_pointer[:'#{caesars_meth}'][caesars_name] = hash
|
341
|
+
end
|
342
|
+
@caesars_pointer = prev
|
343
|
+
end
|
319
344
|
end
|
320
345
|
}
|
321
346
|
nil
|
322
|
-
|
323
|
-
|
347
|
+
end
|
348
|
+
|
349
|
+
# Specify a method that should delay execution of its block.
|
350
|
+
# Here's an example:
|
351
|
+
#
|
352
|
+
# class Food < Caesars
|
353
|
+
# chill :count
|
354
|
+
# end
|
355
|
+
#
|
356
|
+
# food do
|
357
|
+
# taste :delicious
|
358
|
+
# count do |items|
|
359
|
+
# puts items + 2
|
360
|
+
# end
|
361
|
+
# end
|
362
|
+
#
|
363
|
+
# @config.food.count.call(3) # => 5
|
364
|
+
#
|
365
|
+
def self.chill(caesars_meth)
|
366
|
+
@@chilled[caesars_meth.to_sym] = true
|
367
|
+
nil
|
368
|
+
end
|
369
|
+
|
370
|
+
# Specify a method that should store it's args as nested Arrays
|
371
|
+
# Here's an example:
|
372
|
+
#
|
373
|
+
# class Food < Caesars
|
374
|
+
# forced_array :sauce
|
375
|
+
# end
|
376
|
+
#
|
377
|
+
# food do
|
378
|
+
# taste :delicious
|
379
|
+
# sauce
|
380
|
+
# end
|
381
|
+
#
|
382
|
+
# @config.food.count.call(3) # => 5
|
383
|
+
def self.forced_array(caesars_meth)
|
384
|
+
@@forced_array[caesars_meth.to_sym] = true
|
385
|
+
nil
|
324
386
|
end
|
325
387
|
|
326
388
|
# Executes automatically when Caesars is subclassed. This creates the
|
@@ -439,10 +501,13 @@ class Caesars::Config
|
|
439
501
|
|
440
502
|
postprocess
|
441
503
|
|
504
|
+
rescue Caesars::Error => ex
|
505
|
+
STDERR.puts ex.message
|
506
|
+
STDERR.puts ex.backtrace if Caesars.debug?
|
442
507
|
rescue ArgumentError, SyntaxError => ex
|
443
|
-
puts "Syntax error in #{path}."
|
444
|
-
puts ex.message
|
445
|
-
puts ex.backtrace if Caesars.debug?
|
508
|
+
STDERR.puts "Syntax error in #{path}."
|
509
|
+
STDERR.puts ex.message
|
510
|
+
STDERR.puts ex.backtrace if Caesars.debug?
|
446
511
|
exit 1
|
447
512
|
end
|
448
513
|
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.5.
|
4
|
+
version: 0.5.5
|
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-04-
|
12
|
+
date: 2009-04-27 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|