og 0.28.0 → 0.29.0
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/ProjectInfo +2 -2
- data/README +1 -1
- data/doc/RELEASES +34 -0
- data/lib/glue/cacheable.rb +3 -1
- data/lib/glue/hierarchical.rb +3 -3
- data/lib/glue/orderable.rb +1 -1
- data/lib/glue/taggable.rb +71 -21
- data/lib/glue/timestamped.rb +2 -2
- data/lib/og.rb +16 -3
- data/lib/og/entity.rb +58 -10
- data/lib/og/ez/clause.rb +2 -1
- data/lib/og/manager.rb +38 -7
- data/lib/og/relation/joins_many.rb +1 -1
- data/lib/og/store/mysql.rb +2 -18
- data/lib/og/store/psql.rb +2 -1
- data/lib/og/store/sql.rb +79 -26
- data/lib/og/test/assertions.rb +1 -1
- data/lib/og/test/testcase.rb +3 -3
- data/test/glue/tc_revisable.rb +1 -1
- data/test/og/mixin/tc_hierarchical.rb +2 -0
- data/test/og/mixin/tc_orderable.rb +2 -3
- data/test/og/mixin/tc_taggable.rb +8 -11
- data/test/og/mixin/tc_timestamped.rb +1 -1
- data/test/og/store/tc_sti.rb +53 -0
- data/test/og/tc_aggregations_calculations.rb +44 -0
- data/test/og/tc_cacheable.rb +164 -29
- data/test/og/tc_inheritance.rb +4 -1
- data/test/og/tc_multi_validations.rb +1 -0
- data/test/og/tc_override.rb +6 -0
- metadata +11 -10
- data/lib/og/store/alpha/kirby.rb +0 -284
    
        data/lib/og/store/mysql.rb
    CHANGED
    
    | @@ -67,24 +67,6 @@ module MysqlUtils | |
| 67 67 | 
             
                return nil unless str
         | 
| 68 68 | 
             
                return Mysql.quote(str)
         | 
| 69 69 | 
             
              end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
              def quote(val)
         | 
| 72 | 
            -
                case val
         | 
| 73 | 
            -
                  when Fixnum, Integer, Float
         | 
| 74 | 
            -
                    val ? val.to_s : 'NULL'
         | 
| 75 | 
            -
                  when String
         | 
| 76 | 
            -
                    val ? "'#{escape(val)}'" : 'NULL'
         | 
| 77 | 
            -
                  when Time
         | 
| 78 | 
            -
                    val ? "'#{timestamp(val)}'" : 'NULL'
         | 
| 79 | 
            -
                  when Date
         | 
| 80 | 
            -
                    val ? "'#{date(val)}'" : 'NULL'
         | 
| 81 | 
            -
                  when TrueClass
         | 
| 82 | 
            -
                    val ? "'1'" : 'NULL'
         | 
| 83 | 
            -
                  else
         | 
| 84 | 
            -
                    # gmosx: keep the '' for nil symbols.
         | 
| 85 | 
            -
                    val ? escape(val.to_yaml) : ''
         | 
| 86 | 
            -
                end
         | 
| 87 | 
            -
              end
         | 
| 88 70 | 
             
            end
         | 
| 89 71 |  | 
| 90 72 | 
             
            # A Store that persists objects into a MySQL database.
         | 
| @@ -110,6 +92,7 @@ class MysqlStore < SqlStore | |
| 110 92 | 
             
                # gmosx: system is used to avoid shell expansion.
         | 
| 111 93 | 
             
                system 'mysqladmin', '-f', "--user=#{options[:user]}", 
         | 
| 112 94 | 
             
                    "--password=#{options[:password]}", 
         | 
| 95 | 
            +
                    "--host=#{options[:address]}",
         | 
| 113 96 | 
             
                    'create', options[:name]    
         | 
| 114 97 | 
             
                super
         | 
| 115 98 | 
             
              end
         | 
| @@ -117,6 +100,7 @@ class MysqlStore < SqlStore | |
| 117 100 | 
             
              def self.destroy(options)
         | 
| 118 101 | 
             
                system 'mysqladmin', '-f', "--user=#{options[:user]}", 
         | 
| 119 102 | 
             
                    "--password=#{options[:password]}", 'drop', 
         | 
| 103 | 
            +
                    "--host=#{options[:address]}",
         | 
| 120 104 | 
             
                    options[:name]
         | 
| 121 105 | 
             
                super
         | 
| 122 106 | 
             
              end
         | 
    
        data/lib/og/store/psql.rb
    CHANGED
    
    | @@ -516,6 +516,7 @@ class PsqlStore < SqlStore | |
| 516 516 | 
             
                  deleted += 1
         | 
| 517 517 | 
             
                end
         | 
| 518 518 |  | 
| 519 | 
            +
                nullified_relations = 0
         | 
| 519 520 | 
             
                sql_hash[:create].each do |sql|    
         | 
| 520 521 | 
             
                  con_retry = true
         | 
| 521 522 | 
             
                  begin
         | 
| @@ -572,7 +573,7 @@ class PsqlStore < SqlStore | |
| 572 573 | 
             
                  text << "#{deleted} constraints were deleted, " if deleted != 0
         | 
| 573 574 | 
             
                  if broken_relations != 0
         | 
| 574 575 | 
             
                    text.gsub!(/,([^,]+)$/,' and \1')
         | 
| 575 | 
            -
                    text << "#{broken_relations} relations were broken | 
| 576 | 
            +
                    text << "#{broken_relations} relations were broken causing "
         | 
| 576 577 | 
             
                    if nullified_relations != 0
         | 
| 577 578 | 
             
                      text << "#{nullified_relations} relations to have non-existant foreign keys set to null"
         | 
| 578 579 | 
             
                      text << (deleted_relations == 0 ? ", " : " and ")
         | 
    
        data/lib/og/store/sql.rb
    CHANGED
    
    | @@ -97,23 +97,40 @@ module SqlUtils | |
| 97 97 |  | 
| 98 98 | 
             
              # Escape the various Ruby types.
         | 
| 99 99 |  | 
| 100 | 
            -
              def quote( | 
| 100 | 
            +
              def quote(vals)
         | 
| 101 | 
            +
                vals = [vals] unless vals.is_a?(Array)
         | 
| 102 | 
            +
                quoted = vals.inject("") do |s,val|
         | 
| 103 | 
            +
                  s += case val
         | 
| 104 | 
            +
                    when Fixnum, Integer, Float
         | 
| 105 | 
            +
                      val ? val.to_s : 'NULL'
         | 
| 106 | 
            +
                    when String
         | 
| 107 | 
            +
                      val ? "'#{escape(val)}'" : 'NULL'
         | 
| 108 | 
            +
                    when Time
         | 
| 109 | 
            +
                      val ? "'#{timestamp(val)}'" : 'NULL'
         | 
| 110 | 
            +
                    when Date
         | 
| 111 | 
            +
                      val ? "'#{date(val)}'" : 'NULL'
         | 
| 112 | 
            +
                    when TrueClass
         | 
| 113 | 
            +
                      val ? "'t'" : 'NULL'
         | 
| 114 | 
            +
                    else
         | 
| 115 | 
            +
                      # gmosx: keep the '' for nil symbols.
         | 
| 116 | 
            +
                      val ? escape(val.to_yaml) : ''
         | 
| 117 | 
            +
                  end + ','
         | 
| 118 | 
            +
                end
         | 
| 119 | 
            +
                quoted.chop!
         | 
| 120 | 
            +
                vals.size > 1 ? "(#{quoted})" : quoted
         | 
| 121 | 
            +
              end
         | 
| 122 | 
            +
             | 
| 123 | 
            +
              # Escape the Array Ruby type.
         | 
| 124 | 
            +
             | 
| 125 | 
            +
              def quote_array(val)
         | 
| 101 126 | 
             
                case val
         | 
| 102 | 
            -
                  when  | 
| 103 | 
            -
                    val  | 
| 104 | 
            -
                  when String
         | 
| 105 | 
            -
                    val ? "'#{escape(val)}'" : 'NULL'
         | 
| 106 | 
            -
                  when Time
         | 
| 107 | 
            -
                    val ? "'#{timestamp(val)}'" : 'NULL'
         | 
| 108 | 
            -
                  when Date
         | 
| 109 | 
            -
                    val ? "'#{date(val)}'" : 'NULL'
         | 
| 110 | 
            -
                  when TrueClass
         | 
| 111 | 
            -
                    val ? "'t'" : 'NULL'
         | 
| 127 | 
            +
                  when Array
         | 
| 128 | 
            +
                    val.collect{ |v| quotea(v) }.join(',')
         | 
| 112 129 | 
             
                  else
         | 
| 113 | 
            -
                     | 
| 114 | 
            -
                    val ? escape(val.to_yaml) : ''
         | 
| 130 | 
            +
                    quote(val)
         | 
| 115 131 | 
             
                end
         | 
| 116 132 | 
             
              end
         | 
| 133 | 
            +
              alias_method :quotea, :quote_array
         | 
| 117 134 |  | 
| 118 135 | 
             
              # Apply table name conventions to a class name.
         | 
| 119 136 |  | 
| @@ -354,7 +371,7 @@ class SqlStore < Store | |
| 354 371 |  | 
| 355 372 | 
             
              def load(pk, klass)
         | 
| 356 373 | 
             
                pk_field = klass.primary_key.field || klass.primary_key.symbol
         | 
| 357 | 
            -
                sql = "SELECT * FROM #{klass::OGTABLE} WHERE #{pk_field}=#{pk}"
         | 
| 374 | 
            +
                sql = "SELECT * FROM #{klass::OGTABLE} WHERE #{pk_field}=#{pk.to_i}"
         | 
| 358 375 | 
             
                sql << " AND ogtype='#{klass}'" if klass.schema_inheritance_child?
         | 
| 359 376 | 
             
                res = query sql
         | 
| 360 377 | 
             
                read_one(res, klass)
         | 
| @@ -365,7 +382,7 @@ class SqlStore < Store | |
| 365 382 |  | 
| 366 383 | 
             
              def reload(obj, pk)
         | 
| 367 384 | 
             
                raise 'Cannot reload unmanaged object' unless obj.saved?
         | 
| 368 | 
            -
                sql = "SELECT * FROM #{obj.class.table} WHERE #{obj.class.pk_symbol}=#{pk}"
         | 
| 385 | 
            +
                sql = "SELECT * FROM #{obj.class.table} WHERE #{obj.class.pk_symbol}=#{pk.to_i}"
         | 
| 369 386 | 
             
                sql << " AND ogtype='#{obj.class}'" if obj.class.schema_inheritance_child?
         | 
| 370 387 | 
             
                res = query sql
         | 
| 371 388 | 
             
                obj.og_read(res.next, 0)
         | 
| @@ -441,8 +458,8 @@ class SqlStore < Store | |
| 441 458 |  | 
| 442 459 | 
             
              def find_one(options)
         | 
| 443 460 | 
             
                klass = options[:class]
         | 
| 444 | 
            -
            # gmosx, THINK: should not set this by default.
         | 
| 445 | 
            -
            # | 
| 461 | 
            +
                # gmosx, THINK: should not set this by default.
         | 
| 462 | 
            +
                # options[:limit] ||= 1        
         | 
| 446 463 | 
             
                sql = resolve_options(klass, options)
         | 
| 447 464 | 
             
                read_one(query(sql), klass, options)
         | 
| 448 465 | 
             
              end
         | 
| @@ -464,14 +481,21 @@ class SqlStore < Store | |
| 464 481 | 
             
              end
         | 
| 465 482 | 
             
              alias_method :find_by_sql_one, :select_one
         | 
| 466 483 |  | 
| 467 | 
            -
              # Perform an aggregation over query results.
         | 
| 484 | 
            +
              # Perform an aggregation or calculation over query results.
         | 
| 485 | 
            +
              # This low level method is used by the Entity 
         | 
| 486 | 
            +
              # calculation / aggregation methods.
         | 
| 487 | 
            +
              # 
         | 
| 488 | 
            +
              # === Example
         | 
| 489 | 
            +
              #
         | 
| 490 | 
            +
              # calculate 'COUNT(*)'
         | 
| 491 | 
            +
              # calculate 'MIN(age)'
         | 
| 492 | 
            +
              # calculate 'SUM(age)', :group => :name
         | 
| 468 493 |  | 
| 469 | 
            -
              def aggregate(options)
         | 
| 494 | 
            +
              def aggregate(term = 'COUNT(*)', options = {})
         | 
| 470 495 | 
             
                if options.is_a?(String)
         | 
| 471 496 | 
             
                  sql = options
         | 
| 472 497 | 
             
                else
         | 
| 473 | 
            -
                   | 
| 474 | 
            -
                  sql = "SELECT #{aggregate} FROM #{options[:class].table}"
         | 
| 498 | 
            +
                  sql = "SELECT #{term} FROM #{options[:class].table}"
         | 
| 475 499 | 
             
                  if condition = options[:condition]
         | 
| 476 500 | 
             
                    sql << " WHERE #{condition}"
         | 
| 477 501 | 
             
                    sql << " AND " if options[:class].schema_inheritance_child?
         | 
| @@ -479,11 +503,38 @@ class SqlStore < Store | |
| 479 503 | 
             
                    sql << " WHERE " if options[:class].schema_inheritance_child?
         | 
| 480 504 | 
             
                  end
         | 
| 481 505 | 
             
                  sql << "ogtype='#{options[:class]}'" if options[:class].schema_inheritance_child?
         | 
| 506 | 
            +
                  if group = options[:group]
         | 
| 507 | 
            +
                    sql << " GROUP BY #{group}"
         | 
| 508 | 
            +
                  end
         | 
| 509 | 
            +
                  if extra = options[:extra_sql]
         | 
| 510 | 
            +
                    sql << " {extra}"
         | 
| 511 | 
            +
                  end        
         | 
| 512 | 
            +
                end
         | 
| 513 | 
            +
               
         | 
| 514 | 
            +
                if group
         | 
| 515 | 
            +
                  # This is an aggregation, so return the calculated values
         | 
| 516 | 
            +
                  # as an array.
         | 
| 517 | 
            +
                  values = []
         | 
| 518 | 
            +
                  res = query(sql)
         | 
| 519 | 
            +
                  res.each_row do |row, idx|
         | 
| 520 | 
            +
                    values << row[0].to_f 
         | 
| 521 | 
            +
                  end
         | 
| 522 | 
            +
                  return values
         | 
| 523 | 
            +
                else
         | 
| 524 | 
            +
                  #--
         | 
| 525 | 
            +
                  # gmosx, TODO: don't convert to float by default, perhaps
         | 
| 526 | 
            +
                  # should consult an option.
         | 
| 527 | 
            +
                  #++ 
         | 
| 528 | 
            +
                  return query(sql).first_value.to_f
         | 
| 482 529 | 
             
                end
         | 
| 530 | 
            +
              end
         | 
| 531 | 
            +
              alias_method :calculate, :aggregate
         | 
| 483 532 |  | 
| 484 | 
            -
             | 
| 533 | 
            +
              # Perform a count query.
         | 
| 534 | 
            +
              
         | 
| 535 | 
            +
              def count(options = {})
         | 
| 536 | 
            +
                calculate('COUNT(*)', options).to_i
         | 
| 485 537 | 
             
              end
         | 
| 486 | 
            -
              alias_method :count, :aggregate
         | 
| 487 538 |  | 
| 488 539 | 
             
              # Relate two objects through an intermediate join table.
         | 
| 489 540 | 
             
              # Typically used in joins_many and many_to_many relations.
         | 
| @@ -605,7 +656,7 @@ private | |
| 605 656 | 
             
                  # holds the class name.
         | 
| 606 657 | 
             
                  fields << "ogtype VARCHAR(30)"
         | 
| 607 658 |  | 
| 608 | 
            -
                  for desc in klass.descendents
         | 
| 659 | 
            +
                  for desc in klass.schema_inheritance_root_class.descendents
         | 
| 609 660 | 
             
                    properties.update(desc.properties)
         | 
| 610 661 | 
             
                  end
         | 
| 611 662 | 
             
                end
         | 
| @@ -925,7 +976,9 @@ private | |
| 925 976 | 
             
                  if condition.is_a?(Array)
         | 
| 926 977 | 
             
                    args = condition.dup
         | 
| 927 978 | 
             
                    str = args.shift
         | 
| 928 | 
            -
                     | 
| 979 | 
            +
                    # ? handles a single type.
         | 
| 980 | 
            +
                    # ?* handles an array.
         | 
| 981 | 
            +
                    args.each { |arg| str.sub!(/\?\*/, quotea(arg)); str.sub!(/\?/, quote(arg)) }
         | 
| 929 982 | 
             
                    condition = str
         | 
| 930 983 | 
             
                  end
         | 
| 931 984 |  | 
| @@ -968,7 +1021,7 @@ private | |
| 968 1021 |  | 
| 969 1022 | 
             
              # Dynamicaly deserializes a result set row into an object.
         | 
| 970 1023 | 
             
              # Used for specialized queries or join queries. Please
         | 
| 971 | 
            -
              #  | 
| 1024 | 
            +
              # note that this deserialization method is slower than the
         | 
| 972 1025 | 
             
              # precompiled og_read method.
         | 
| 973 1026 |  | 
| 974 1027 | 
             
              def read_row(obj, res, res_row, row)
         | 
    
        data/lib/og/test/assertions.rb
    CHANGED
    
    
    
        data/lib/og/test/testcase.rb
    CHANGED
    
    | @@ -20,9 +20,9 @@ class TestCase | |
| 20 20 | 
             
              def fixture(*classes)
         | 
| 21 21 |  | 
| 22 22 | 
             
                for klass in classes
         | 
| 23 | 
            -
                  f = Fixture.new(klass)
         | 
| 23 | 
            +
                  f = Glue::Fixture.new(klass)
         | 
| 24 24 | 
             
                  instance_variable_set "@#{klass.to_s.demodulize.underscore.pluralize}", f
         | 
| 25 | 
            -
                  Fixtures[klass] = f
         | 
| 25 | 
            +
                  Glue::Fixtures[klass] = f
         | 
| 26 26 |  | 
| 27 27 | 
             
                  # create variables for the fixture objects.
         | 
| 28 28 |  | 
| @@ -40,7 +40,7 @@ class TestCase | |
| 40 40 | 
             
                fixture(*classes)
         | 
| 41 41 |  | 
| 42 42 | 
             
                for klass in classes
         | 
| 43 | 
            -
                  f = Fixtures[klass]
         | 
| 43 | 
            +
                  f = Glue::Fixtures[klass]
         | 
| 44 44 |  | 
| 45 45 | 
             
                  for obj in f.objects
         | 
| 46 46 | 
             
                    obj.save
         | 
    
        data/test/glue/tc_revisable.rb
    CHANGED
    
    
| @@ -61,6 +61,7 @@ class TC_OgHierarchical < Test::Unit::TestCase # :nodoc: all | |
| 61 61 |  | 
| 62 62 | 
             
                c1.reload
         | 
| 63 63 |  | 
| 64 | 
            +
            =begin
         | 
| 64 65 | 
             
                Comment.all(:order => "lft, rgt").each { |c|
         | 
| 65 66 | 
             
                  puts sprintf("%3d %3d %s", c.lft, c.rgt, c.body)
         | 
| 66 67 | 
             
                  # p c  
         | 
| @@ -71,6 +72,7 @@ class TC_OgHierarchical < Test::Unit::TestCase # :nodoc: all | |
| 71 72 | 
             
                c1.full_comments(:order => "lft, rgt").each { |c| puts c.body }
         | 
| 72 73 | 
             
                puts '--3'
         | 
| 73 74 | 
             
                c1.direct_comments(:order => "lft, rgt").each { |c| puts c.body }
         | 
| 75 | 
            +
            =end
         | 
| 74 76 |  | 
| 75 77 | 
             
                assert_equal 6, c1.full_comments.size
         | 
| 76 78 | 
             
                assert_equal 5, c1.comments.size
         | 
| @@ -34,7 +34,7 @@ class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all | |
| 34 34 | 
             
                property :body, String
         | 
| 35 35 | 
             
                belongs_to :article, Article
         | 
| 36 36 |  | 
| 37 | 
            -
                is Orderable, :scope => :article
         | 
| 37 | 
            +
                is Glue::Orderable, :scope => :article
         | 
| 38 38 |  | 
| 39 39 | 
             
                def initialize(body = nil)
         | 
| 40 40 | 
             
                  @body = body
         | 
| @@ -48,7 +48,7 @@ class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all | |
| 48 48 |  | 
| 49 49 | 
             
              class Track
         | 
| 50 50 | 
             
                prop :name, String
         | 
| 51 | 
            -
                is Orderable, :scope => :playlist
         | 
| 51 | 
            +
                is Glue::Orderable, :scope => :playlist
         | 
| 52 52 |  | 
| 53 53 | 
             
                belongs_to Playlist
         | 
| 54 54 |  | 
| @@ -62,7 +62,6 @@ class TestCaseOgOrderable < Test::Unit::TestCase # :nodoc: all | |
| 62 62 |  | 
| 63 63 | 
             
              def test_all
         | 
| 64 64 | 
             
                a = Article.create('article')
         | 
| 65 | 
            -
                a.save
         | 
| 66 65 |  | 
| 67 66 | 
             
                c1 = Comment.create('1')
         | 
| 68 67 | 
             
                a.comments << c1
         | 
| @@ -1,3 +1,5 @@ | |
| 1 | 
            +
            $DBG = true
         | 
| 2 | 
            +
             | 
| 1 3 | 
             
            require File.join(File.dirname(__FILE__), '..', 'CONFIG.rb')
         | 
| 2 4 |  | 
| 3 5 | 
             
            require 'rubygems'
         | 
| @@ -8,16 +10,6 @@ require 'ostruct' | |
| 8 10 | 
             
            require 'og'
         | 
| 9 11 | 
             
            require 'glue/taggable'
         | 
| 10 12 |  | 
| 11 | 
            -
            =begin
         | 
| 12 | 
            -
            $og = Og.setup(
         | 
| 13 | 
            -
              :store => 'mysql',
         | 
| 14 | 
            -
              :name => 'test',
         | 
| 15 | 
            -
              :user => 'root',
         | 
| 16 | 
            -
              :password => 'navelrulez',
         | 
| 17 | 
            -
              :destroy => true
         | 
| 18 | 
            -
            )
         | 
| 19 | 
            -
            =end
         | 
| 20 | 
            -
             | 
| 21 13 | 
             
            class TestOgTaggable < Test::Unit::TestCase # :nodoc: all
         | 
| 22 14 |  | 
| 23 15 | 
             
              class Article
         | 
| @@ -43,7 +35,9 @@ class TestOgTaggable < Test::Unit::TestCase # :nodoc: all | |
| 43 35 | 
             
                a3 = Article.create('George')
         | 
| 44 36 | 
             
                a3.tag('phd name')
         | 
| 45 37 | 
             
                a3.save
         | 
| 46 | 
            -
             | 
| 38 | 
            +
             | 
| 39 | 
            +
             | 
| 40 | 
            +
                assert_equal 6, Tag.count
         | 
| 47 41 | 
             
                assert_equal 3, a1.tags.size 
         | 
| 48 42 | 
             
                assert a1.tag_names.include?('navel')
         | 
| 49 43 |  | 
| @@ -63,6 +57,9 @@ class TestOgTaggable < Test::Unit::TestCase # :nodoc: all | |
| 63 57 |  | 
| 64 58 | 
             
                res = Article.find_with_any_tag('navel', 'gmosx', 'phd')
         | 
| 65 59 | 
             
                assert_equal 3, res.size
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                a1.delete_all_tags
         | 
| 62 | 
            +
                assert_equal 0, a1.tags.size
         | 
| 66 63 |  | 
| 67 64 | 
             
            =begin
         | 
| 68 65 | 
             
                TODO:
         | 
| @@ -0,0 +1,53 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), '..', 'CONFIG.rb')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'test/unit'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            require 'og'
         | 
| 6 | 
            +
            require 'og/store/sql'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            class TC_Sti < Test::Unit::TestCase
         | 
| 9 | 
            +
              class StiParent
         | 
| 10 | 
            +
                property :one
         | 
| 11 | 
            +
                property :two
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                schema_inheritance
         | 
| 14 | 
            +
              end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              class StiChild < StiParent
         | 
| 17 | 
            +
                property :three
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              def setup
         | 
| 21 | 
            +
                @store = Og::SqlStore.new(nil)
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def teardown
         | 
| 25 | 
            +
                @store = nil
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              def test_fields_for_class_child
         | 
| 29 | 
            +
                fields = @store.__send__(:fields_for_class, StiChild)
         | 
| 30 | 
            +
                field_names = fields.map {|f| name, * = f.split(/\s/); name}
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                msg = "Sti Child not inheiriting parent fields"
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                assert_equal(5, field_names.size, msg)
         | 
| 35 | 
            +
                assert(field_names.member?(:one.to_s), msg)
         | 
| 36 | 
            +
                assert(field_names.member?(:two.to_s), msg)
         | 
| 37 | 
            +
                assert(field_names.member?(:three.to_s), msg)
         | 
| 38 | 
            +
                assert(field_names.member?(:ogtype.to_s), msg)
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              def test_fields_for_class_parent
         | 
| 42 | 
            +
                fields = @store.__send__(:fields_for_class, StiParent)
         | 
| 43 | 
            +
                field_names = fields.map {|f| name, * = f.split(/\s/); name}
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                msg = "Sti Parent not collecting child fields"
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                assert_equal(5, field_names.size, msg)
         | 
| 48 | 
            +
                assert(field_names.member?(:one.to_s), msg)
         | 
| 49 | 
            +
                assert(field_names.member?(:two.to_s), msg)
         | 
| 50 | 
            +
                assert(field_names.member?(:three.to_s), msg)
         | 
| 51 | 
            +
                assert(field_names.member?(:ogtype.to_s), msg)
         | 
| 52 | 
            +
              end
         | 
| 53 | 
            +
            end
         | 
| @@ -0,0 +1,44 @@ | |
| 1 | 
            +
            require File.join(File.dirname(__FILE__), 'CONFIG.rb')
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'rubygems'
         | 
| 4 | 
            +
            require 'facets'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            require 'test/unit'
         | 
| 7 | 
            +
            require 'og'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            class TC_OgAggrCalc < Test::Unit::TestCase # :nodoc: all
         | 
| 10 | 
            +
              include Og
         | 
| 11 | 
            +
             | 
| 12 | 
            +
              class User
         | 
| 13 | 
            +
                property :section, String
         | 
| 14 | 
            +
                property :age, Fixnum
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def initialize(section, age)
         | 
| 17 | 
            +
                  @section = section
         | 
| 18 | 
            +
                  @age = age
         | 
| 19 | 
            +
                end    
         | 
| 20 | 
            +
              end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
              $og1.manage_classes(User)
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              def test_all
         | 
| 25 | 
            +
                User.create('a', 12)
         | 
| 26 | 
            +
                User.create('a', 16)
         | 
| 27 | 
            +
                User.create('d', 34)
         | 
| 28 | 
            +
                User.create('d', 33)
         | 
| 29 | 
            +
                User.create('c', 27)
         | 
| 30 | 
            +
                User.create('c', 31)
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                assert_equal 6, User.count
         | 
| 33 | 
            +
                assert_equal 12, User.minimum(:age)
         | 
| 34 | 
            +
                assert_equal 34, User.maximum(:age)
         | 
| 35 | 
            +
                assert_equal 34, User.max(:age)
         | 
| 36 | 
            +
                assert_equal 25.5, User.avg(:age)
         | 
| 37 | 
            +
                assert_equal 153, User.sum(:age)
         | 
| 38 | 
            +
                
         | 
| 39 | 
            +
                sums = User.sum(:age, :group => :section)
         | 
| 40 | 
            +
                assert_equal 3, sums.size
         | 
| 41 | 
            +
                assert_equal 28, sums[0]
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
              
         | 
| 44 | 
            +
            end
         |