db2 2.6.2 → 2.7.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/CHANGES +17 -0
- data/README +79 -141
- data/ext/Makefile.nt32 +3 -3
- data/ext/Makefile.nt32.191 +212 -0
- data/ext/extconf.rb +75 -14
- data/ext/ibm_db.c +504 -47
- data/ext/ruby_ibm_db.h +4 -1
- data/ext/ruby_ibm_db_cli.c +108 -1
- data/ext/ruby_ibm_db_cli.h +54 -1
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +423 -124
- data/lib/active_record/connection_adapters/ibm_db_pstmt.rb +1 -1
- data/test/cases/adapter_test.rb +169 -164
- data/test/cases/associations/belongs_to_associations_test.rb +268 -43
- data/test/cases/associations/cascaded_eager_loading_test.rb +31 -33
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +90 -156
- data/test/cases/associations/join_model_test.rb +100 -150
- data/test/cases/attribute_methods_test.rb +259 -58
- data/test/cases/base_test.rb +785 -138
- data/test/cases/calculations_test.rb +128 -8
- data/test/cases/migration_test.rb +680 -286
- data/test/cases/persistence_test.rb +642 -0
- data/test/cases/query_cache_test.rb +257 -0
- data/test/cases/relations_test.rb +1182 -0
- data/test/cases/schema_dumper_test.rb +41 -17
- data/test/cases/transaction_callbacks_test.rb +300 -0
- data/test/cases/validations/uniqueness_validation_test.rb +38 -22
- data/test/cases/xml_serialization_test.rb +408 -0
- data/test/config.yml +154 -0
- data/test/connections/native_ibm_db/connection.rb +2 -0
- data/test/models/warehouse_thing.rb +4 -4
- data/test/schema/i5/ibm_db_specific_schema.rb +3 -1
- data/test/schema/ids/ibm_db_specific_schema.rb +3 -1
- data/test/schema/luw/ibm_db_specific_schema.rb +2 -0
- data/test/schema/schema.rb +196 -92
- data/test/schema/zOS/ibm_db_specific_schema.rb +3 -1
- metadata +73 -68
- data/.gitignore +0 -1
- data/test/cases/associations/eager_test.rb +0 -862
- data/test/cases/associations/has_many_through_associations_test.rb +0 -461
- data/test/cases/finder_test.rb +0 -1088
- data/test/cases/fixtures_test.rb +0 -684
@@ -1,13 +1,22 @@
|
|
1
1
|
require "cases/helper"
|
2
|
-
require 'stringio'
|
3
2
|
|
4
3
|
|
5
4
|
class SchemaDumperTest < ActiveRecord::TestCase
|
5
|
+
def setup
|
6
|
+
@stream = StringIO.new
|
7
|
+
end
|
8
|
+
|
6
9
|
def standard_dump
|
7
|
-
stream = StringIO.new
|
10
|
+
@stream = StringIO.new
|
8
11
|
ActiveRecord::SchemaDumper.ignore_tables = []
|
9
|
-
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, stream)
|
10
|
-
stream.string
|
12
|
+
ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, @stream)
|
13
|
+
@stream.string
|
14
|
+
end
|
15
|
+
|
16
|
+
if "string".encoding_aware?
|
17
|
+
def test_magic_comment
|
18
|
+
assert_match "# encoding: #{@stream.external_encoding.name}", standard_dump
|
19
|
+
end
|
11
20
|
end
|
12
21
|
|
13
22
|
def test_schema_dump
|
@@ -22,9 +31,12 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
22
31
|
assert_no_match %r{create_table "sqlite_sequence"}, output
|
23
32
|
end
|
24
33
|
|
25
|
-
|
26
|
-
|
27
|
-
|
34
|
+
def test_schema_dump_includes_camelcase_table_name
|
35
|
+
output = standard_dump
|
36
|
+
if current_adapter?(:IBM_DBAdapter)
|
37
|
+
#DB2 is case insensitive
|
38
|
+
assert_match %r{create_table "camelcase"}, output
|
39
|
+
else
|
28
40
|
assert_match %r{create_table "CamelCase"}, output
|
29
41
|
end
|
30
42
|
end
|
@@ -102,7 +114,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
102
114
|
|
103
115
|
assert_match %r{c_int_4.*}, output
|
104
116
|
assert_no_match %r{c_int_4.*:limit}, output
|
105
|
-
elsif current_adapter?(:
|
117
|
+
elsif current_adapter?(:SQLite3Adapter)
|
106
118
|
assert_match %r{c_int_1.*:limit => 1}, output
|
107
119
|
assert_match %r{c_int_2.*:limit => 2}, output
|
108
120
|
assert_match %r{c_int_3.*:limit => 3}, output
|
@@ -111,7 +123,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
111
123
|
assert_match %r{c_int_without_limit.*}, output
|
112
124
|
assert_no_match %r{c_int_without_limit.*:limit}, output
|
113
125
|
|
114
|
-
if current_adapter?(:
|
126
|
+
if current_adapter?(:SQLite3Adapter)
|
115
127
|
assert_match %r{c_int_5.*:limit => 5}, output
|
116
128
|
assert_match %r{c_int_6.*:limit => 6}, output
|
117
129
|
assert_match %r{c_int_7.*:limit => 7}, output
|
@@ -121,13 +133,13 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
121
133
|
assert_match %r{c_int_6.*:limit => 6}, output
|
122
134
|
assert_match %r{c_int_7.*:limit => 7}, output
|
123
135
|
assert_match %r{c_int_8.*:limit => 8}, output
|
136
|
+
elsif current_adapter?(:IBM_DBAdapter)
|
137
|
+
#Limits is not supported on integer column by DB2
|
124
138
|
else
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
assert_match %r{c_int_8.*:limit => 8}, output
|
130
|
-
end
|
139
|
+
assert_match %r{c_int_5.*:limit => 8}, output
|
140
|
+
assert_match %r{c_int_6.*:limit => 8}, output
|
141
|
+
assert_match %r{c_int_7.*:limit => 8}, output
|
142
|
+
assert_match %r{c_int_8.*:limit => 8}, output
|
131
143
|
end
|
132
144
|
end
|
133
145
|
|
@@ -207,6 +219,13 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
207
219
|
assert_match %r{t.xml "data"}, output
|
208
220
|
end
|
209
221
|
end
|
222
|
+
|
223
|
+
def test_schema_dump_includes_tsvector_shorthand_definition
|
224
|
+
output = standard_dump
|
225
|
+
if %r{create_table "postgresql_tsvectors"} =~ output
|
226
|
+
assert_match %r{t.tsvector "text_vector"}, output
|
227
|
+
end
|
228
|
+
end
|
210
229
|
end
|
211
230
|
|
212
231
|
def test_schema_dump_keeps_large_precision_integer_columns_as_decimal
|
@@ -215,7 +234,8 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
215
234
|
if current_adapter?(:OracleAdapter)
|
216
235
|
assert_match %r{t.integer\s+"atoms_in_universe",\s+:precision => 38,\s+:scale => 0}, output
|
217
236
|
elsif current_adapter?(:IBM_DBAdapter)
|
218
|
-
|
237
|
+
# DB2 supports precision up to 31
|
238
|
+
assert_match %r{t.decimal\s+"atoms_in_universe",\s+:precision => 31,\s+:scale => 0}, output
|
219
239
|
else
|
220
240
|
assert_match %r{t.decimal\s+"atoms_in_universe",\s+:precision => 55,\s+:scale => 0}, output
|
221
241
|
end
|
@@ -228,5 +248,9 @@ class SchemaDumperTest < ActiveRecord::TestCase
|
|
228
248
|
assert_match %r(:id => false), match[1], "no table id not preserved"
|
229
249
|
assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved"
|
230
250
|
end
|
231
|
-
end
|
232
251
|
|
252
|
+
def test_schema_dump_keeps_id_false_when_id_is_false_and_unique_not_null_column_added
|
253
|
+
output = standard_dump
|
254
|
+
assert_match %r{create_table "subscribers", :id => false}, output
|
255
|
+
end
|
256
|
+
end
|
@@ -0,0 +1,300 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/topic'
|
3
|
+
|
4
|
+
class TransactionCallbacksTest < ActiveRecord::TestCase
|
5
|
+
self.use_transactional_fixtures = false
|
6
|
+
fixtures :topics
|
7
|
+
|
8
|
+
class TopicWithCallbacks < ActiveRecord::Base
|
9
|
+
self.table_name = :topics
|
10
|
+
|
11
|
+
after_commit{|record| record.send(:do_after_commit, nil)}
|
12
|
+
after_commit(:on => :create){|record| record.send(:do_after_commit, :create)}
|
13
|
+
after_commit(:on => :update){|record| record.send(:do_after_commit, :update)}
|
14
|
+
after_commit(:on => :destroy){|record| record.send(:do_after_commit, :destroy)}
|
15
|
+
after_rollback{|record| record.send(:do_after_rollback, nil)}
|
16
|
+
after_rollback(:on => :create){|record| record.send(:do_after_rollback, :create)}
|
17
|
+
after_rollback(:on => :update){|record| record.send(:do_after_rollback, :update)}
|
18
|
+
after_rollback(:on => :destroy){|record| record.send(:do_after_rollback, :destroy)}
|
19
|
+
|
20
|
+
def history
|
21
|
+
@history ||= []
|
22
|
+
end
|
23
|
+
|
24
|
+
def after_commit_block(on = nil, &block)
|
25
|
+
@after_commit ||= {}
|
26
|
+
@after_commit[on] ||= []
|
27
|
+
@after_commit[on] << block
|
28
|
+
end
|
29
|
+
|
30
|
+
def after_rollback_block(on = nil, &block)
|
31
|
+
@after_rollback ||= {}
|
32
|
+
@after_rollback[on] ||= []
|
33
|
+
@after_rollback[on] << block
|
34
|
+
end
|
35
|
+
|
36
|
+
def do_after_commit(on)
|
37
|
+
blocks = @after_commit[on] if defined?(@after_commit)
|
38
|
+
blocks.each{|b| b.call(self)} if blocks
|
39
|
+
end
|
40
|
+
|
41
|
+
def do_after_rollback(on)
|
42
|
+
blocks = @after_rollback[on] if defined?(@after_rollback)
|
43
|
+
blocks.each{|b| b.call(self)} if blocks
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def setup
|
48
|
+
@first, @second = TopicWithCallbacks.find(1, 3).sort_by { |t| t.id }
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_call_after_commit_after_transaction_commits
|
52
|
+
@first.after_commit_block{|r| r.history << :after_commit}
|
53
|
+
@first.after_rollback_block{|r| r.history << :after_rollback}
|
54
|
+
|
55
|
+
@first.save!
|
56
|
+
assert_equal [:after_commit], @first.history
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_only_call_after_commit_on_update_after_transaction_commits_for_existing_record
|
60
|
+
@first.after_commit_block(:create){|r| r.history << :commit_on_create}
|
61
|
+
@first.after_commit_block(:update){|r| r.history << :commit_on_update}
|
62
|
+
@first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
|
63
|
+
@first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
|
64
|
+
@first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
|
65
|
+
@first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
|
66
|
+
|
67
|
+
@first.save!
|
68
|
+
assert_equal [:commit_on_update], @first.history
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_only_call_after_commit_on_destroy_after_transaction_commits_for_destroyed_record
|
72
|
+
@first.after_commit_block(:create){|r| r.history << :commit_on_create}
|
73
|
+
@first.after_commit_block(:update){|r| r.history << :commit_on_update}
|
74
|
+
@first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
|
75
|
+
@first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
|
76
|
+
@first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
|
77
|
+
@first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
|
78
|
+
|
79
|
+
@first.destroy
|
80
|
+
assert_equal [:commit_on_destroy], @first.history
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_only_call_after_commit_on_create_after_transaction_commits_for_new_record
|
84
|
+
unless current_adapter?(:IBM_DBAdapter)
|
85
|
+
@new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
|
86
|
+
else
|
87
|
+
@new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Time.now)
|
88
|
+
end
|
89
|
+
@new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
|
90
|
+
@new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
|
91
|
+
@new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
|
92
|
+
@new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
|
93
|
+
@new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
|
94
|
+
@new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
|
95
|
+
|
96
|
+
@new_record.save!
|
97
|
+
assert_equal [:commit_on_create], @new_record.history
|
98
|
+
end
|
99
|
+
|
100
|
+
def test_call_after_rollback_after_transaction_rollsback
|
101
|
+
@first.after_commit_block{|r| r.history << :after_commit}
|
102
|
+
@first.after_rollback_block{|r| r.history << :after_rollback}
|
103
|
+
|
104
|
+
Topic.transaction do
|
105
|
+
@first.save!
|
106
|
+
raise ActiveRecord::Rollback
|
107
|
+
end
|
108
|
+
|
109
|
+
assert_equal [:after_rollback], @first.history
|
110
|
+
end
|
111
|
+
|
112
|
+
def test_only_call_after_rollback_on_update_after_transaction_rollsback_for_existing_record
|
113
|
+
@first.after_commit_block(:create){|r| r.history << :commit_on_create}
|
114
|
+
@first.after_commit_block(:update){|r| r.history << :commit_on_update}
|
115
|
+
@first.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
|
116
|
+
@first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
|
117
|
+
@first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
|
118
|
+
@first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
|
119
|
+
|
120
|
+
Topic.transaction do
|
121
|
+
@first.save!
|
122
|
+
raise ActiveRecord::Rollback
|
123
|
+
end
|
124
|
+
|
125
|
+
assert_equal [:rollback_on_update], @first.history
|
126
|
+
end
|
127
|
+
|
128
|
+
def test_only_call_after_rollback_on_destroy_after_transaction_rollsback_for_destroyed_record
|
129
|
+
@first.after_commit_block(:create){|r| r.history << :commit_on_create}
|
130
|
+
@first.after_commit_block(:update){|r| r.history << :commit_on_update}
|
131
|
+
@first.after_commit_block(:destroy){|r| r.history << :commit_on_update}
|
132
|
+
@first.after_rollback_block(:create){|r| r.history << :rollback_on_create}
|
133
|
+
@first.after_rollback_block(:update){|r| r.history << :rollback_on_update}
|
134
|
+
@first.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
|
135
|
+
|
136
|
+
Topic.transaction do
|
137
|
+
@first.destroy
|
138
|
+
raise ActiveRecord::Rollback
|
139
|
+
end
|
140
|
+
|
141
|
+
assert_equal [:rollback_on_destroy], @first.history
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_only_call_after_rollback_on_create_after_transaction_rollsback_for_new_record
|
145
|
+
unless current_adapter?(:IBM_DBAdapter)
|
146
|
+
@new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Date.today)
|
147
|
+
else
|
148
|
+
@new_record = TopicWithCallbacks.new(:title => "New topic", :written_on => Time.now)
|
149
|
+
end
|
150
|
+
@new_record.after_commit_block(:create){|r| r.history << :commit_on_create}
|
151
|
+
@new_record.after_commit_block(:update){|r| r.history << :commit_on_update}
|
152
|
+
@new_record.after_commit_block(:destroy){|r| r.history << :commit_on_destroy}
|
153
|
+
@new_record.after_rollback_block(:create){|r| r.history << :rollback_on_create}
|
154
|
+
@new_record.after_rollback_block(:update){|r| r.history << :rollback_on_update}
|
155
|
+
@new_record.after_rollback_block(:destroy){|r| r.history << :rollback_on_destroy}
|
156
|
+
|
157
|
+
Topic.transaction do
|
158
|
+
@new_record.save!
|
159
|
+
raise ActiveRecord::Rollback
|
160
|
+
end
|
161
|
+
|
162
|
+
assert_equal [:rollback_on_create], @new_record.history
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_call_after_rollback_when_commit_fails
|
166
|
+
@first.connection.class.send(:alias_method, :real_method_commit_db_transaction, :commit_db_transaction)
|
167
|
+
begin
|
168
|
+
@first.connection.class.class_eval do
|
169
|
+
def commit_db_transaction; raise "boom!"; end
|
170
|
+
end
|
171
|
+
|
172
|
+
@first.after_commit_block{|r| r.history << :after_commit}
|
173
|
+
@first.after_rollback_block{|r| r.history << :after_rollback}
|
174
|
+
|
175
|
+
assert !@first.save rescue nil
|
176
|
+
assert_equal [:after_rollback], @first.history
|
177
|
+
ensure
|
178
|
+
@first.connection.class.send(:remove_method, :commit_db_transaction)
|
179
|
+
@first.connection.class.send(:alias_method, :commit_db_transaction, :real_method_commit_db_transaction)
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint
|
184
|
+
def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
|
185
|
+
def @first.commits(i=0); @commits ||= 0; @commits += i if i; end
|
186
|
+
@first.after_rollback_block{|r| r.rollbacks(1)}
|
187
|
+
@first.after_commit_block{|r| r.commits(1)}
|
188
|
+
|
189
|
+
def @second.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
|
190
|
+
def @second.commits(i=0); @commits ||= 0; @commits += i if i; end
|
191
|
+
@second.after_rollback_block{|r| r.rollbacks(1)}
|
192
|
+
@second.after_commit_block{|r| r.commits(1)}
|
193
|
+
|
194
|
+
Topic.transaction do
|
195
|
+
@first.save!
|
196
|
+
Topic.transaction(:requires_new => true) do
|
197
|
+
@second.save!
|
198
|
+
raise ActiveRecord::Rollback
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
assert_equal 1, @first.commits
|
203
|
+
assert_equal 0, @first.rollbacks
|
204
|
+
assert_equal 0, @second.commits
|
205
|
+
assert_equal 1, @second.rollbacks
|
206
|
+
end
|
207
|
+
|
208
|
+
def test_only_call_after_rollback_on_records_rolled_back_to_a_savepoint_when_release_savepoint_fails
|
209
|
+
def @first.rollbacks(i=0); @rollbacks ||= 0; @rollbacks += i if i; end
|
210
|
+
def @first.commits(i=0); @commits ||= 0; @commits += i if i; end
|
211
|
+
|
212
|
+
@first.after_rollback_block{|r| r.rollbacks(1)}
|
213
|
+
@first.after_commit_block{|r| r.commits(1)}
|
214
|
+
|
215
|
+
Topic.transaction do
|
216
|
+
@first.save
|
217
|
+
Topic.transaction(:requires_new => true) do
|
218
|
+
@first.save!
|
219
|
+
raise ActiveRecord::Rollback
|
220
|
+
end
|
221
|
+
Topic.transaction(:requires_new => true) do
|
222
|
+
@first.save!
|
223
|
+
raise ActiveRecord::Rollback
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
assert_equal 1, @first.commits
|
228
|
+
assert_equal 2, @first.rollbacks
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_after_transaction_callbacks_should_prevent_callbacks_from_being_called
|
232
|
+
def @first.last_after_transaction_error=(e); @last_transaction_error = e; end
|
233
|
+
def @first.last_after_transaction_error; @last_transaction_error; end
|
234
|
+
@first.after_commit_block{|r| r.last_after_transaction_error = :commit; raise "fail!";}
|
235
|
+
@first.after_rollback_block{|r| r.last_after_transaction_error = :rollback; raise "fail!";}
|
236
|
+
@second.after_commit_block{|r| r.history << :after_commit}
|
237
|
+
@second.after_rollback_block{|r| r.history << :after_rollback}
|
238
|
+
|
239
|
+
Topic.transaction do
|
240
|
+
@first.save!
|
241
|
+
@second.save!
|
242
|
+
end
|
243
|
+
assert_equal :commit, @first.last_after_transaction_error
|
244
|
+
assert_equal [:after_commit], @second.history
|
245
|
+
|
246
|
+
@second.history.clear
|
247
|
+
Topic.transaction do
|
248
|
+
@first.save!
|
249
|
+
@second.save!
|
250
|
+
raise ActiveRecord::Rollback
|
251
|
+
end
|
252
|
+
assert_equal :rollback, @first.last_after_transaction_error
|
253
|
+
assert_equal [:after_rollback], @second.history
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
|
258
|
+
class TransactionObserverCallbacksTest < ActiveRecord::TestCase
|
259
|
+
self.use_transactional_fixtures = false
|
260
|
+
fixtures :topics
|
261
|
+
|
262
|
+
class TopicWithObserverAttached < ActiveRecord::Base
|
263
|
+
self.table_name = :topics
|
264
|
+
def history
|
265
|
+
@history ||= []
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
class TopicWithObserverAttachedObserver < ActiveRecord::Observer
|
270
|
+
def after_commit(record)
|
271
|
+
record.history.push "after_commit"
|
272
|
+
end
|
273
|
+
|
274
|
+
def after_rollback(record)
|
275
|
+
record.history.push "after_rollback"
|
276
|
+
end
|
277
|
+
end
|
278
|
+
|
279
|
+
def test_after_commit_called
|
280
|
+
assert TopicWithObserverAttachedObserver.instance, 'should have observer'
|
281
|
+
|
282
|
+
topic = TopicWithObserverAttached.new
|
283
|
+
topic.save!
|
284
|
+
|
285
|
+
assert_equal %w{ after_commit }, topic.history
|
286
|
+
end
|
287
|
+
|
288
|
+
def test_after_rollback_called
|
289
|
+
assert TopicWithObserverAttachedObserver.instance, 'should have observer'
|
290
|
+
|
291
|
+
topic = TopicWithObserverAttached.new
|
292
|
+
|
293
|
+
Topic.transaction do
|
294
|
+
topic.save!
|
295
|
+
raise ActiveRecord::Rollback
|
296
|
+
end
|
297
|
+
|
298
|
+
assert_equal %w{ after_rollback }, topic.history
|
299
|
+
end
|
300
|
+
end
|
@@ -6,19 +6,6 @@ require 'models/warehouse_thing'
|
|
6
6
|
require 'models/guid'
|
7
7
|
require 'models/event'
|
8
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
9
|
class Wizard < ActiveRecord::Base
|
23
10
|
self.abstract_class = true
|
24
11
|
|
@@ -36,7 +23,7 @@ class Thaumaturgist < IneptWizard
|
|
36
23
|
end
|
37
24
|
|
38
25
|
class UniquenessValidationTest < ActiveRecord::TestCase
|
39
|
-
fixtures :topics,
|
26
|
+
fixtures :topics, 'warehouse_things', :developers
|
40
27
|
|
41
28
|
repair_validations(Topic, Reply)
|
42
29
|
|
@@ -60,7 +47,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
60
47
|
|
61
48
|
def test_validates_uniqueness_with_validates
|
62
49
|
Topic.validates :title, :uniqueness => true
|
63
|
-
|
50
|
+
Topic.create!('title' => 'abc')
|
64
51
|
|
65
52
|
t2 = Topic.new('title' => 'abc')
|
66
53
|
assert !t2.valid?
|
@@ -175,6 +162,32 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
175
162
|
end
|
176
163
|
end
|
177
164
|
|
165
|
+
def test_validate_case_sensitive_uniqueness_with_special_sql_like_chars
|
166
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => true)
|
167
|
+
|
168
|
+
t = Topic.new("title" => "I'm unique!")
|
169
|
+
assert t.save, "Should save t as unique"
|
170
|
+
|
171
|
+
t2 = Topic.new("title" => "I'm %")
|
172
|
+
assert t2.save, "Should save t2 as unique"
|
173
|
+
|
174
|
+
t3 = Topic.new("title" => "I'm uniqu_!")
|
175
|
+
assert t3.save, "Should save t3 as unique"
|
176
|
+
end
|
177
|
+
|
178
|
+
def test_validate_case_insensitive_uniqueness_with_special_sql_like_chars
|
179
|
+
Topic.validates_uniqueness_of(:title, :case_sensitive => false)
|
180
|
+
|
181
|
+
t = Topic.new("title" => "I'm unique!")
|
182
|
+
assert t.save, "Should save t as unique"
|
183
|
+
|
184
|
+
t2 = Topic.new("title" => "I'm %")
|
185
|
+
assert t2.save, "Should save t2 as unique"
|
186
|
+
|
187
|
+
t3 = Topic.new("title" => "I'm uniqu_!")
|
188
|
+
assert t3.save, "Should save t3 as unique"
|
189
|
+
end
|
190
|
+
|
178
191
|
def test_validate_case_sensitive_uniqueness
|
179
192
|
Topic.validates_uniqueness_of(:title, :case_sensitive => true, :allow_nil => true)
|
180
193
|
|
@@ -201,7 +214,7 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
201
214
|
|
202
215
|
def test_validate_case_sensitive_uniqueness_with_attribute_passed_as_integer
|
203
216
|
Topic.validates_uniqueness_of(:title, :case_sensitve => true)
|
204
|
-
|
217
|
+
Topic.create!('title' => 101)
|
205
218
|
|
206
219
|
t2 = Topic.new('title' => 101)
|
207
220
|
assert !t2.valid?
|
@@ -243,12 +256,15 @@ class UniquenessValidationTest < ActiveRecord::TestCase
|
|
243
256
|
end
|
244
257
|
|
245
258
|
def test_validate_uniqueness_with_limit_and_utf8
|
246
|
-
|
247
|
-
#
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
259
|
+
unless current_adapter?(:IBM_DBAdapter)
|
260
|
+
# Limit for the varchar field is number of bytes and not characters for DB2. Hence the below test cases is expected to fail.
|
261
|
+
with_kcode('UTF8') do
|
262
|
+
# Event.title is limited to 5 characters
|
263
|
+
e1 = Event.create(:title => "一二三四五")
|
264
|
+
assert e1.valid?, "Could not create an event with a unique, 5 character title"
|
265
|
+
e2 = Event.create(:title => "一二三四五六七八")
|
266
|
+
assert !e2.valid?, "Created an event whose title, with limit taken into account, is not unique"
|
267
|
+
end
|
252
268
|
end
|
253
269
|
end
|
254
270
|
|