caesars 0.5.4 → 0.5.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. data/CHANGES.txt +10 -0
  2. data/bin/example +26 -2
  3. data/caesars.gemspec +2 -2
  4. data/lib/caesars.rb +128 -63
  5. 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"
4
- s.date = %q{2009-04-11}
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 = "0.5.4"
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 do not contain blocks.
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 Caesar for returning the appropriate
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
- return nil if args.empty? && b.nil?
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
- @caesars_pointer = @caesars_pointer[name]
231
- begin
232
- b.call if b
233
- rescue ArgumentError, SyntaxError => ex
234
- STDERR.puts "CAESARS: error in #{meth} (#{args.join(', ')})"
235
- raise ex
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
- @caesars_pointer[meth] = [@caesars_pointer[meth]] unless @caesars_pointer[meth].is_a?(Array)
243
- @caesars_pointer[meth] += args
244
- elsif !args.empty?
245
- @caesars_pointer[meth] = args.size == 1 ? args.first : args
246
- end
247
-
248
- end
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
- @caesars_pointer[:'#{caesars_meth}']
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 = hash
315
- b.call if b
316
- @caesars_pointer = prev
317
- @caesars_pointer[:'#{caesars_meth}'][caesars_name] = hash
318
- @caesars_pointer = prev
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
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-11 00:00:00 -04:00
12
+ date: 2009-04-27 00:00:00 -04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15