ibm_db 2.5.6-x86-mingw32

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.
Files changed (43) hide show
  1. data/CHANGES +181 -0
  2. data/LICENSE +18 -0
  3. data/MANIFEST +14 -0
  4. data/ParameterizedQueries README +39 -0
  5. data/README +282 -0
  6. data/ext/Makefile.nt32 +181 -0
  7. data/ext/extconf.rb +66 -0
  8. data/ext/ibm_db.c +11166 -0
  9. data/ext/ruby_ibm_db.h +236 -0
  10. data/ext/ruby_ibm_db_cli.c +738 -0
  11. data/ext/ruby_ibm_db_cli.h +431 -0
  12. data/init.rb +42 -0
  13. data/lib/IBM_DB.rb +2 -0
  14. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +2598 -0
  15. data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1965 -0
  16. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -0
  17. data/lib/mswin32/ibm_db.rb +1 -0
  18. data/lib/mswin32/rb18x/ibm_db.so +0 -0
  19. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  20. data/test/cases/adapter_test.rb +202 -0
  21. data/test/cases/associations/belongs_to_associations_test.rb +486 -0
  22. data/test/cases/associations/cascaded_eager_loading_test.rb +183 -0
  23. data/test/cases/associations/eager_test.rb +862 -0
  24. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +917 -0
  25. data/test/cases/associations/has_many_through_associations_test.rb +461 -0
  26. data/test/cases/associations/join_model_test.rb +793 -0
  27. data/test/cases/attribute_methods_test.rb +621 -0
  28. data/test/cases/base_test.rb +1486 -0
  29. data/test/cases/calculations_test.rb +362 -0
  30. data/test/cases/finder_test.rb +1088 -0
  31. data/test/cases/fixtures_test.rb +684 -0
  32. data/test/cases/migration_test.rb +2014 -0
  33. data/test/cases/schema_dumper_test.rb +232 -0
  34. data/test/cases/validations/uniqueness_validation_test.rb +283 -0
  35. data/test/connections/native_ibm_db/connection.rb +42 -0
  36. data/test/ibm_db_test.rb +25 -0
  37. data/test/models/warehouse_thing.rb +5 -0
  38. data/test/schema/i5/ibm_db_specific_schema.rb +135 -0
  39. data/test/schema/ids/ibm_db_specific_schema.rb +138 -0
  40. data/test/schema/luw/ibm_db_specific_schema.rb +135 -0
  41. data/test/schema/schema.rb +647 -0
  42. data/test/schema/zOS/ibm_db_specific_schema.rb +206 -0
  43. metadata +123 -0
@@ -0,0 +1,232 @@
1
+ require "cases/helper"
2
+ require 'stringio'
3
+
4
+
5
+ class SchemaDumperTest < ActiveRecord::TestCase
6
+ def standard_dump
7
+ stream = StringIO.new
8
+ ActiveRecord::SchemaDumper.ignore_tables = []
9
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
10
+ stream.string
11
+ end
12
+
13
+ def test_schema_dump
14
+ output = standard_dump
15
+ assert_match %r{create_table "accounts"}, output
16
+ assert_match %r{create_table "authors"}, output
17
+ assert_no_match %r{create_table "schema_migrations"}, output
18
+ end
19
+
20
+ def test_schema_dump_excludes_sqlite_sequence
21
+ output = standard_dump
22
+ assert_no_match %r{create_table "sqlite_sequence"}, output
23
+ end
24
+
25
+ unless current_adapter?(:IBM_DBAdapter) #DB2 is case insensitive
26
+ def test_schema_dump_includes_camelcase_table_name
27
+ output = standard_dump
28
+ assert_match %r{create_table "CamelCase"}, output
29
+ end
30
+ end
31
+
32
+ def assert_line_up(lines, pattern, required = false)
33
+ return assert(true) if lines.empty?
34
+ matches = lines.map { |line| line.match(pattern) }
35
+ assert matches.all? if required
36
+ matches.compact!
37
+ return assert(true) if matches.empty?
38
+ assert_equal 1, matches.map{ |match| match.offset(0).first }.uniq.length
39
+ end
40
+
41
+ def column_definition_lines(output = standard_dump)
42
+ output.scan(/^( *)create_table.*?\n(.*?)^\1end/m).map{ |m| m.last.split(/\n/) }
43
+ end
44
+
45
+ def test_types_line_up
46
+ column_definition_lines.each do |column_set|
47
+ next if column_set.empty?
48
+
49
+ lengths = column_set.map do |column|
50
+ if match = column.match(/t\.(?:integer|decimal|float|datetime|timestamp|time|date|text|binary|string|boolean)\s+"/)
51
+ match[0].length
52
+ end
53
+ end
54
+
55
+ assert_equal 1, lengths.uniq.length
56
+ end
57
+ end
58
+
59
+ def test_arguments_line_up
60
+ column_definition_lines.each do |column_set|
61
+ assert_line_up(column_set, /:default => /)
62
+ assert_line_up(column_set, /:limit => /)
63
+ assert_line_up(column_set, /:null => /)
64
+ end
65
+ end
66
+
67
+ def test_no_dump_errors
68
+ output = standard_dump
69
+ assert_no_match %r{\# Could not dump table}, output
70
+ end
71
+
72
+ def test_schema_dump_includes_not_null_columns
73
+ stream = StringIO.new
74
+
75
+ ActiveRecord::SchemaDumper.ignore_tables = [/^[^r]/]
76
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
77
+ output = stream.string
78
+ assert_match %r{:null => false}, output
79
+ end
80
+
81
+ def test_schema_dump_includes_limit_constraint_for_integer_columns
82
+ stream = StringIO.new
83
+
84
+ ActiveRecord::SchemaDumper.ignore_tables = [/^(?!integer_limits)/]
85
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
86
+ output = stream.string
87
+
88
+ if current_adapter?(:PostgreSQLAdapter)
89
+ assert_match %r{c_int_1.*:limit => 2}, output
90
+ assert_match %r{c_int_2.*:limit => 2}, output
91
+
92
+ # int 3 is 4 bytes in postgresql
93
+ assert_match %r{c_int_3.*}, output
94
+ assert_no_match %r{c_int_3.*:limit}, output
95
+
96
+ assert_match %r{c_int_4.*}, output
97
+ assert_no_match %r{c_int_4.*:limit}, output
98
+ elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
99
+ assert_match %r{c_int_1.*:limit => 1}, output
100
+ assert_match %r{c_int_2.*:limit => 2}, output
101
+ assert_match %r{c_int_3.*:limit => 3}, output
102
+
103
+ assert_match %r{c_int_4.*}, output
104
+ assert_no_match %r{c_int_4.*:limit}, output
105
+ elsif current_adapter?(:SQLiteAdapter)
106
+ assert_match %r{c_int_1.*:limit => 1}, output
107
+ assert_match %r{c_int_2.*:limit => 2}, output
108
+ assert_match %r{c_int_3.*:limit => 3}, output
109
+ assert_match %r{c_int_4.*:limit => 4}, output
110
+ end
111
+ assert_match %r{c_int_without_limit.*}, output
112
+ assert_no_match %r{c_int_without_limit.*:limit}, output
113
+
114
+ if current_adapter?(:SQLiteAdapter)
115
+ assert_match %r{c_int_5.*:limit => 5}, output
116
+ assert_match %r{c_int_6.*:limit => 6}, output
117
+ assert_match %r{c_int_7.*:limit => 7}, output
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
124
+ else
125
+ unless current_adapter?(:IBM_DBAdapter) #IBM data servers do not support limits on integer datatype
126
+ assert_match %r{c_int_5.*:limit => 8}, output
127
+ assert_match %r{c_int_6.*:limit => 8}, output
128
+ assert_match %r{c_int_7.*:limit => 8}, output
129
+ assert_match %r{c_int_8.*:limit => 8}, output
130
+ end
131
+ end
132
+ end
133
+
134
+ def test_schema_dump_with_string_ignored_table
135
+ stream = StringIO.new
136
+
137
+ ActiveRecord::SchemaDumper.ignore_tables = ['accounts']
138
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
139
+ output = stream.string
140
+ assert_no_match %r{create_table "accounts"}, output
141
+ assert_match %r{create_table "authors"}, output
142
+ assert_no_match %r{create_table "schema_migrations"}, output
143
+ end
144
+
145
+ def test_schema_dump_with_regexp_ignored_table
146
+ stream = StringIO.new
147
+
148
+ ActiveRecord::SchemaDumper.ignore_tables = [/^account/]
149
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
150
+ output = stream.string
151
+ assert_no_match %r{create_table "accounts"}, output
152
+ assert_match %r{create_table "authors"}, output
153
+ assert_no_match %r{create_table "schema_migrations"}, output
154
+ end
155
+
156
+ def test_schema_dump_illegal_ignored_table_value
157
+ stream = StringIO.new
158
+ ActiveRecord::SchemaDumper.ignore_tables = [5]
159
+ assert_raise(StandardError) do
160
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
161
+ end
162
+ end
163
+
164
+ def test_schema_dumps_index_columns_in_right_order
165
+ index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
166
+ assert_equal 'add_index "companies", ["firm_id", "type", "rating", "ruby_type"], :name => "company_index"', index_definition
167
+ end
168
+
169
+ def test_schema_dump_should_honor_nonstandard_primary_keys
170
+ output = standard_dump
171
+ match = output.match(%r{create_table "movies"(.*)do})
172
+ assert_not_nil(match, "nonstandardpk table not found")
173
+ assert_match %r(:primary_key => "movieid"), match[1], "non-standard primary key not preserved"
174
+ end
175
+
176
+ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
177
+ def test_schema_dump_should_not_add_default_value_for_mysql_text_field
178
+ output = standard_dump
179
+ assert_match %r{t.text\s+"body",\s+:null => false$}, output
180
+ end
181
+
182
+ def test_schema_dump_includes_length_for_mysql_blob_and_text_fields
183
+ output = standard_dump
184
+ assert_match %r{t.binary\s+"tiny_blob",\s+:limit => 255$}, output
185
+ assert_match %r{t.binary\s+"normal_blob"$}, output
186
+ assert_match %r{t.binary\s+"medium_blob",\s+:limit => 16777215$}, output
187
+ assert_match %r{t.binary\s+"long_blob",\s+:limit => 2147483647$}, output
188
+ assert_match %r{t.text\s+"tiny_text",\s+:limit => 255$}, output
189
+ assert_match %r{t.text\s+"normal_text"$}, output
190
+ assert_match %r{t.text\s+"medium_text",\s+:limit => 16777215$}, output
191
+ assert_match %r{t.text\s+"long_text",\s+:limit => 2147483647$}, output
192
+ end
193
+ end
194
+
195
+ def test_schema_dump_includes_decimal_options
196
+ stream = StringIO.new
197
+ ActiveRecord::SchemaDumper.ignore_tables = [/^[^n]/]
198
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
199
+ output = stream.string
200
+ assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
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
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