ibm_db 2.5.5 → 2.5.6
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 +5 -0
- data/README +4 -2
- data/ext/ibm_db.c +144 -12
- data/ext/ruby_ibm_db_cli.h +1 -0
- data/lib/IBM_DB.rb +1 -1
- data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +62 -1
- data/test/cases/adapter_test.rb +41 -19
- data/test/cases/associations/belongs_to_associations_test.rb +486 -0
- data/test/cases/associations/cascaded_eager_loading_test.rb +53 -3
- data/test/cases/associations/eager_test.rb +42 -22
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +114 -71
- data/test/cases/associations/has_many_through_associations_test.rb +214 -34
- data/test/cases/associations/join_model_test.rb +26 -34
- data/test/cases/attribute_methods_test.rb +387 -78
- data/test/cases/base_test.rb +555 -1183
- data/test/cases/calculations_test.rb +55 -43
- data/test/cases/finder_test.rb +218 -222
- data/test/cases/fixtures_test.rb +44 -20
- data/test/cases/migration_test.rb +638 -242
- data/test/cases/schema_dumper_test.rb +38 -3
- data/test/cases/validations/uniqueness_validation_test.rb +283 -0
- data/test/schema/i5/ibm_db_specific_schema.rb +1 -0
- data/test/schema/ids/ibm_db_specific_schema.rb +1 -0
- data/test/schema/luw/ibm_db_specific_schema.rb +2 -1
- data/test/schema/schema.rb +157 -10
- data/test/schema/zOS/ibm_db_specific_schema.rb +1 -0
- metadata +5 -5
- data/test/cases/helper.rb +0 -75
- data/test/cases/validations_test.rb +0 -1604
| @@ -95,7 +95,7 @@ class SchemaDumperTest < ActiveRecord::TestCase | |
| 95 95 |  | 
| 96 96 | 
             
                  assert_match %r{c_int_4.*}, output
         | 
| 97 97 | 
             
                  assert_no_match %r{c_int_4.*:limit}, output
         | 
| 98 | 
            -
                elsif current_adapter?(:MysqlAdapter)
         | 
| 98 | 
            +
                elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
         | 
| 99 99 | 
             
                  assert_match %r{c_int_1.*:limit => 1}, output
         | 
| 100 100 | 
             
                  assert_match %r{c_int_2.*:limit => 2}, output
         | 
| 101 101 | 
             
                  assert_match %r{c_int_3.*:limit => 3}, output
         | 
| @@ -116,6 +116,11 @@ class SchemaDumperTest < ActiveRecord::TestCase | |
| 116 116 | 
             
                  assert_match %r{c_int_6.*:limit => 6}, output
         | 
| 117 117 | 
             
                  assert_match %r{c_int_7.*:limit => 7}, output
         | 
| 118 118 | 
             
                  assert_match %r{c_int_8.*:limit => 8}, output
         | 
| 119 | 
            +
                elsif current_adapter?(:OracleAdapter)
         | 
| 120 | 
            +
                  assert_match %r{c_int_5.*:limit => 5}, output
         | 
| 121 | 
            +
                  assert_match %r{c_int_6.*:limit => 6}, output
         | 
| 122 | 
            +
                  assert_match %r{c_int_7.*:limit => 7}, output
         | 
| 123 | 
            +
                  assert_match %r{c_int_8.*:limit => 8}, output
         | 
| 119 124 | 
             
                else
         | 
| 120 125 | 
             
                  unless current_adapter?(:IBM_DBAdapter) #IBM data servers do not support limits on integer datatype
         | 
| 121 126 | 
             
                    assert_match %r{c_int_5.*:limit => 8}, output
         | 
| @@ -160,7 +165,7 @@ class SchemaDumperTest < ActiveRecord::TestCase | |
| 160 165 | 
             
                index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
         | 
| 161 166 | 
             
                assert_equal 'add_index "companies", ["firm_id", "type", "rating", "ruby_type"], :name => "company_index"', index_definition
         | 
| 162 167 | 
             
              end
         | 
| 163 | 
            -
             | 
| 168 | 
            +
             | 
| 164 169 | 
             
              def test_schema_dump_should_honor_nonstandard_primary_keys
         | 
| 165 170 | 
             
                output = standard_dump
         | 
| 166 171 | 
             
                match = output.match(%r{create_table "movies"(.*)do})
         | 
| @@ -168,7 +173,7 @@ class SchemaDumperTest < ActiveRecord::TestCase | |
| 168 173 | 
             
                assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved"
         | 
| 169 174 | 
             
              end
         | 
| 170 175 |  | 
| 171 | 
            -
              if current_adapter?(:MysqlAdapter)
         | 
| 176 | 
            +
              if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
         | 
| 172 177 | 
             
                def test_schema_dump_should_not_add_default_value_for_mysql_text_field
         | 
| 173 178 | 
             
                  output = standard_dump
         | 
| 174 179 | 
             
                  assert_match %r{t.text\s+"body",\s+:null => false$}, output
         | 
| @@ -194,4 +199,34 @@ class SchemaDumperTest < ActiveRecord::TestCase | |
| 194 199 | 
             
                output = stream.string
         | 
| 195 200 | 
             
                assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
         | 
| 196 201 | 
             
              end
         | 
| 202 | 
            +
             | 
| 203 | 
            +
              if current_adapter?(:PostgreSQLAdapter)
         | 
| 204 | 
            +
                def test_schema_dump_includes_xml_shorthand_definition
         | 
| 205 | 
            +
                  output = standard_dump
         | 
| 206 | 
            +
                  if %r{create_table "postgresql_xml_data_type"} =~ output
         | 
| 207 | 
            +
                    assert_match %r{t.xml "data"}, output
         | 
| 208 | 
            +
                  end
         | 
| 209 | 
            +
                end
         | 
| 210 | 
            +
              end
         | 
| 211 | 
            +
             | 
| 212 | 
            +
              def test_schema_dump_keeps_large_precision_integer_columns_as_decimal
         | 
| 213 | 
            +
                output = standard_dump
         | 
| 214 | 
            +
                # Oracle supports precision up to 38 and it identifies decimals with scale 0 as integers
         | 
| 215 | 
            +
                if current_adapter?(:OracleAdapter)
         | 
| 216 | 
            +
                  assert_match %r{t.integer\s+"atoms_in_universe",\s+:precision => 38,\s+:scale => 0}, output
         | 
| 217 | 
            +
                elsif current_adapter?(:IBM_DBAdapter)
         | 
| 218 | 
            +
                  assert_match %r{t.integer\s+"atoms_in_universe",\s+:precision => 31,\s+:scale => 0}, output
         | 
| 219 | 
            +
                else
         | 
| 220 | 
            +
                  assert_match %r{t.decimal\s+"atoms_in_universe",\s+:precision => 55,\s+:scale => 0}, output
         | 
| 221 | 
            +
                end
         | 
| 222 | 
            +
              end
         | 
| 223 | 
            +
             | 
| 224 | 
            +
              def test_schema_dump_keeps_id_column_when_id_is_false_and_id_column_added
         | 
| 225 | 
            +
                output = standard_dump
         | 
| 226 | 
            +
                match = output.match(%r{create_table "goofy_string_id"(.*)do.*\n(.*)\n})
         | 
| 227 | 
            +
                assert_not_nil(match, "goofy_string_id table not found")
         | 
| 228 | 
            +
                assert_match %r(:id => false), match[1], "no table id not preserved"
         | 
| 229 | 
            +
                assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved"
         | 
| 230 | 
            +
              end
         | 
| 197 231 | 
             
            end
         | 
| 232 | 
            +
             | 
| @@ -0,0 +1,283 @@ | |
| 1 | 
            +
            # encoding: utf-8
         | 
| 2 | 
            +
            require "cases/helper"
         | 
| 3 | 
            +
            require 'models/topic'
         | 
| 4 | 
            +
            require 'models/reply'
         | 
| 5 | 
            +
            require 'models/warehouse_thing'
         | 
| 6 | 
            +
            require 'models/guid'
         | 
| 7 | 
            +
            require 'models/event'
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            # The following methods in Topic are used in test_conditional_validation_*
         | 
| 10 | 
            +
            class Topic
         | 
| 11 | 
            +
              has_many :unique_replies, :dependent => :destroy, :foreign_key => "parent_id"
         | 
| 12 | 
            +
              has_many :silly_unique_replies, :dependent => :destroy, :foreign_key => "parent_id"
         | 
| 13 | 
            +
            end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            class UniqueReply < Reply
         | 
| 16 | 
            +
              validates_uniqueness_of :content, :scope => 'parent_id'
         | 
| 17 | 
            +
            end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            class SillyUniqueReply < UniqueReply
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            class Wizard < ActiveRecord::Base
         | 
| 23 | 
            +
              self.abstract_class = true
         | 
| 24 | 
            +
             | 
| 25 | 
            +
              validates_uniqueness_of :name
         | 
| 26 | 
            +
            end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            class IneptWizard < Wizard
         | 
| 29 | 
            +
              validates_uniqueness_of :city
         | 
| 30 | 
            +
            end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            class Conjurer < IneptWizard
         | 
| 33 | 
            +
            end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
            class Thaumaturgist < IneptWizard
         | 
| 36 | 
            +
            end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            class UniquenessValidationTest < ActiveRecord::TestCase
         | 
| 39 | 
            +
              fixtures :topics, :warehouse_things, :developers
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              repair_validations(Topic, Reply)
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              def test_validate_uniqueness
         | 
| 44 | 
            +
                Topic.validates_uniqueness_of(:title)
         | 
| 45 | 
            +
             | 
| 46 | 
            +
                t = Topic.new("title" => "I'm uniqué!")
         | 
| 47 | 
            +
                assert t.save, "Should save t as unique"
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                t.content = "Remaining unique"
         | 
| 50 | 
            +
                assert t.save, "Should still save t as unique"
         | 
| 51 | 
            +
             | 
| 52 | 
            +
                t2 = Topic.new("title" => "I'm uniqué!")
         | 
| 53 | 
            +
                assert !t2.valid?, "Shouldn't be valid"
         | 
| 54 | 
            +
                assert !t2.save, "Shouldn't save t2 as unique"
         | 
| 55 | 
            +
                assert_equal ["has already been taken"], t2.errors[:title]
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                t2.title = "Now Im really also unique"
         | 
| 58 | 
            +
                assert t2.save, "Should now save t2 as unique"
         | 
| 59 | 
            +
              end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
              def test_validates_uniqueness_with_validates
         | 
| 62 | 
            +
                Topic.validates :title, :uniqueness => true
         | 
| 63 | 
            +
                t = Topic.create!('title' => 'abc')
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                t2 = Topic.new('title' => 'abc')
         | 
| 66 | 
            +
                assert !t2.valid?
         | 
| 67 | 
            +
                assert t2.errors[:title]
         | 
| 68 | 
            +
              end
         | 
| 69 | 
            +
             | 
| 70 | 
            +
              def test_validates_uniqueness_with_newline_chars
         | 
| 71 | 
            +
                Topic.validates_uniqueness_of(:title, :case_sensitive => false)
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                t = Topic.new("title" => "new\nline")
         | 
| 74 | 
            +
                assert t.save, "Should save t as unique"
         | 
| 75 | 
            +
              end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
              def test_validate_uniqueness_with_scope
         | 
| 78 | 
            +
                Reply.validates_uniqueness_of(:content, :scope => "parent_id")
         | 
| 79 | 
            +
             | 
| 80 | 
            +
                t = Topic.create("title" => "I'm unique!")
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                r1 = t.replies.create "title" => "r1", "content" => "hello world"
         | 
| 83 | 
            +
                assert r1.valid?, "Saving r1"
         | 
| 84 | 
            +
             | 
| 85 | 
            +
                r2 = t.replies.create "title" => "r2", "content" => "hello world"
         | 
| 86 | 
            +
                assert !r2.valid?, "Saving r2 first time"
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                r2.content = "something else"
         | 
| 89 | 
            +
                assert r2.save, "Saving r2 second time"
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                t2 = Topic.create("title" => "I'm unique too!")
         | 
| 92 | 
            +
                r3 = t2.replies.create "title" => "r3", "content" => "hello world"
         | 
| 93 | 
            +
                assert r3.valid?, "Saving r3"
         | 
| 94 | 
            +
              end
         | 
| 95 | 
            +
             | 
| 96 | 
            +
              def test_validate_uniqueness_scoped_to_defining_class
         | 
| 97 | 
            +
                t = Topic.create("title" => "What, me worry?")
         | 
| 98 | 
            +
             | 
| 99 | 
            +
                r1 = t.unique_replies.create "title" => "r1", "content" => "a barrel of fun"
         | 
| 100 | 
            +
                assert r1.valid?, "Saving r1"
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                r2 = t.silly_unique_replies.create "title" => "r2", "content" => "a barrel of fun"
         | 
| 103 | 
            +
                assert !r2.valid?, "Saving r2"
         | 
| 104 | 
            +
             | 
| 105 | 
            +
                # Should succeed as validates_uniqueness_of only applies to
         | 
| 106 | 
            +
                # UniqueReply and its subclasses
         | 
| 107 | 
            +
                r3 = t.replies.create "title" => "r2", "content" => "a barrel of fun"
         | 
| 108 | 
            +
                assert r3.valid?, "Saving r3"
         | 
| 109 | 
            +
              end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
              def test_validate_uniqueness_with_scope_array
         | 
| 112 | 
            +
                Reply.validates_uniqueness_of(:author_name, :scope => [:author_email_address, :parent_id])
         | 
| 113 | 
            +
             | 
| 114 | 
            +
                t = Topic.create("title" => "The earth is actually flat!")
         | 
| 115 | 
            +
             | 
| 116 | 
            +
                r1 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply"
         | 
| 117 | 
            +
                assert r1.valid?, "Saving r1"
         | 
| 118 | 
            +
             | 
| 119 | 
            +
                r2 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy@rubyonrails.com", "title" => "You're crazy!", "content" => "Crazy reply again..."
         | 
| 120 | 
            +
                assert !r2.valid?, "Saving r2. Double reply by same author."
         | 
| 121 | 
            +
             | 
| 122 | 
            +
                r2.author_email_address = "jeremy_alt_email@rubyonrails.com"
         | 
| 123 | 
            +
                assert r2.save, "Saving r2 the second time."
         | 
| 124 | 
            +
             | 
| 125 | 
            +
                r3 = t.replies.create "author_name" => "jeremy", "author_email_address" => "jeremy_alt_email@rubyonrails.com", "title" => "You're wrong", "content" => "It's cubic"
         | 
| 126 | 
            +
                assert !r3.valid?, "Saving r3"
         | 
| 127 | 
            +
             | 
| 128 | 
            +
                r3.author_name = "jj"
         | 
| 129 | 
            +
                assert r3.save, "Saving r3 the second time."
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                r3.author_name = "jeremy"
         | 
| 132 | 
            +
                assert !r3.save, "Saving r3 the third time."
         | 
| 133 | 
            +
              end
         | 
| 134 | 
            +
             | 
| 135 | 
            +
              def test_validate_case_insensitive_uniqueness
         | 
| 136 | 
            +
                Topic.validates_uniqueness_of(:title, :parent_id, :case_sensitive => false, :allow_nil => true)
         | 
| 137 | 
            +
             | 
| 138 | 
            +
                t = Topic.new("title" => "I'm unique!", :parent_id => 2)
         | 
| 139 | 
            +
                assert t.save, "Should save t as unique"
         | 
| 140 | 
            +
             | 
| 141 | 
            +
                t.content = "Remaining unique"
         | 
| 142 | 
            +
                assert t.save, "Should still save t as unique"
         | 
| 143 | 
            +
             | 
| 144 | 
            +
                t2 = Topic.new("title" => "I'm UNIQUE!", :parent_id => 1)
         | 
| 145 | 
            +
                assert !t2.valid?, "Shouldn't be valid"
         | 
| 146 | 
            +
                assert !t2.save, "Shouldn't save t2 as unique"
         | 
| 147 | 
            +
                assert t2.errors[:title].any?
         | 
| 148 | 
            +
                assert t2.errors[:parent_id].any?
         | 
| 149 | 
            +
                assert_equal ["has already been taken"], t2.errors[:title]
         | 
| 150 | 
            +
             | 
| 151 | 
            +
                t2.title = "I'm truly UNIQUE!"
         | 
| 152 | 
            +
                assert !t2.valid?, "Shouldn't be valid"
         | 
| 153 | 
            +
                assert !t2.save, "Shouldn't save t2 as unique"
         | 
| 154 | 
            +
                assert t2.errors[:title].empty?
         | 
| 155 | 
            +
                assert t2.errors[:parent_id].any?
         | 
| 156 | 
            +
             | 
| 157 | 
            +
                t2.parent_id = 4
         | 
| 158 | 
            +
                assert t2.save, "Should now save t2 as unique"
         | 
| 159 | 
            +
             | 
| 160 | 
            +
                t2.parent_id = nil
         | 
| 161 | 
            +
                t2.title = nil
         | 
| 162 | 
            +
                assert t2.valid?, "should validate with nil"
         | 
| 163 | 
            +
                assert t2.save, "should save with nil"
         | 
| 164 | 
            +
             | 
| 165 | 
            +
                with_kcode('UTF8') do
         | 
| 166 | 
            +
                  t_utf8 = Topic.new("title" => "Я тоже уникальный!")
         | 
| 167 | 
            +
                  assert t_utf8.save, "Should save t_utf8 as unique"
         | 
| 168 | 
            +
             | 
| 169 | 
            +
                  # If database hasn't UTF-8 character set, this test fails
         | 
| 170 | 
            +
                  if Topic.find(t_utf8, :select => 'LOWER(title) AS title').title == "я тоже уникальный!"
         | 
| 171 | 
            +
                    t2_utf8 = Topic.new("title" => "я тоже УНИКАЛЬНЫЙ!")
         | 
| 172 | 
            +
                    assert !t2_utf8.valid?, "Shouldn't be valid"
         | 
| 173 | 
            +
                    assert !t2_utf8.save, "Shouldn't save t2_utf8 as unique"
         | 
| 174 | 
            +
                  end
         | 
| 175 | 
            +
                end
         | 
| 176 | 
            +
              end
         | 
| 177 | 
            +
             | 
| 178 | 
            +
              def test_validate_case_sensitive_uniqueness
         | 
| 179 | 
            +
                Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
         | 
| 180 | 
            +
             | 
| 181 | 
            +
                t = Topic.new("title" => "I'm unique!")
         | 
| 182 | 
            +
                assert t.save, "Should save t as unique"
         | 
| 183 | 
            +
             | 
| 184 | 
            +
                t.content = "Remaining unique"
         | 
| 185 | 
            +
                assert t.save, "Should still save t as unique"
         | 
| 186 | 
            +
             | 
| 187 | 
            +
                t2 = Topic.new("title" => "I'M UNIQUE!")
         | 
| 188 | 
            +
                assert t2.valid?, "Should be valid"
         | 
| 189 | 
            +
                assert t2.save, "Should save t2 as unique"
         | 
| 190 | 
            +
                assert t2.errors[:title].empty?
         | 
| 191 | 
            +
                assert t2.errors[:parent_id].empty?
         | 
| 192 | 
            +
                assert_not_equal ["has already been taken"], t2.errors[:title]
         | 
| 193 | 
            +
             | 
| 194 | 
            +
                t3 = Topic.new("title" => "I'M uNiQUe!")
         | 
| 195 | 
            +
                assert t3.valid?, "Should be valid"
         | 
| 196 | 
            +
                assert t3.save, "Should save t2 as unique"
         | 
| 197 | 
            +
                assert t3.errors[:title].empty?
         | 
| 198 | 
            +
                assert t3.errors[:parent_id].empty?
         | 
| 199 | 
            +
                assert_not_equal ["has already been taken"], t3.errors[:title]
         | 
| 200 | 
            +
              end
         | 
| 201 | 
            +
             | 
| 202 | 
            +
              def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
         | 
| 203 | 
            +
                Topic.validates_uniqueness_of(:title, :case_sensitve => true)
         | 
| 204 | 
            +
                t = Topic.create!('title' => 101)
         | 
| 205 | 
            +
             | 
| 206 | 
            +
                t2 = Topic.new('title' => 101)
         | 
| 207 | 
            +
                assert !t2.valid?
         | 
| 208 | 
            +
                assert t2.errors[:title]
         | 
| 209 | 
            +
              end
         | 
| 210 | 
            +
             | 
| 211 | 
            +
              def test_validate_uniqueness_with_non_standard_table_names
         | 
| 212 | 
            +
                i1 = WarehouseThing.create(:value => 1000)
         | 
| 213 | 
            +
                assert !i1.valid?, "i1 should not be valid"
         | 
| 214 | 
            +
                assert i1.errors[:value].any?, "Should not be empty"
         | 
| 215 | 
            +
              end
         | 
| 216 | 
            +
             | 
| 217 | 
            +
              def test_validates_uniqueness_inside_with_scope
         | 
| 218 | 
            +
                Topic.validates_uniqueness_of(:title)
         | 
| 219 | 
            +
             | 
| 220 | 
            +
                Topic.send(:with_scope, :find => { :conditions => { :author_name => "David" } }) do
         | 
| 221 | 
            +
                  t1 = Topic.new("title" => "I'm unique!", "author_name" => "Mary")
         | 
| 222 | 
            +
                  assert t1.save
         | 
| 223 | 
            +
                  t2 = Topic.new("title" => "I'm unique!", "author_name" => "David")
         | 
| 224 | 
            +
                  assert !t2.valid?
         | 
| 225 | 
            +
                end
         | 
| 226 | 
            +
              end
         | 
| 227 | 
            +
             | 
| 228 | 
            +
              def test_validate_uniqueness_with_columns_which_are_sql_keywords
         | 
| 229 | 
            +
                repair_validations(Guid) do
         | 
| 230 | 
            +
                  Guid.validates_uniqueness_of :key
         | 
| 231 | 
            +
                  g = Guid.new
         | 
| 232 | 
            +
                  g.key = "foo"
         | 
| 233 | 
            +
                  assert_nothing_raised { !g.valid? }
         | 
| 234 | 
            +
                end
         | 
| 235 | 
            +
              end
         | 
| 236 | 
            +
             | 
| 237 | 
            +
              def test_validate_uniqueness_with_limit
         | 
| 238 | 
            +
                # Event.title is limited to 5 characters
         | 
| 239 | 
            +
                e1 = Event.create(:title => "abcde")
         | 
| 240 | 
            +
                assert e1.valid?, "Could not create an event with a unique, 5 character title"
         | 
| 241 | 
            +
                e2 = Event.create(:title => "abcdefgh")
         | 
| 242 | 
            +
                assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
         | 
| 243 | 
            +
              end
         | 
| 244 | 
            +
             | 
| 245 | 
            +
              def test_validate_uniqueness_with_limit_and_utf8
         | 
| 246 | 
            +
                with_kcode('UTF8') do
         | 
| 247 | 
            +
                  # Event.title is limited to 5 characters
         | 
| 248 | 
            +
                  e1 = Event.create(:title => "一二三四五")
         | 
| 249 | 
            +
                  assert e1.valid?, "Could not create an event with a unique, 5 character title"
         | 
| 250 | 
            +
                  e2 = Event.create(:title => "一二三四五六七八")
         | 
| 251 | 
            +
                  assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
         | 
| 252 | 
            +
                end
         | 
| 253 | 
            +
              end
         | 
| 254 | 
            +
             | 
| 255 | 
            +
              def test_validate_straight_inheritance_uniqueness
         | 
| 256 | 
            +
                w1 = IneptWizard.create(:name => "Rincewind", :city => "Ankh-Morpork")
         | 
| 257 | 
            +
                assert w1.valid?, "Saving w1"
         | 
| 258 | 
            +
             | 
| 259 | 
            +
                # Should use validation from base class (which is abstract)
         | 
| 260 | 
            +
                w2 = IneptWizard.new(:name => "Rincewind", :city => "Quirm")
         | 
| 261 | 
            +
                assert !w2.valid?, "w2 shouldn't be valid"
         | 
| 262 | 
            +
                assert w2.errors[:name].any?, "Should have errors for name"
         | 
| 263 | 
            +
                assert_equal ["has already been taken"], w2.errors[:name], "Should have uniqueness message for name"
         | 
| 264 | 
            +
             | 
| 265 | 
            +
                w3 = Conjurer.new(:name => "Rincewind", :city => "Quirm")
         | 
| 266 | 
            +
                assert !w3.valid?, "w3 shouldn't be valid"
         | 
| 267 | 
            +
                assert w3.errors[:name].any?, "Should have errors for name"
         | 
| 268 | 
            +
                assert_equal ["has already been taken"], w3.errors[:name], "Should have uniqueness message for name"
         | 
| 269 | 
            +
             | 
| 270 | 
            +
                w4 = Conjurer.create(:name => "The Amazing Bonko", :city => "Quirm")
         | 
| 271 | 
            +
                assert w4.valid?, "Saving w4"
         | 
| 272 | 
            +
             | 
| 273 | 
            +
                w5 = Thaumaturgist.new(:name => "The Amazing Bonko", :city => "Lancre")
         | 
| 274 | 
            +
                assert !w5.valid?, "w5 shouldn't be valid"
         | 
| 275 | 
            +
                assert w5.errors[:name].any?, "Should have errors for name"
         | 
| 276 | 
            +
                assert_equal ["has already been taken"], w5.errors[:name], "Should have uniqueness message for name"
         | 
| 277 | 
            +
             | 
| 278 | 
            +
                w6 = Thaumaturgist.new(:name => "Mustrum Ridcully", :city => "Quirm")
         | 
| 279 | 
            +
                assert !w6.valid?, "w6 shouldn't be valid"
         | 
| 280 | 
            +
                assert w6.errors[:city].any?, "Should have errors for city"
         | 
| 281 | 
            +
                assert_equal ["has already been taken"], w6.errors[:city], "Should have uniqueness message for city"
         | 
| 282 | 
            +
              end
         | 
| 283 | 
            +
            end
         | 
    
        data/test/schema/schema.rb
    CHANGED
    
    | @@ -1,4 +1,3 @@ | |
| 1 | 
            -
             | 
| 2 1 | 
             
            ActiveRecord::Schema.define do
         | 
| 3 2 | 
             
              def except(adapter_names_to_exclude)
         | 
| 4 3 | 
             
                unless [adapter_names_to_exclude].flatten.include?(adapter_name)
         | 
| @@ -27,6 +26,15 @@ ActiveRecord::Schema.define do | |
| 27 26 | 
             
                t.integer :credit_limit
         | 
| 28 27 | 
             
              end
         | 
| 29 28 |  | 
| 29 | 
            +
              create_table :admin_accounts, :force => true do |t|
         | 
| 30 | 
            +
                t.string :name
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              create_table :admin_users, :force => true do |t|
         | 
| 34 | 
            +
                t.string :name
         | 
| 35 | 
            +
                t.references :account
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 30 38 | 
             
              create_table :audit_logs, :force => true do |t|
         | 
| 31 39 | 
             
                t.column :message, :string, :null=>false
         | 
| 32 40 | 
             
                t.column :developer_id, :integer, :null=>false
         | 
| @@ -58,6 +66,7 @@ ActiveRecord::Schema.define do | |
| 58 66 |  | 
| 59 67 | 
             
              create_table :birds, :force => true do |t|
         | 
| 60 68 | 
             
                t.string :name
         | 
| 69 | 
            +
                t.string :color
         | 
| 61 70 | 
             
                t.integer :pirate_id
         | 
| 62 71 | 
             
              end
         | 
| 63 72 |  | 
| @@ -65,7 +74,7 @@ ActiveRecord::Schema.define do | |
| 65 74 | 
             
                t.column :name, :string
         | 
| 66 75 | 
             
              end
         | 
| 67 76 |  | 
| 68 | 
            -
              create_table : | 
| 77 | 
            +
              create_table :booleans, :force => true do |t|
         | 
| 69 78 | 
             
                t.boolean :value
         | 
| 70 79 | 
             
              end
         | 
| 71 80 |  | 
| @@ -73,6 +82,12 @@ ActiveRecord::Schema.define do | |
| 73 82 | 
             
                t.string :name
         | 
| 74 83 | 
             
              end
         | 
| 75 84 |  | 
| 85 | 
            +
              create_table :cars, :force => true do |t|
         | 
| 86 | 
            +
                t.string  :name
         | 
| 87 | 
            +
                t.integer :engines_count
         | 
| 88 | 
            +
                t.integer :wheels_count
         | 
| 89 | 
            +
              end
         | 
| 90 | 
            +
             | 
| 76 91 | 
             
              create_table :categories, :force => true do |t|
         | 
| 77 92 | 
             
                t.string :name, :null => false
         | 
| 78 93 | 
             
                t.string :type
         | 
| @@ -99,6 +114,10 @@ ActiveRecord::Schema.define do | |
| 99 114 | 
             
                t.string :name
         | 
| 100 115 | 
             
              end
         | 
| 101 116 |  | 
| 117 | 
            +
              create_table :collections, :force => true do |t|
         | 
| 118 | 
            +
                t.string :name
         | 
| 119 | 
            +
              end
         | 
| 120 | 
            +
             | 
| 102 121 | 
             
              create_table :colnametests, :force => true do |t|
         | 
| 103 122 | 
             
                t.integer :references, :null => false
         | 
| 104 123 | 
             
              end
         | 
| @@ -128,6 +147,10 @@ ActiveRecord::Schema.define do | |
| 128 147 | 
             
                t.integer :extendedWarranty, :null => false
         | 
| 129 148 | 
             
              end
         | 
| 130 149 |  | 
| 150 | 
            +
              create_table :contracts, :force => true do |t|
         | 
| 151 | 
            +
                t.integer :developer_id
         | 
| 152 | 
            +
                t.integer :company_id
         | 
| 153 | 
            +
              end
         | 
| 131 154 |  | 
| 132 155 | 
             
              create_table :customers, :force => true do |t|
         | 
| 133 156 | 
             
                t.string  :name
         | 
| @@ -138,6 +161,11 @@ ActiveRecord::Schema.define do | |
| 138 161 | 
             
                t.string  :gps_location
         | 
| 139 162 | 
             
              end
         | 
| 140 163 |  | 
| 164 | 
            +
              create_table :dashboards, :force => true, :id => false do |t|
         | 
| 165 | 
            +
                t.string :dashboard_id
         | 
| 166 | 
            +
                t.string :name
         | 
| 167 | 
            +
              end
         | 
| 168 | 
            +
             | 
| 141 169 | 
             
              create_table :developers, :force => true do |t|
         | 
| 142 170 | 
             
                t.string   :name
         | 
| 143 171 | 
             
                t.integer  :salary, :default => 70000
         | 
| @@ -152,12 +180,24 @@ ActiveRecord::Schema.define do | |
| 152 180 | 
             
                t.integer :access_level, :default => 1
         | 
| 153 181 | 
             
              end
         | 
| 154 182 |  | 
| 155 | 
            -
              create_table :edges, :force => true do |t|
         | 
| 183 | 
            +
              create_table :edges, :force => true, :id => false do |t|
         | 
| 156 184 | 
             
                t.column :source_id, :integer, :null => false
         | 
| 157 185 | 
             
                t.column :sink_id,   :integer, :null => false
         | 
| 158 186 | 
             
              end
         | 
| 159 187 | 
             
              add_index :edges, [:source_id, :sink_id], :unique => true, :name => 'unique_edge_index'
         | 
| 160 188 |  | 
| 189 | 
            +
              create_table :engines, :force => true do |t|
         | 
| 190 | 
            +
                t.integer :car_id
         | 
| 191 | 
            +
              end
         | 
| 192 | 
            +
             | 
| 193 | 
            +
              create_table :tyres, :force => true do |t|
         | 
| 194 | 
            +
                t.integer :car_id
         | 
| 195 | 
            +
              end
         | 
| 196 | 
            +
             | 
| 197 | 
            +
              create_table :bulbs, :force => true do |t|
         | 
| 198 | 
            +
                t.integer :car_id
         | 
| 199 | 
            +
                t.string  :name
         | 
| 200 | 
            +
              end
         | 
| 161 201 |  | 
| 162 202 | 
             
              create_table :entrants, :force => true do |t|
         | 
| 163 203 | 
             
                t.string  :name, :null => false
         | 
| @@ -182,7 +222,12 @@ ActiveRecord::Schema.define do | |
| 182 222 | 
             
                t.string :id, :null => false
         | 
| 183 223 | 
             
                t.string :info
         | 
| 184 224 | 
             
              end
         | 
| 185 | 
            -
             | 
| 225 | 
            +
             | 
| 226 | 
            +
              create_table :invoices, :force => true do |t|
         | 
| 227 | 
            +
                t.integer :balance
         | 
| 228 | 
            +
                t.datetime :updated_at
         | 
| 229 | 
            +
              end
         | 
| 230 | 
            +
             | 
| 186 231 | 
             
              except 'IBM_DB' do
         | 
| 187 232 | 
             
                create_table :items, :force => true do |t|
         | 
| 188 233 | 
             
                 t.column :name, :string
         | 
| @@ -210,6 +255,11 @@ ActiveRecord::Schema.define do | |
| 210 255 | 
             
                t.integer :version, :null => false, :default => 0
         | 
| 211 256 | 
             
              end
         | 
| 212 257 |  | 
| 258 | 
            +
              create_table :line_items, :force => true do |t|
         | 
| 259 | 
            +
                t.integer :invoice_id
         | 
| 260 | 
            +
                t.integer :amount
         | 
| 261 | 
            +
              end
         | 
| 262 | 
            +
             | 
| 213 263 | 
             
              create_table :lock_without_defaults, :force => true do |t|
         | 
| 214 264 | 
             
                t.column :lock_version, :integer
         | 
| 215 265 | 
             
              end
         | 
| @@ -253,6 +303,13 @@ ActiveRecord::Schema.define do | |
| 253 303 | 
             
                t.integer :lock_version, :default => 0
         | 
| 254 304 | 
             
              end
         | 
| 255 305 |  | 
| 306 | 
            +
              create_table :minivans, :force => true, :id => false do |t|
         | 
| 307 | 
            +
                t.string :minivan_id
         | 
| 308 | 
            +
                t.string :name
         | 
| 309 | 
            +
                t.string :speedometer_id
         | 
| 310 | 
            +
                t.string :color
         | 
| 311 | 
            +
              end
         | 
| 312 | 
            +
             | 
| 256 313 | 
             
              create_table :minimalistics, :force => true do |t|
         | 
| 257 314 | 
             
              end
         | 
| 258 315 |  | 
| @@ -284,6 +341,14 @@ ActiveRecord::Schema.define do | |
| 284 341 | 
             
                t.decimal :my_house_population, :precision => 2, :scale => 0
         | 
| 285 342 | 
             
                t.decimal :decimal_number_with_default, :precision => 3, :scale => 2, :default => 2.78
         | 
| 286 343 | 
             
                t.float   :temperature
         | 
| 344 | 
            +
                # Oracle supports precision up to 38
         | 
| 345 | 
            +
                if current_adapter?(:OracleAdapter)
         | 
| 346 | 
            +
                  t.decimal :atoms_in_universe, :precision => 38, :scale => 0
         | 
| 347 | 
            +
                elsif current_adapter?(:IBM_DBAdapter)
         | 
| 348 | 
            +
                  t.decimal :atoms_in_universe, :precision => 31, :scale => 0
         | 
| 349 | 
            +
                else
         | 
| 350 | 
            +
                  t.decimal :atoms_in_universe, :precision => 55, :scale => 0
         | 
| 351 | 
            +
                end
         | 
| 287 352 | 
             
              end
         | 
| 288 353 |  | 
| 289 354 | 
             
              create_table :orders, :force => true do |t|
         | 
| @@ -311,7 +376,7 @@ ActiveRecord::Schema.define do | |
| 311 376 | 
             
                 t.integer :non_poly_two_id
         | 
| 312 377 | 
             
                end
         | 
| 313 378 | 
             
              end
         | 
| 314 | 
            -
             | 
| 379 | 
            +
             | 
| 315 380 | 
             
              create_table :parrots, :force => true do |t|
         | 
| 316 381 | 
             
                t.column :name, :string
         | 
| 317 382 | 
             
                t.column :parrot_sti_class, :string
         | 
| @@ -336,6 +401,7 @@ ActiveRecord::Schema.define do | |
| 336 401 | 
             
                t.string     :first_name, :null => false
         | 
| 337 402 | 
             
                t.references :primary_contact
         | 
| 338 403 | 
             
                t.string     :gender, :limit => 1
         | 
| 404 | 
            +
                t.references :number1_fan
         | 
| 339 405 | 
             
                t.integer    :lock_version, :null => false, :default => 0
         | 
| 340 406 | 
             
              end
         | 
| 341 407 |  | 
| @@ -368,6 +434,11 @@ ActiveRecord::Schema.define do | |
| 368 434 | 
             
                t.integer :price
         | 
| 369 435 | 
             
              end
         | 
| 370 436 |  | 
| 437 | 
            +
              create_table :products, :force => true do |t|
         | 
| 438 | 
            +
                t.references :collection
         | 
| 439 | 
            +
                t.string     :name
         | 
| 440 | 
            +
              end
         | 
| 441 | 
            +
             | 
| 371 442 | 
             
              create_table :projects, :force => true do |t|
         | 
| 372 443 | 
             
                t.string :name
         | 
| 373 444 | 
             
                t.string :type
         | 
| @@ -376,6 +447,7 @@ ActiveRecord::Schema.define do | |
| 376 447 | 
             
              create_table :readers, :force => true do |t|
         | 
| 377 448 | 
             
                t.integer :post_id, :null => false
         | 
| 378 449 | 
             
                t.integer :person_id, :null => false
         | 
| 450 | 
            +
                t.boolean :skimmer, :default => false
         | 
| 379 451 | 
             
              end
         | 
| 380 452 |  | 
| 381 453 | 
             
              create_table :shape_expressions, :force => true do |t|
         | 
| @@ -399,6 +471,12 @@ ActiveRecord::Schema.define do | |
| 399 471 | 
             
                t.integer :ship_id
         | 
| 400 472 | 
             
              end
         | 
| 401 473 |  | 
| 474 | 
            +
              create_table :speedometers, :force => true, :id => false do |t|
         | 
| 475 | 
            +
                t.string :speedometer_id
         | 
| 476 | 
            +
                t.string :name
         | 
| 477 | 
            +
                t.string :dashboard_id
         | 
| 478 | 
            +
              end
         | 
| 479 | 
            +
             | 
| 402 480 | 
             
              create_table :sponsors, :force => true do |t|
         | 
| 403 481 | 
             
                t.integer :club_id
         | 
| 404 482 | 
             
                t.integer :sponsorable_id
         | 
| @@ -455,12 +533,24 @@ ActiveRecord::Schema.define do | |
| 455 533 | 
             
                t.integer :pet_id, :integer
         | 
| 456 534 | 
             
              end
         | 
| 457 535 |  | 
| 536 | 
            +
              create_table :traffic_lights, :force => true do |t|
         | 
| 537 | 
            +
                t.string   :location
         | 
| 538 | 
            +
                t.string   :state
         | 
| 539 | 
            +
                t.datetime :created_at
         | 
| 540 | 
            +
                t.datetime :updated_at
         | 
| 541 | 
            +
              end
         | 
| 542 | 
            +
             | 
| 458 543 | 
             
              create_table :treasures, :force => true do |t|
         | 
| 459 544 | 
             
                t.column :name, :string
         | 
| 460 545 | 
             
                t.column :looter_id, :integer
         | 
| 461 546 | 
             
                t.column :looter_type, :string
         | 
| 462 547 | 
             
              end
         | 
| 463 548 |  | 
| 549 | 
            +
              create_table :variants, :force => true do |t|
         | 
| 550 | 
            +
                t.references :product
         | 
| 551 | 
            +
                t.string     :name
         | 
| 552 | 
            +
              end
         | 
| 553 | 
            +
             | 
| 464 554 | 
             
              create_table :vertices, :force => true do |t|
         | 
| 465 555 | 
             
                t.column :label, :string
         | 
| 466 556 | 
             
              end
         | 
| @@ -469,11 +559,9 @@ ActiveRecord::Schema.define do | |
| 469 559 | 
             
                t.integer :value
         | 
| 470 560 | 
             
              end
         | 
| 471 561 |  | 
| 472 | 
            -
               | 
| 473 | 
            -
                 | 
| 474 | 
            -
             | 
| 475 | 
            -
                end
         | 
| 476 | 
            -
              end 
         | 
| 562 | 
            +
              [:circles, :squares, :triangles, :non_poly_ones, :non_poly_twos].each do |t|
         | 
| 563 | 
            +
                create_table(t, :force => true) { }
         | 
| 564 | 
            +
              end
         | 
| 477 565 |  | 
| 478 566 | 
             
              create_table :guids, :force => true do |t|
         | 
| 479 567 | 
             
                t.column :key, :string
         | 
| @@ -486,6 +574,61 @@ ActiveRecord::Schema.define do | |
| 486 574 | 
             
                end
         | 
| 487 575 | 
             
              end
         | 
| 488 576 |  | 
| 577 | 
            +
              # NOTE - the following 4 tables are used by models that have :inverse_of options on the associations
         | 
| 578 | 
            +
              create_table :men, :force => true do |t|
         | 
| 579 | 
            +
                t.string  :name
         | 
| 580 | 
            +
              end
         | 
| 581 | 
            +
             | 
| 582 | 
            +
              create_table :faces, :force => true do |t|
         | 
| 583 | 
            +
                t.string  :description
         | 
| 584 | 
            +
                t.integer :man_id
         | 
| 585 | 
            +
                t.integer :polymorphic_man_id
         | 
| 586 | 
            +
                t.string :polymorphic_man_type
         | 
| 587 | 
            +
              end
         | 
| 588 | 
            +
             | 
| 589 | 
            +
              create_table :interests, :force => true do |t|
         | 
| 590 | 
            +
                t.string :topic
         | 
| 591 | 
            +
                t.integer :man_id
         | 
| 592 | 
            +
                t.integer :polymorphic_man_id
         | 
| 593 | 
            +
                t.string :polymorphic_man_type
         | 
| 594 | 
            +
                t.integer :zine_id
         | 
| 595 | 
            +
              end
         | 
| 596 | 
            +
             | 
| 597 | 
            +
              create_table :wheels, :force => true do |t|
         | 
| 598 | 
            +
                t.references :wheelable, :polymorphic => true
         | 
| 599 | 
            +
              end
         | 
| 600 | 
            +
             | 
| 601 | 
            +
              create_table :zines, :force => true do |t|
         | 
| 602 | 
            +
                t.string :title
         | 
| 603 | 
            +
              end
         | 
| 604 | 
            +
             | 
| 605 | 
            +
              create_table :countries, :force => true, :id => false, :primary_key => 'country_id' do |t|
         | 
| 606 | 
            +
                t.string :country_id
         | 
| 607 | 
            +
                t.string :name
         | 
| 608 | 
            +
              end
         | 
| 609 | 
            +
              create_table :treaties, :force => true, :id => false, :primary_key => 'treaty_id' do |t|
         | 
| 610 | 
            +
                t.string :treaty_id
         | 
| 611 | 
            +
                t.string :name
         | 
| 612 | 
            +
              end
         | 
| 613 | 
            +
              create_table :countries_treaties, :force => true, :id => false do |t|
         | 
| 614 | 
            +
                t.string :country_id, :null => false
         | 
| 615 | 
            +
                t.string :treaty_id, :null => false
         | 
| 616 | 
            +
                t.datetime :created_at
         | 
| 617 | 
            +
                t.datetime :updated_at
         | 
| 618 | 
            +
              end
         | 
| 619 | 
            +
             | 
| 620 | 
            +
              create_table :liquid, :force => true do |t|
         | 
| 621 | 
            +
                t.string :name
         | 
| 622 | 
            +
              end
         | 
| 623 | 
            +
              create_table :molecules, :force => true do |t|
         | 
| 624 | 
            +
                t.integer :liquid_id
         | 
| 625 | 
            +
                t.string :name
         | 
| 626 | 
            +
              end
         | 
| 627 | 
            +
              create_table :electrons, :force => true do |t|
         | 
| 628 | 
            +
                t.integer :molecule_id
         | 
| 629 | 
            +
                t.string :name
         | 
| 630 | 
            +
              end
         | 
| 631 | 
            +
             | 
| 489 632 | 
             
              except ['SQLite','IBM_DB'] do
         | 
| 490 633 | 
             
                # fk_test_has_fk should be before fk_test_has_pk
         | 
| 491 634 | 
             
                create_table :fk_test_has_fk, :force => true do |t|
         | 
| @@ -498,3 +641,7 @@ ActiveRecord::Schema.define do | |
| 498 641 | 
             
                execute "ALTER TABLE fk_test_has_fk ADD CONSTRAINT fk_name FOREIGN KEY (#{quote_column_name 'fk_id'}) REFERENCES #{quote_table_name 'fk_test_has_pk'} (#{quote_column_name 'id'})"
         | 
| 499 642 | 
             
              end
         | 
| 500 643 | 
             
            end
         | 
| 644 | 
            +
             | 
| 645 | 
            +
            Course.connection.create_table :courses, :force => true do |t|
         | 
| 646 | 
            +
              t.column :name, :string, :null => false
         | 
| 647 | 
            +
            end
         |