# = opencascade.rb # # == Copyright (c) 2006 Thomas Sawyer # # Ruby License # # This module is free software. You may use, modify, and/or redistribute this # software under the same terms as Ruby. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. # # == Author(s) # # * Thomas Sawyer # # == Developer Notes # # TODO Think about this more! # # What about parent when descending downward? # Should parent even be part of OpenObject? # Maybe that should be in a differnt class? # # Should cascading work via hash on the fly like this? # Or perhaps converted all at once? # # Returning nil doesn't work if assigning! # Author:: Thomas Sawyer # Copyright:: Copyright (c) 2006 Thomas Sawyer # License:: Ruby License require 'facets/core/kernel/bool.rb' require 'facets/more/openobject.rb' #require 'facets/more/nullclass' # = OpenCascade # # OpenCascade is subclass of OpenObject, but differs in a few # significant ways. # # The main reason this class is labeled "cascade", every internal # Hash is trandformed into an OpenCascade dynamically upon access. # This makes it easy to create "cascading" references. # # h = { :x => { :y => { :z => 1 } } } # c = OpenCascade[h] # c.x.y.z #=> 1 # #-- # Last, when an entry is not found, 'null' is returned rather then 'nil'. # This allows for run-on entries withuot error. Eg. # # o = OpenCascade.new # o.a.b.c #=> null # # Unfortuately this requires an explict test for of nil? in 'if' conditions, # # if o.a.b.c.null? # True if null # if o.a.b.c.nil? # True if nil or null # if o.a.b.c.not? # True if nil or null or false # # So be sure to take that into account. #++ class OpenCascade < OpenObject def method_missing( sym, arg=nil ) type = sym.to_s[-1,1] name = sym.to_s.gsub(/[=!?]$/, '').to_sym if type == '=' self[name] = arg elsif type == '!' self[name] = arg self else val = self[name] val = object_class[val] if Hash === val val end end end # _____ _ # |_ _|__ ___| |_ # | |/ _ \/ __| __| # | | __/\__ \ |_ # |_|\___||___/\__| # =begin testing require 'test/unit' class TestOpenCascade1 < Test::Unit::TestCase def test_1_01 o = OpenCascade[:a=>1,:b=>2] assert_equal( 1, o.a ) assert_equal( 2, o.b ) end def test_1_02 o = OpenCascade[:a=>1,:b=>2,:c=>{:x=>9}] assert_equal( 9, o.c.x ) end def test_1_03 f0 = OpenCascade.new f0[:a] = 1 assert_equal( [[:a,1]], f0.to_a ) assert_equal( {:a=>1}, f0.to_h ) end def test_1_04 f0 = OpenCascade[:a=>1] f0[:b] = 2 assert_equal( {:a=>1,:b=>2}, f0.to_h ) end end class TestOpenCascade2 < Test::Unit::TestCase def test_02_001 f0 = OpenCascade[:f0=>"f0"] h0 = { :h0=>"h0" } assert_equal( OpenCascade[:f0=>"f0", :h0=>"h0"], f0.send(:merge,h0) ) assert_equal( {:f0=>"f0", :h0=>"h0"}, h0.merge( f0 ) ) end def test_02_002 f1 = OpenCascade[:f1=>"f1"] h1 = { :h1=>"h1" } f1.send(:update, h1) h1.update( f1 ) assert_equal( OpenCascade[:f1=>"f1", :h1=>"h1"], f1 ) assert_equal( {:f1=>"f1", :h1=>"h1"}, h1 ) end end class TestOpenCascade3 < Test::Unit::TestCase def test_01_001 fo = OpenCascade.new 99.times{ |i| fo.__send__( "n#{i}=", 1 ) } 99.times{ |i| assert_equal( 1, fo.__send__( "n#{i}" ) ) } end end =end