ibm_db 2.5.26-universal-darwin-14 → 2.6.1-universal-darwin-14

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. checksums.yaml +4 -4
  2. data/CHANGES +11 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +264 -261
  8. data/ext/extconf_MacOS.rb +269 -0
  9. data/ext/ibm_db.c +11879 -11793
  10. data/ext/ruby_ibm_db.h +241 -240
  11. data/ext/ruby_ibm_db_cli.c +851 -845
  12. data/ext/ruby_ibm_db_cli.h +500 -489
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -19
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3339 -3289
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/test/cases/adapter_test.rb +207 -207
  19. data/test/cases/associations/belongs_to_associations_test.rb +711 -711
  20. data/test/cases/associations/cascaded_eager_loading_test.rb +181 -181
  21. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +851 -851
  22. data/test/cases/associations/join_model_test.rb +743 -743
  23. data/test/cases/attribute_methods_test.rb +822 -822
  24. data/test/cases/base_test.rb +2133 -2133
  25. data/test/cases/calculations_test.rb +482 -482
  26. data/test/cases/migration_test.rb +2408 -2408
  27. data/test/cases/persistence_test.rb +642 -642
  28. data/test/cases/query_cache_test.rb +257 -257
  29. data/test/cases/relations_test.rb +1182 -1182
  30. data/test/cases/schema_dumper_test.rb +256 -256
  31. data/test/cases/transaction_callbacks_test.rb +300 -300
  32. data/test/cases/validations/uniqueness_validation_test.rb +299 -299
  33. data/test/cases/xml_serialization_test.rb +408 -408
  34. data/test/config.yml +154 -154
  35. data/test/connections/native_ibm_db/connection.rb +43 -43
  36. data/test/ibm_db_test.rb +24 -24
  37. data/test/models/warehouse_thing.rb +4 -4
  38. data/test/schema/schema.rb +751 -751
  39. metadata +6 -8
  40. data/lib/linux/rb18x/ibm_db.bundle +0 -0
  41. data/lib/linux/rb19x/ibm_db.bundle +0 -0
  42. data/lib/linux/rb20x/ibm_db.bundle +0 -0
  43. data/lib/linux/rb21x/ibm_db.bundle +0 -0
@@ -1,408 +1,408 @@
1
- require "cases/helper"
2
- require 'models/contact'
3
- require 'models/post'
4
- require 'models/author'
5
- require 'models/comment'
6
- require 'models/company_in_module'
7
- require 'models/toy'
8
- require 'models/topic'
9
- require 'models/reply'
10
- require 'models/company'
11
-
12
- class XmlSerializationTest < ActiveRecord::TestCase
13
- def test_should_serialize_default_root
14
- @xml = Contact.new.to_xml
15
- assert_match %r{^<contact>}, @xml
16
- assert_match %r{</contact>$}, @xml
17
- end
18
-
19
- def test_should_serialize_default_root_with_namespace
20
- @xml = Contact.new.to_xml :namespace=>"http://xml.rubyonrails.org/contact"
21
- assert_match %r{^<contact xmlns="http://xml.rubyonrails.org/contact">}, @xml
22
- assert_match %r{</contact>$}, @xml
23
- end
24
-
25
- def test_should_serialize_custom_root
26
- @xml = Contact.new.to_xml :root => 'xml_contact'
27
- assert_match %r{^<xml-contact>}, @xml
28
- assert_match %r{</xml-contact>$}, @xml
29
- end
30
-
31
- def test_should_allow_undasherized_tags
32
- @xml = Contact.new.to_xml :root => 'xml_contact', :dasherize => false
33
- assert_match %r{^<xml_contact>}, @xml
34
- assert_match %r{</xml_contact>$}, @xml
35
- assert_match %r{<created_at}, @xml
36
- end
37
-
38
- def test_should_allow_camelized_tags
39
- @xml = Contact.new.to_xml :root => 'xml_contact', :camelize => true
40
- assert_match %r{^<XmlContact>}, @xml
41
- assert_match %r{</XmlContact>$}, @xml
42
- assert_match %r{<CreatedAt}, @xml
43
- end
44
-
45
- def test_should_allow_skipped_types
46
- @xml = Contact.new(:age => 25).to_xml :skip_types => true
47
- assert %r{<age>25</age>}.match(@xml)
48
- end
49
-
50
- def test_should_include_yielded_additions
51
- @xml = Contact.new.to_xml do |xml|
52
- xml.creator "David"
53
- end
54
- assert_match %r{<creator>David</creator>}, @xml
55
- end
56
-
57
- def test_to_xml_with_block
58
- value = "Rockin' the block"
59
- xml = Contact.new.to_xml(:skip_instruct => true) do |_xml|
60
- _xml.tag! "arbitrary-element", value
61
- end
62
- assert_equal "<contact>", xml.first(9)
63
- assert xml.include?(%(<arbitrary-element>#{value}</arbitrary-element>))
64
- end
65
-
66
- def test_should_skip_instruct_for_included_records
67
- @contact = Contact.new
68
- @contact.alternative = Contact.new(:name => 'Copa Cabana')
69
- @xml = @contact.to_xml(:include => [ :alternative ])
70
- assert_equal @xml.index('<?xml '), 0
71
- assert_nil @xml.index('<?xml ', 1)
72
- end
73
- end
74
-
75
- class DefaultXmlSerializationTest < ActiveRecord::TestCase
76
- def setup
77
- @xml = Contact.new(:name => 'aaron stack', :age => 25, :avatar => 'binarydata', :created_at => Time.utc(2006, 8, 1), :awesome => false, :preferences => { :gem => 'ruby' }).to_xml
78
- end
79
-
80
- def test_should_serialize_string
81
- assert_match %r{<name>aaron stack</name>}, @xml
82
- end
83
-
84
- def test_should_serialize_integer
85
- assert_match %r{<age type="integer">25</age>}, @xml
86
- end
87
-
88
- def test_should_serialize_binary
89
- assert_match %r{YmluYXJ5ZGF0YQ==\n</avatar>}, @xml
90
- assert_match %r{<avatar(.*)(type="binary")}, @xml
91
- assert_match %r{<avatar(.*)(encoding="base64")}, @xml
92
- end
93
-
94
- def test_should_serialize_datetime
95
- assert_match %r{<created-at type=\"datetime\">2006-08-01T00:00:00Z</created-at>}, @xml
96
- end
97
-
98
- def test_should_serialize_boolean
99
- assert_match %r{<awesome type=\"boolean\">false</awesome>}, @xml
100
- end
101
-
102
- def test_should_serialize_hash
103
- assert_match %r{<preferences>\s*<gem>ruby</gem>\s*</preferences>}m, @xml
104
- end
105
- end
106
-
107
- class DefaultXmlSerializationTimezoneTest < ActiveRecord::TestCase
108
- def test_should_serialize_datetime_with_timezone
109
- timezone, Time.zone = Time.zone, "Pacific Time (US & Canada)"
110
-
111
- toy = Toy.create(:name => 'Mickey', :updated_at => Time.utc(2006, 8, 1))
112
- unless current_adapter?(:IBM_DBAdapter)
113
- assert_match %r{<updated-at type=\"datetime\">2006-07-31T17:00:00-07:00</updated-at>}, toy.to_xml
114
- else
115
- assert_match %r{<updated-at type=\"timestamp\">2006-07-31 17:00:00 -0700</updated-at>}, toy.to_xml
116
- end
117
- ensure
118
- Time.zone = timezone
119
- end
120
-
121
- def test_should_serialize_datetime_with_timezone_reloaded
122
- timezone, Time.zone = Time.zone, "Pacific Time (US & Canada)"
123
-
124
- toy = Toy.create(:name => 'Minnie', :updated_at => Time.utc(2006, 8, 1)).reload
125
- unless current_adapter?(:IBM_DBAdapter)
126
- assert_match %r{<updated-at type=\"datetime\">2006-07-31T17:00:00-07:00</updated-at>}, toy.to_xml
127
- else
128
- assert_match %r{<updated-at type=\"timestamp\">2006-07-31 17:00:00 -0700</updated-at>}, toy.to_xml
129
- end
130
- ensure
131
- Time.zone = timezone
132
- end
133
- end
134
-
135
- class NilXmlSerializationTest < ActiveRecord::TestCase
136
- def setup
137
- @xml = Contact.new.to_xml(:root => 'xml_contact')
138
- end
139
-
140
- def test_should_serialize_string
141
- assert_match %r{<name nil="true"></name>}, @xml
142
- end
143
-
144
- def test_should_serialize_integer
145
- assert %r{<age (.*)></age>}.match(@xml)
146
- attributes = $1
147
- assert_match %r{nil="true"}, attributes
148
- assert_match %r{type="integer"}, attributes
149
- end
150
-
151
- def test_should_serialize_binary
152
- assert %r{<avatar (.*)></avatar>}.match(@xml)
153
- attributes = $1
154
- assert_match %r{type="binary"}, attributes
155
- assert_match %r{encoding="base64"}, attributes
156
- assert_match %r{nil="true"}, attributes
157
- end
158
-
159
- def test_should_serialize_datetime
160
- assert %r{<created-at (.*)></created-at>}.match(@xml)
161
- attributes = $1
162
- assert_match %r{nil="true"}, attributes
163
- assert_match %r{type="datetime"}, attributes
164
- end
165
-
166
- def test_should_serialize_boolean
167
- assert %r{<awesome (.*)></awesome>}.match(@xml)
168
- attributes = $1
169
- assert_match %r{type="boolean"}, attributes
170
- assert_match %r{nil="true"}, attributes
171
- end
172
-
173
- def test_should_serialize_yaml
174
- assert_match %r{<preferences nil=\"true\"></preferences>}, @xml
175
- end
176
- end
177
-
178
- class DatabaseConnectedXmlSerializationTest < ActiveRecord::TestCase
179
- fixtures :topics, :companies, :accounts, :authors, :posts, :projects
180
-
181
- def test_to_xml
182
- xml = REXML::Document.new(topics(:first).to_xml(:indent => 0))
183
- bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema
184
- written_on_in_current_timezone = topics(:first).written_on.xmlschema
185
- last_read_in_current_timezone = topics(:first).last_read.xmlschema
186
-
187
- assert_equal "topic", xml.root.name
188
- assert_equal "The First Topic" , xml.elements["//title"].text
189
- assert_equal "David" , xml.elements["//author-name"].text
190
- assert_match "Have a nice day", xml.elements["//content"].text
191
-
192
- assert_equal "1", xml.elements["//id"].text
193
- assert_equal "integer" , xml.elements["//id"].attributes['type']
194
-
195
- assert_equal "1", xml.elements["//replies-count"].text
196
- assert_equal "integer" , xml.elements["//replies-count"].attributes['type']
197
-
198
- assert_equal written_on_in_current_timezone, xml.elements["//written-on"].text
199
- assert_equal "datetime" , xml.elements["//written-on"].attributes['type']
200
-
201
- assert_equal "david@loudthinking.com", xml.elements["//author-email-address"].text
202
-
203
- assert_equal nil, xml.elements["//parent-id"].text
204
- assert_equal "integer", xml.elements["//parent-id"].attributes['type']
205
- assert_equal "true", xml.elements["//parent-id"].attributes['nil']
206
-
207
- if current_adapter?(:SybaseAdapter)
208
- assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
209
- assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
210
- else
211
- # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
212
- assert_equal "2004-04-15", xml.elements["//last-read"].text
213
- assert_equal "date" , xml.elements["//last-read"].attributes['type']
214
- end
215
-
216
- # Oracle and DB2 don't have true boolean or time-only fields
217
- unless current_adapter?(:OracleAdapter, :DB2Adapter)
218
- assert_equal "false", xml.elements["//approved"].text
219
- assert_equal "boolean" , xml.elements["//approved"].attributes['type']
220
-
221
- assert_equal bonus_time_in_current_timezone, xml.elements["//bonus-time"].text
222
- assert_equal "datetime" , xml.elements["//bonus-time"].attributes['type']
223
- end
224
- end
225
-
226
- def test_except_option
227
- xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :replies_count])
228
- assert_equal "<topic>", xml.first(7)
229
- assert !xml.include?(%(<title>The First Topic</title>))
230
- assert xml.include?(%(<author-name>David</author-name>))
231
-
232
- xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :author_name, :replies_count])
233
- assert !xml.include?(%(<title>The First Topic</title>))
234
- assert !xml.include?(%(<author-name>David</author-name>))
235
- end
236
-
237
- # to_xml used to mess with the hash the user provided which
238
- # caused the builder to be reused. This meant the document kept
239
- # getting appended to.
240
-
241
- def test_modules
242
- projects = MyApplication::Business::Project.all
243
- xml = projects.to_xml
244
- root = projects.first.class.to_s.underscore.pluralize.tr('/','_').dasherize
245
- assert_match "<#{root} type=\"array\">", xml
246
- assert_match "</#{root}>", xml
247
- end
248
-
249
- def test_passing_hash_shouldnt_reuse_builder
250
- options = {:include=>:posts}
251
- david = authors(:david)
252
- first_xml_size = david.to_xml(options).size
253
- second_xml_size = david.to_xml(options).size
254
- assert_equal first_xml_size, second_xml_size
255
- end
256
-
257
- def test_include_uses_association_name
258
- xml = authors(:david).to_xml :include=>:hello_posts, :indent => 0
259
- assert_match %r{<hello-posts type="array">}, xml
260
- assert_match %r{<hello-post type="Post">}, xml
261
- assert_match %r{<hello-post type="StiPost">}, xml
262
- end
263
-
264
- def test_included_associations_should_skip_types
265
- xml = authors(:david).to_xml :include=>:hello_posts, :indent => 0, :skip_types => true
266
- assert_match %r{<hello-posts>}, xml
267
- assert_match %r{<hello-post>}, xml
268
- assert_match %r{<hello-post>}, xml
269
- end
270
-
271
- def test_including_has_many_association
272
- xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies, :except => :replies_count)
273
- assert_equal "<topic>", xml.first(7)
274
- assert xml.include?(%(<replies type="array"><reply>))
275
- assert xml.include?(%(<title>The Second Topic of the day</title>))
276
- end
277
-
278
- def test_including_belongs_to_association
279
- xml = companies(:first_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
280
- assert !xml.include?("<firm>")
281
-
282
- xml = companies(:second_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
283
- assert xml.include?("<firm>")
284
- end
285
-
286
- def test_including_multiple_associations
287
- xml = companies(:first_firm).to_xml(:indent => 0, :skip_instruct => true, :include => [ :clients, :account ])
288
- assert_equal "<firm>", xml.first(6)
289
- assert xml.include?(%(<account>))
290
- assert xml.include?(%(<clients type="array"><client>))
291
- end
292
-
293
- def test_including_association_with_options
294
- xml = companies(:first_firm).to_xml(
295
- :indent => 0, :skip_instruct => true,
296
- :include => { :clients => { :only => :name } }
297
- )
298
-
299
- assert_equal "<firm>", xml.first(6)
300
- assert xml.include?(%(<client><name>Summit</name></client>))
301
- assert xml.include?(%(<clients type="array"><client>))
302
- end
303
-
304
- def test_methods_are_called_on_object
305
- xml = authors(:david).to_xml :methods => :label, :indent => 0
306
- assert_match %r{<label>.*</label>}, xml
307
- end
308
-
309
- def test_should_not_call_methods_on_associations_that_dont_respond
310
- xml = authors(:david).to_xml :include=>:hello_posts, :methods => :label, :indent => 2
311
- assert !authors(:david).hello_posts.first.respond_to?(:label)
312
- assert_match %r{^ <label>.*</label>}, xml
313
- assert_no_match %r{^ <label>}, xml
314
- end
315
-
316
- def test_procs_are_called_on_object
317
- proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') }
318
- xml = authors(:david).to_xml(:procs => [ proc ])
319
- assert_match %r{<nationality>Danish</nationality>}, xml
320
- end
321
-
322
- def test_dual_arity_procs_are_called_on_object
323
- proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
324
- xml = authors(:david).to_xml(:procs => [ proc ])
325
- assert_match %r{<name-reverse>divaD</name-reverse>}, xml
326
- end
327
-
328
- def test_top_level_procs_arent_applied_to_associations
329
- author_proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') }
330
- xml = authors(:david).to_xml(:procs => [ author_proc ], :include => :posts, :indent => 2)
331
-
332
- assert_match %r{^ <nationality>Danish</nationality>}, xml
333
- assert_no_match %r{^ {6}<nationality>Danish</nationality>}, xml
334
- end
335
-
336
- def test_procs_on_included_associations_are_called
337
- posts_proc = Proc.new { |options| options[:builder].tag!('copyright', 'DHH') }
338
- xml = authors(:david).to_xml(
339
- :indent => 2,
340
- :include => {
341
- :posts => { :procs => [ posts_proc ] }
342
- }
343
- )
344
-
345
- assert_no_match %r{^ <copyright>DHH</copyright>}, xml
346
- assert_match %r{^ {6}<copyright>DHH</copyright>}, xml
347
- end
348
-
349
- def test_should_include_empty_has_many_as_empty_array
350
- authors(:david).posts.delete_all
351
- xml = authors(:david).to_xml :include=>:posts, :indent => 2
352
-
353
- assert_equal [], Hash.from_xml(xml)['author']['posts']
354
- assert_match %r{^ <posts type="array"/>}, xml
355
- end
356
-
357
- def test_should_has_many_array_elements_should_include_type_when_different_from_guessed_value
358
- xml = authors(:david).to_xml :include=>:posts_with_comments, :indent => 2
359
-
360
- assert Hash.from_xml(xml)
361
- assert_match %r{^ <posts-with-comments type="array">}, xml
362
- assert_match %r{^ <posts-with-comment type="Post">}, xml
363
- assert_match %r{^ <posts-with-comment type="StiPost">}, xml
364
-
365
- types = Hash.from_xml(xml)['author']['posts_with_comments'].collect {|t| t['type'] }
366
- assert types.include?('SpecialPost')
367
- assert types.include?('Post')
368
- assert types.include?('StiPost')
369
- end
370
-
371
- def test_should_produce_xml_for_methods_returning_array
372
- xml = authors(:david).to_xml(:methods => :social)
373
- array = Hash.from_xml(xml)['author']['social']
374
- assert_equal 2, array.size
375
- assert array.include? 'twitter'
376
- assert array.include? 'github'
377
- end
378
-
379
- def test_should_support_aliased_attributes
380
- xml = Author.select("name as firstname").to_xml
381
- array = Hash.from_xml(xml)['authors']
382
- assert_equal array.size, array.select { |author| author.has_key? 'firstname' }.size
383
- end
384
-
385
- def test_array_to_xml_including_has_many_association
386
- xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :include => :replies)
387
- assert xml.include?(%(<replies type="array"><reply>))
388
- end
389
-
390
- def test_array_to_xml_including_methods
391
- xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :methods => [ :topic_id ])
392
- assert xml.include?(%(<topic-id type="integer">#{topics(:first).topic_id}</topic-id>)), xml
393
- assert xml.include?(%(<topic-id type="integer">#{topics(:second).topic_id}</topic-id>)), xml
394
- end
395
-
396
- def test_array_to_xml_including_has_one_association
397
- xml = [ companies(:first_firm), companies(:rails_core) ].to_xml(:indent => 0, :skip_instruct => true, :include => :account)
398
- assert xml.include?(companies(:first_firm).account.to_xml(:indent => 0, :skip_instruct => true))
399
- assert xml.include?(companies(:rails_core).account.to_xml(:indent => 0, :skip_instruct => true))
400
- end
401
-
402
- def test_array_to_xml_including_belongs_to_association
403
- xml = [ companies(:first_client), companies(:second_client), companies(:another_client) ].to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
404
- assert xml.include?(companies(:first_client).to_xml(:indent => 0, :skip_instruct => true))
405
- assert xml.include?(companies(:second_client).firm.to_xml(:indent => 0, :skip_instruct => true))
406
- assert xml.include?(companies(:another_client).firm.to_xml(:indent => 0, :skip_instruct => true))
407
- end
408
- end
1
+ require "cases/helper"
2
+ require 'models/contact'
3
+ require 'models/post'
4
+ require 'models/author'
5
+ require 'models/comment'
6
+ require 'models/company_in_module'
7
+ require 'models/toy'
8
+ require 'models/topic'
9
+ require 'models/reply'
10
+ require 'models/company'
11
+
12
+ class XmlSerializationTest < ActiveRecord::TestCase
13
+ def test_should_serialize_default_root
14
+ @xml = Contact.new.to_xml
15
+ assert_match %r{^<contact>}, @xml
16
+ assert_match %r{</contact>$}, @xml
17
+ end
18
+
19
+ def test_should_serialize_default_root_with_namespace
20
+ @xml = Contact.new.to_xml :namespace=>"http://xml.rubyonrails.org/contact"
21
+ assert_match %r{^<contact xmlns="http://xml.rubyonrails.org/contact">}, @xml
22
+ assert_match %r{</contact>$}, @xml
23
+ end
24
+
25
+ def test_should_serialize_custom_root
26
+ @xml = Contact.new.to_xml :root => 'xml_contact'
27
+ assert_match %r{^<xml-contact>}, @xml
28
+ assert_match %r{</xml-contact>$}, @xml
29
+ end
30
+
31
+ def test_should_allow_undasherized_tags
32
+ @xml = Contact.new.to_xml :root => 'xml_contact', :dasherize => false
33
+ assert_match %r{^<xml_contact>}, @xml
34
+ assert_match %r{</xml_contact>$}, @xml
35
+ assert_match %r{<created_at}, @xml
36
+ end
37
+
38
+ def test_should_allow_camelized_tags
39
+ @xml = Contact.new.to_xml :root => 'xml_contact', :camelize => true
40
+ assert_match %r{^<XmlContact>}, @xml
41
+ assert_match %r{</XmlContact>$}, @xml
42
+ assert_match %r{<CreatedAt}, @xml
43
+ end
44
+
45
+ def test_should_allow_skipped_types
46
+ @xml = Contact.new(:age => 25).to_xml :skip_types => true
47
+ assert %r{<age>25</age>}.match(@xml)
48
+ end
49
+
50
+ def test_should_include_yielded_additions
51
+ @xml = Contact.new.to_xml do |xml|
52
+ xml.creator "David"
53
+ end
54
+ assert_match %r{<creator>David</creator>}, @xml
55
+ end
56
+
57
+ def test_to_xml_with_block
58
+ value = "Rockin' the block"
59
+ xml = Contact.new.to_xml(:skip_instruct => true) do |_xml|
60
+ _xml.tag! "arbitrary-element", value
61
+ end
62
+ assert_equal "<contact>", xml.first(9)
63
+ assert xml.include?(%(<arbitrary-element>#{value}</arbitrary-element>))
64
+ end
65
+
66
+ def test_should_skip_instruct_for_included_records
67
+ @contact = Contact.new
68
+ @contact.alternative = Contact.new(:name => 'Copa Cabana')
69
+ @xml = @contact.to_xml(:include => [ :alternative ])
70
+ assert_equal @xml.index('<?xml '), 0
71
+ assert_nil @xml.index('<?xml ', 1)
72
+ end
73
+ end
74
+
75
+ class DefaultXmlSerializationTest < ActiveRecord::TestCase
76
+ def setup
77
+ @xml = Contact.new(:name => 'aaron stack', :age => 25, :avatar => 'binarydata', :created_at => Time.utc(2006, 8, 1), :awesome => false, :preferences => { :gem => 'ruby' }).to_xml
78
+ end
79
+
80
+ def test_should_serialize_string
81
+ assert_match %r{<name>aaron stack</name>}, @xml
82
+ end
83
+
84
+ def test_should_serialize_integer
85
+ assert_match %r{<age type="integer">25</age>}, @xml
86
+ end
87
+
88
+ def test_should_serialize_binary
89
+ assert_match %r{YmluYXJ5ZGF0YQ==\n</avatar>}, @xml
90
+ assert_match %r{<avatar(.*)(type="binary")}, @xml
91
+ assert_match %r{<avatar(.*)(encoding="base64")}, @xml
92
+ end
93
+
94
+ def test_should_serialize_datetime
95
+ assert_match %r{<created-at type=\"datetime\">2006-08-01T00:00:00Z</created-at>}, @xml
96
+ end
97
+
98
+ def test_should_serialize_boolean
99
+ assert_match %r{<awesome type=\"boolean\">false</awesome>}, @xml
100
+ end
101
+
102
+ def test_should_serialize_hash
103
+ assert_match %r{<preferences>\s*<gem>ruby</gem>\s*</preferences>}m, @xml
104
+ end
105
+ end
106
+
107
+ class DefaultXmlSerializationTimezoneTest < ActiveRecord::TestCase
108
+ def test_should_serialize_datetime_with_timezone
109
+ timezone, Time.zone = Time.zone, "Pacific Time (US & Canada)"
110
+
111
+ toy = Toy.create(:name => 'Mickey', :updated_at => Time.utc(2006, 8, 1))
112
+ unless current_adapter?(:IBM_DBAdapter)
113
+ assert_match %r{<updated-at type=\"datetime\">2006-07-31T17:00:00-07:00</updated-at>}, toy.to_xml
114
+ else
115
+ assert_match %r{<updated-at type=\"timestamp\">2006-07-31 17:00:00 -0700</updated-at>}, toy.to_xml
116
+ end
117
+ ensure
118
+ Time.zone = timezone
119
+ end
120
+
121
+ def test_should_serialize_datetime_with_timezone_reloaded
122
+ timezone, Time.zone = Time.zone, "Pacific Time (US & Canada)"
123
+
124
+ toy = Toy.create(:name => 'Minnie', :updated_at => Time.utc(2006, 8, 1)).reload
125
+ unless current_adapter?(:IBM_DBAdapter)
126
+ assert_match %r{<updated-at type=\"datetime\">2006-07-31T17:00:00-07:00</updated-at>}, toy.to_xml
127
+ else
128
+ assert_match %r{<updated-at type=\"timestamp\">2006-07-31 17:00:00 -0700</updated-at>}, toy.to_xml
129
+ end
130
+ ensure
131
+ Time.zone = timezone
132
+ end
133
+ end
134
+
135
+ class NilXmlSerializationTest < ActiveRecord::TestCase
136
+ def setup
137
+ @xml = Contact.new.to_xml(:root => 'xml_contact')
138
+ end
139
+
140
+ def test_should_serialize_string
141
+ assert_match %r{<name nil="true"></name>}, @xml
142
+ end
143
+
144
+ def test_should_serialize_integer
145
+ assert %r{<age (.*)></age>}.match(@xml)
146
+ attributes = $1
147
+ assert_match %r{nil="true"}, attributes
148
+ assert_match %r{type="integer"}, attributes
149
+ end
150
+
151
+ def test_should_serialize_binary
152
+ assert %r{<avatar (.*)></avatar>}.match(@xml)
153
+ attributes = $1
154
+ assert_match %r{type="binary"}, attributes
155
+ assert_match %r{encoding="base64"}, attributes
156
+ assert_match %r{nil="true"}, attributes
157
+ end
158
+
159
+ def test_should_serialize_datetime
160
+ assert %r{<created-at (.*)></created-at>}.match(@xml)
161
+ attributes = $1
162
+ assert_match %r{nil="true"}, attributes
163
+ assert_match %r{type="datetime"}, attributes
164
+ end
165
+
166
+ def test_should_serialize_boolean
167
+ assert %r{<awesome (.*)></awesome>}.match(@xml)
168
+ attributes = $1
169
+ assert_match %r{type="boolean"}, attributes
170
+ assert_match %r{nil="true"}, attributes
171
+ end
172
+
173
+ def test_should_serialize_yaml
174
+ assert_match %r{<preferences nil=\"true\"></preferences>}, @xml
175
+ end
176
+ end
177
+
178
+ class DatabaseConnectedXmlSerializationTest < ActiveRecord::TestCase
179
+ fixtures :topics, :companies, :accounts, :authors, :posts, :projects
180
+
181
+ def test_to_xml
182
+ xml = REXML::Document.new(topics(:first).to_xml(:indent => 0))
183
+ bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema
184
+ written_on_in_current_timezone = topics(:first).written_on.xmlschema
185
+ last_read_in_current_timezone = topics(:first).last_read.xmlschema
186
+
187
+ assert_equal "topic", xml.root.name
188
+ assert_equal "The First Topic" , xml.elements["//title"].text
189
+ assert_equal "David" , xml.elements["//author-name"].text
190
+ assert_match "Have a nice day", xml.elements["//content"].text
191
+
192
+ assert_equal "1", xml.elements["//id"].text
193
+ assert_equal "integer" , xml.elements["//id"].attributes['type']
194
+
195
+ assert_equal "1", xml.elements["//replies-count"].text
196
+ assert_equal "integer" , xml.elements["//replies-count"].attributes['type']
197
+
198
+ assert_equal written_on_in_current_timezone, xml.elements["//written-on"].text
199
+ assert_equal "datetime" , xml.elements["//written-on"].attributes['type']
200
+
201
+ assert_equal "david@loudthinking.com", xml.elements["//author-email-address"].text
202
+
203
+ assert_equal nil, xml.elements["//parent-id"].text
204
+ assert_equal "integer", xml.elements["//parent-id"].attributes['type']
205
+ assert_equal "true", xml.elements["//parent-id"].attributes['nil']
206
+
207
+ if current_adapter?(:SybaseAdapter)
208
+ assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
209
+ assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
210
+ else
211
+ # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb)
212
+ assert_equal "2004-04-15", xml.elements["//last-read"].text
213
+ assert_equal "date" , xml.elements["//last-read"].attributes['type']
214
+ end
215
+
216
+ # Oracle and DB2 don't have true boolean or time-only fields
217
+ unless current_adapter?(:OracleAdapter, :DB2Adapter)
218
+ assert_equal "false", xml.elements["//approved"].text
219
+ assert_equal "boolean" , xml.elements["//approved"].attributes['type']
220
+
221
+ assert_equal bonus_time_in_current_timezone, xml.elements["//bonus-time"].text
222
+ assert_equal "datetime" , xml.elements["//bonus-time"].attributes['type']
223
+ end
224
+ end
225
+
226
+ def test_except_option
227
+ xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :replies_count])
228
+ assert_equal "<topic>", xml.first(7)
229
+ assert !xml.include?(%(<title>The First Topic</title>))
230
+ assert xml.include?(%(<author-name>David</author-name>))
231
+
232
+ xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :except => [:title, :author_name, :replies_count])
233
+ assert !xml.include?(%(<title>The First Topic</title>))
234
+ assert !xml.include?(%(<author-name>David</author-name>))
235
+ end
236
+
237
+ # to_xml used to mess with the hash the user provided which
238
+ # caused the builder to be reused. This meant the document kept
239
+ # getting appended to.
240
+
241
+ def test_modules
242
+ projects = MyApplication::Business::Project.all
243
+ xml = projects.to_xml
244
+ root = projects.first.class.to_s.underscore.pluralize.tr('/','_').dasherize
245
+ assert_match "<#{root} type=\"array\">", xml
246
+ assert_match "</#{root}>", xml
247
+ end
248
+
249
+ def test_passing_hash_shouldnt_reuse_builder
250
+ options = {:include=>:posts}
251
+ david = authors(:david)
252
+ first_xml_size = david.to_xml(options).size
253
+ second_xml_size = david.to_xml(options).size
254
+ assert_equal first_xml_size, second_xml_size
255
+ end
256
+
257
+ def test_include_uses_association_name
258
+ xml = authors(:david).to_xml :include=>:hello_posts, :indent => 0
259
+ assert_match %r{<hello-posts type="array">}, xml
260
+ assert_match %r{<hello-post type="Post">}, xml
261
+ assert_match %r{<hello-post type="StiPost">}, xml
262
+ end
263
+
264
+ def test_included_associations_should_skip_types
265
+ xml = authors(:david).to_xml :include=>:hello_posts, :indent => 0, :skip_types => true
266
+ assert_match %r{<hello-posts>}, xml
267
+ assert_match %r{<hello-post>}, xml
268
+ assert_match %r{<hello-post>}, xml
269
+ end
270
+
271
+ def test_including_has_many_association
272
+ xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies, :except => :replies_count)
273
+ assert_equal "<topic>", xml.first(7)
274
+ assert xml.include?(%(<replies type="array"><reply>))
275
+ assert xml.include?(%(<title>The Second Topic of the day</title>))
276
+ end
277
+
278
+ def test_including_belongs_to_association
279
+ xml = companies(:first_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
280
+ assert !xml.include?("<firm>")
281
+
282
+ xml = companies(:second_client).to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
283
+ assert xml.include?("<firm>")
284
+ end
285
+
286
+ def test_including_multiple_associations
287
+ xml = companies(:first_firm).to_xml(:indent => 0, :skip_instruct => true, :include => [ :clients, :account ])
288
+ assert_equal "<firm>", xml.first(6)
289
+ assert xml.include?(%(<account>))
290
+ assert xml.include?(%(<clients type="array"><client>))
291
+ end
292
+
293
+ def test_including_association_with_options
294
+ xml = companies(:first_firm).to_xml(
295
+ :indent => 0, :skip_instruct => true,
296
+ :include => { :clients => { :only => :name } }
297
+ )
298
+
299
+ assert_equal "<firm>", xml.first(6)
300
+ assert xml.include?(%(<client><name>Summit</name></client>))
301
+ assert xml.include?(%(<clients type="array"><client>))
302
+ end
303
+
304
+ def test_methods_are_called_on_object
305
+ xml = authors(:david).to_xml :methods => :label, :indent => 0
306
+ assert_match %r{<label>.*</label>}, xml
307
+ end
308
+
309
+ def test_should_not_call_methods_on_associations_that_dont_respond
310
+ xml = authors(:david).to_xml :include=>:hello_posts, :methods => :label, :indent => 2
311
+ assert !authors(:david).hello_posts.first.respond_to?(:label)
312
+ assert_match %r{^ <label>.*</label>}, xml
313
+ assert_no_match %r{^ <label>}, xml
314
+ end
315
+
316
+ def test_procs_are_called_on_object
317
+ proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') }
318
+ xml = authors(:david).to_xml(:procs => [ proc ])
319
+ assert_match %r{<nationality>Danish</nationality>}, xml
320
+ end
321
+
322
+ def test_dual_arity_procs_are_called_on_object
323
+ proc = Proc.new { |options, record| options[:builder].tag!('name-reverse', record.name.reverse) }
324
+ xml = authors(:david).to_xml(:procs => [ proc ])
325
+ assert_match %r{<name-reverse>divaD</name-reverse>}, xml
326
+ end
327
+
328
+ def test_top_level_procs_arent_applied_to_associations
329
+ author_proc = Proc.new { |options| options[:builder].tag!('nationality', 'Danish') }
330
+ xml = authors(:david).to_xml(:procs => [ author_proc ], :include => :posts, :indent => 2)
331
+
332
+ assert_match %r{^ <nationality>Danish</nationality>}, xml
333
+ assert_no_match %r{^ {6}<nationality>Danish</nationality>}, xml
334
+ end
335
+
336
+ def test_procs_on_included_associations_are_called
337
+ posts_proc = Proc.new { |options| options[:builder].tag!('copyright', 'DHH') }
338
+ xml = authors(:david).to_xml(
339
+ :indent => 2,
340
+ :include => {
341
+ :posts => { :procs => [ posts_proc ] }
342
+ }
343
+ )
344
+
345
+ assert_no_match %r{^ <copyright>DHH</copyright>}, xml
346
+ assert_match %r{^ {6}<copyright>DHH</copyright>}, xml
347
+ end
348
+
349
+ def test_should_include_empty_has_many_as_empty_array
350
+ authors(:david).posts.delete_all
351
+ xml = authors(:david).to_xml :include=>:posts, :indent => 2
352
+
353
+ assert_equal [], Hash.from_xml(xml)['author']['posts']
354
+ assert_match %r{^ <posts type="array"/>}, xml
355
+ end
356
+
357
+ def test_should_has_many_array_elements_should_include_type_when_different_from_guessed_value
358
+ xml = authors(:david).to_xml :include=>:posts_with_comments, :indent => 2
359
+
360
+ assert Hash.from_xml(xml)
361
+ assert_match %r{^ <posts-with-comments type="array">}, xml
362
+ assert_match %r{^ <posts-with-comment type="Post">}, xml
363
+ assert_match %r{^ <posts-with-comment type="StiPost">}, xml
364
+
365
+ types = Hash.from_xml(xml)['author']['posts_with_comments'].collect {|t| t['type'] }
366
+ assert types.include?('SpecialPost')
367
+ assert types.include?('Post')
368
+ assert types.include?('StiPost')
369
+ end
370
+
371
+ def test_should_produce_xml_for_methods_returning_array
372
+ xml = authors(:david).to_xml(:methods => :social)
373
+ array = Hash.from_xml(xml)['author']['social']
374
+ assert_equal 2, array.size
375
+ assert array.include? 'twitter'
376
+ assert array.include? 'github'
377
+ end
378
+
379
+ def test_should_support_aliased_attributes
380
+ xml = Author.select("name as firstname").to_xml
381
+ array = Hash.from_xml(xml)['authors']
382
+ assert_equal array.size, array.select { |author| author.has_key? 'firstname' }.size
383
+ end
384
+
385
+ def test_array_to_xml_including_has_many_association
386
+ xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :include => :replies)
387
+ assert xml.include?(%(<replies type="array"><reply>))
388
+ end
389
+
390
+ def test_array_to_xml_including_methods
391
+ xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :methods => [ :topic_id ])
392
+ assert xml.include?(%(<topic-id type="integer">#{topics(:first).topic_id}</topic-id>)), xml
393
+ assert xml.include?(%(<topic-id type="integer">#{topics(:second).topic_id}</topic-id>)), xml
394
+ end
395
+
396
+ def test_array_to_xml_including_has_one_association
397
+ xml = [ companies(:first_firm), companies(:rails_core) ].to_xml(:indent => 0, :skip_instruct => true, :include => :account)
398
+ assert xml.include?(companies(:first_firm).account.to_xml(:indent => 0, :skip_instruct => true))
399
+ assert xml.include?(companies(:rails_core).account.to_xml(:indent => 0, :skip_instruct => true))
400
+ end
401
+
402
+ def test_array_to_xml_including_belongs_to_association
403
+ xml = [ companies(:first_client), companies(:second_client), companies(:another_client) ].to_xml(:indent => 0, :skip_instruct => true, :include => :firm)
404
+ assert xml.include?(companies(:first_client).to_xml(:indent => 0, :skip_instruct => true))
405
+ assert xml.include?(companies(:second_client).firm.to_xml(:indent => 0, :skip_instruct => true))
406
+ assert xml.include?(companies(:another_client).firm.to_xml(:indent => 0, :skip_instruct => true))
407
+ end
408
+ end