# File lib/caesars.rb, line 254
254:   def method_missing(meth, *args, &b)
255:     STDERR.puts "Caesars.method_missing: #{meth}" if Caesars.debug?
256:     add_known_symbol(meth)
257:     if Caesars.forced_ignore?(meth)
258:       STDERR.puts "Forced ignore: #{meth}" if Caesars.debug?
259:       return
260:     end
261:     
262:     # Handle the setter, attribute=
263:     if meth.to_s =~ /=$/ && @caesars_properties.has_key?(meth.to_s.chop.to_sym)
264:       return @caesars_properties[meth.to_s.chop.to_sym] = (args.size == 1) ? args.first : args
265:     end
266:     
267:     return @caesars_properties[meth] if @caesars_properties.has_key?(meth) && args.empty? && b.nil?
268:     
269:     # We there are no args and no block, we return nil. This is useful
270:     # for calls to methods on a Caesars::Hash object that don't have a
271:     # value (so we cam treat self[:someval] the same as self.someval).
272:     if args.empty? && b.nil?
273:       
274:       # We make an exception for methods that we are already expecting. 
275:       if Caesars.forced_array?(meth)
276:         return @caesars_pointer[meth] ||= Caesars::Hash.new
277:       else
278:         return nil 
279:       end
280:     end
281:     
282:     if b
283:       if Caesars.forced_array?(meth)
284:         @caesars_pointer[meth] ||= []
285:         args << b  # Forced array blocks are always chilled and at the end
286:         @caesars_pointer[meth] << args
287:       else
288:         # We loop through each of the arguments sent to "meth". 
289:         # Elements are added for each of the arguments and the
290:         # contents of the block will be applied to each one. 
291:         # This is an important feature for Rudy configs since
292:         # it allows defining several environments, roles, etc
293:         # at the same time.
294:         #     env :dev, :stage, :prod do
295:         #       ...
296:         #     end
297:         
298:         # Use the name of the method if no name is supplied. 
299:         args << meth if args.empty?
300:         
301:         args.each do |name|
302:           prev = @caesars_pointer
303:           @caesars_pointer[name] ||= Caesars::Hash.new
304:           if Caesars.chilled?(meth)
305:             @caesars_pointer[name] = b
306:           else
307:             @caesars_pointer = @caesars_pointer[name]
308:             begin
309:               b.call if b
310:             rescue ArgumentError, SyntaxError => ex
311:               STDERR.puts "CAESARS: error in #{meth} (#{args.join(', ')})" 
312:               raise ex
313:             end
314:             @caesars_pointer = prev
315:           end
316:         end
317:       end
318:       
319:     # We've seen this attribute before, add the value to the existing element    
320:     elsif @caesars_pointer.kind_of?(Hash) && @caesars_pointer[meth]
321:       
322:       if Caesars.forced_array?(meth)
323:         @caesars_pointer[meth] ||= []
324:         @caesars_pointer[meth] << args
325:       else
326:         # Make the element an Array once there's more than a single value
327:         unless @caesars_pointer[meth].is_a?(Array)
328:           @caesars_pointer[meth] = [@caesars_pointer[meth]] 
329:         end
330:         @caesars_pointer[meth] += args
331:       end
332:       
333:     elsif !args.empty?
334:       if Caesars.forced_array?(meth)
335:         @caesars_pointer[meth] = [args]
336:       else
337:         @caesars_pointer[meth] = args.size == 1 ? args.first : args
338:       end
339:     end
340:   
341:   end