ibm_db 0.9.4 → 0.9.5

Sign up to get free protection for your applications and to get access to all the features.
data/test/base_test.rb CHANGED
@@ -11,6 +11,8 @@ require 'fixtures/column_name'
11
11
  require 'fixtures/subscriber'
12
12
  require 'fixtures/keyboard'
13
13
  require 'fixtures/post'
14
+ require 'fixtures/minimalistic'
15
+ require 'rexml/document'
14
16
 
15
17
  class Category < ActiveRecord::Base; end
16
18
  class Smarts < ActiveRecord::Base; end
@@ -38,6 +40,11 @@ class LooseDescendant < LoosePerson
38
40
  attr_protected :phone_number
39
41
  end
40
42
 
43
+ class LooseDescendantSecond< LoosePerson
44
+ attr_protected :phone_number
45
+ attr_protected :name
46
+ end
47
+
41
48
  class TightPerson < ActiveRecord::Base
42
49
  self.table_name = 'people'
43
50
  attr_accessible :name, :address
@@ -47,14 +54,24 @@ class TightDescendant < TightPerson
47
54
  attr_accessible :phone_number
48
55
  end
49
56
 
57
+ class ReadonlyTitlePost < Post
58
+ attr_readonly :title
59
+ end
60
+
50
61
  class Booleantest < ActiveRecord::Base; end
51
62
 
52
63
  class Task < ActiveRecord::Base
53
64
  attr_protected :starting
54
65
  end
55
66
 
56
- class BasicsTest < Test::Unit::TestCase
57
- fixtures :topics, :companies, :developers, :projects, :computers, :accounts
67
+ class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
68
+ self.table_name = 'topics'
69
+ attr_accessible :author_name
70
+ attr_protected :content
71
+ end
72
+
73
+ class IBMDBBasicsTest < Test::Unit::TestCase
74
+ fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics
58
75
 
59
76
  def test_table_exists
60
77
  assert !NonExistentTable.table_exists?
@@ -164,8 +181,25 @@ class BasicsTest < Test::Unit::TestCase
164
181
  topic.reload
165
182
  assert_equal("null", topic.title)
166
183
  assert_equal("null", topic.author_name)
167
- end
168
-
184
+ end
185
+
186
+ def test_save_nil_string_attributes
187
+ topic = Topic.find(1)
188
+ topic.title = nil
189
+ topic.save!
190
+ topic.reload
191
+ assert_nil topic.title
192
+ end
193
+
194
+ def test_save_for_record_with_only_primary_key
195
+ minimalistic = Minimalistic.new
196
+ assert_nothing_raised { minimalistic.save }
197
+ end
198
+
199
+ def test_save_for_record_with_only_primary_key_that_is_provided
200
+ assert_nothing_raised { Minimalistic.create!(:id => 2) }
201
+ end
202
+
169
203
  def test_hashes_not_mangled
170
204
  new_topic = { :title => "New Topic" }
171
205
  new_topic_values = { :title => "AnotherTopic" }
@@ -222,6 +256,11 @@ class BasicsTest < Test::Unit::TestCase
222
256
  topicReloaded.send :write_attribute, 'does_not_exist', 'test'
223
257
  assert_nothing_raised { topicReloaded.save }
224
258
  end
259
+
260
+ def test_update_for_record_with_only_primary_key
261
+ minimalistic = minimalistics(:first)
262
+ assert_nothing_raised { minimalistic.save }
263
+ end
225
264
 
226
265
  def test_write_attribute
227
266
  topic = Topic.new
@@ -281,25 +320,59 @@ class BasicsTest < Test::Unit::TestCase
281
320
  assert topic.approved?, "approved should be true"
282
321
  # puts ""
283
322
  end
284
-
285
- def test_reader_generation
286
- Topic.find(:first).title
287
- Firm.find(:first).name
288
- Client.find(:first).name
289
- if ActiveRecord::Base.generate_read_methods
290
- assert_readers(Topic, %w(type replies_count))
291
- assert_readers(Firm, %w(type))
292
- assert_readers(Client, %w(type ruby_type rating?))
293
- else
294
- [Topic, Firm, Client].each {|klass| assert_equal klass.read_methods, {}}
323
+
324
+ def test_query_attribute_string
325
+ [nil, "", " "].each do |value|
326
+ assert_equal false, Topic.new(:author_name => value).author_name?
327
+ end
328
+
329
+ assert_equal true, Topic.new(:author_name => "Name").author_name?
330
+ end
331
+
332
+ def test_query_attribute_number
333
+ [nil, 0, "0"].each do |value|
334
+ assert_equal false, Developer.new(:salary => value).salary?
295
335
  end
336
+
337
+ assert_equal true, Developer.new(:salary => 1).salary?
338
+ assert_equal true, Developer.new(:salary => "1").salary?
296
339
  end
340
+
341
+ def test_query_attribute_boolean
342
+ [nil, "", false, "false", "f", 0].each do |value|
343
+ assert_equal false, Topic.new(:approved => value).approved?
344
+ end
345
+
346
+ [true, "true", "1", 1].each do |value|
347
+ assert_equal true, Topic.new(:approved => value).approved?
348
+ end
349
+ end
350
+
351
+ def test_query_attribute_with_custom_fields
352
+ object = Company.find_by_sql(<<-SQL).first
353
+ SELECT c1.*, c2.ruby_type as string_value, c2.rating as int_value
354
+ FROM companies c1, companies c2
355
+ WHERE c1.firm_id = c2.id
356
+ AND c1.id = 2
357
+ SQL
358
+
359
+ assert_equal "Firm", object.string_value
360
+ assert object.string_value?
361
+
362
+ object.string_value = " "
363
+ assert !object.string_value?
364
+
365
+ assert_equal 1, object.int_value.to_i
366
+ assert object.int_value?
367
+
368
+ object.int_value = "0"
369
+ assert !object.int_value?
370
+ end
371
+
297
372
 
298
373
  def test_reader_for_invalid_column_names
299
- # column names which aren't legal ruby ids
300
- topic = Topic.find(:first)
301
- topic.send(:define_read_method, "mumub-jumbo".to_sym, "mumub-jumbo", nil)
302
- assert !Topic.read_methods.include?("mumub-jumbo")
374
+ Topic.send(:define_read_method, "mumub-jumbo".to_sym, "mumub-jumbo", nil)
375
+ assert !Topic.generated_methods.include?("mumub-jumbo")
303
376
  end
304
377
 
305
378
  def test_non_attribute_access_and_assignment
@@ -313,8 +386,9 @@ class BasicsTest < Test::Unit::TestCase
313
386
  # SQL Server doesn't have a separate column type just for dates, so all are returned as time
314
387
  return true if current_adapter?(:SQLServerAdapter)
315
388
 
316
- if current_adapter?(:SybaseAdapter)
389
+ if current_adapter?(:SybaseAdapter, :OracleAdapter)
317
390
  # Sybase ctlib does not (yet?) support the date type; use datetime instead.
391
+ # Oracle treats all dates/times as Time.
318
392
  assert_kind_of(
319
393
  Time, Topic.find(1).last_read,
320
394
  "The last_read attribute should be of the Time class"
@@ -345,6 +419,13 @@ class BasicsTest < Test::Unit::TestCase
345
419
  assert_equal 9900, Topic.find(2).written_on.usec
346
420
  end
347
421
  end
422
+
423
+ def test_custom_mutator
424
+ topic = Topic.find(1)
425
+ # This mutator is protected in the class definition
426
+ topic.send(:approved=, true)
427
+ assert topic.instance_variable_get("@custom_approved")
428
+ end
348
429
 
349
430
  def test_destroy
350
431
  topic = Topic.find(1)
@@ -486,17 +567,33 @@ class BasicsTest < Test::Unit::TestCase
486
567
  Topic.decrement_counter("replies_count", 2)
487
568
  assert_equal -2, Topic.find(2).replies_count
488
569
  end
489
-
490
- def test_update_all
491
- # The ADO library doesn't support the number of affected rows
492
- return true if current_adapter?(:SQLServerAdapter)
493
570
 
571
+ def test_update_all
494
572
  assert_equal 2, Topic.update_all("content = 'bulk updated!'")
495
573
  assert_equal "bulk updated!", Topic.find(1).content
496
574
  assert_equal "bulk updated!", Topic.find(2).content
575
+
497
576
  assert_equal 2, Topic.update_all(['content = ?', 'bulk updated again!'])
498
577
  assert_equal "bulk updated again!", Topic.find(1).content
499
578
  assert_equal "bulk updated again!", Topic.find(2).content
579
+
580
+ assert_equal 2, Topic.update_all(['content = ?', nil])
581
+ assert_nil Topic.find(1).content
582
+ end
583
+
584
+ def test_update_all_with_hash
585
+ assert_not_nil Topic.find(1).last_read
586
+ assert_equal 2, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
587
+ assert_equal "bulk updated with hash!", Topic.find(1).content
588
+ assert_equal "bulk updated with hash!", Topic.find(2).content
589
+ assert_nil Topic.find(1).last_read
590
+ assert_nil Topic.find(2).last_read
591
+ end
592
+
593
+ if current_adapter?(:MysqlAdapter)
594
+ def test_update_all_with_order_and_limit
595
+ assert_equal 1, Topic.update_all("content = 'bulk updated!'", nil, :limit => 1, :order => 'id DESC')
596
+ end
500
597
  end
501
598
 
502
599
  def test_update_many
@@ -509,9 +606,6 @@ class BasicsTest < Test::Unit::TestCase
509
606
  end
510
607
 
511
608
  def test_delete_all
512
- # The ADO library doesn't support the number of affected rows
513
- return true if current_adapter?(:SQLServerAdapter)
514
-
515
609
  assert_equal 2, Topic.delete_all
516
610
  end
517
611
 
@@ -695,11 +789,27 @@ class BasicsTest < Test::Unit::TestCase
695
789
  assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") }
696
790
  end
697
791
 
792
+ def test_mass_assignment_should_raise_exception_if_accessible_and_protected_attribute_writers_are_both_used
793
+ topic = TopicWithProtectedContentAndAccessibleAuthorName.new
794
+ assert_raises(RuntimeError) { topic.attributes = { "author_name" => "me" } }
795
+ assert_raises(RuntimeError) { topic.attributes = { "content" => "stuff" } }
796
+ end
797
+
698
798
  def test_mass_assignment_protection
699
799
  firm = Firm.new
700
800
  firm.attributes = { "name" => "Next Angle", "rating" => 5 }
701
801
  assert_equal 1, firm.rating
702
802
  end
803
+
804
+ def test_mass_assignment_protection_against_class_attribute_writers
805
+ [:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
806
+ :default_timezone, :allow_concurrency, :schema_format, :verification_timeout, :lock_optimistically, :record_timestamps].each do |method|
807
+ assert Task.respond_to?(method)
808
+ assert Task.respond_to?("#{method}=")
809
+ assert Task.new.respond_to?(method)
810
+ assert !Task.new.respond_to?("#{method}=")
811
+ end
812
+ end
703
813
 
704
814
  def test_customized_primary_key_remains_protected
705
815
  subscriber = Subscriber.new(:nick => 'webster123', :name => 'nice try')
@@ -709,7 +819,7 @@ class BasicsTest < Test::Unit::TestCase
709
819
  assert_nil keyboard.id
710
820
  end
711
821
 
712
- def test_customized_primary_key_remains_protected_when_refered_to_as_id
822
+ def test_customized_primary_key_remains_protected_when_referred_to_as_id
713
823
  subscriber = Subscriber.new(:id => 'webster123', :name => 'nice try')
714
824
  assert_nil subscriber.id
715
825
 
@@ -738,16 +848,32 @@ class BasicsTest < Test::Unit::TestCase
738
848
 
739
849
  def test_mass_assignment_protection_inheritance
740
850
  assert_nil LoosePerson.accessible_attributes
741
- assert_equal [ :credit_rating, :administrator ], LoosePerson.protected_attributes
851
+ assert_equal Set.new([ 'credit_rating', 'administrator' ]), LoosePerson.protected_attributes
742
852
 
743
853
  assert_nil LooseDescendant.accessible_attributes
744
- assert_equal [ :credit_rating, :administrator, :phone_number ], LooseDescendant.protected_attributes
854
+ assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number' ]), LooseDescendant.protected_attributes
855
+
856
+ assert_nil LooseDescendantSecond.accessible_attributes
857
+ assert_equal Set.new([ 'credit_rating', 'administrator', 'phone_number', 'name' ]), LooseDescendantSecond.protected_attributes, 'Running attr_protected twice in one class should merge the protections'
745
858
 
746
859
  assert_nil TightPerson.protected_attributes
747
- assert_equal [ :name, :address ], TightPerson.accessible_attributes
860
+ assert_equal Set.new([ 'name', 'address' ]), TightPerson.accessible_attributes
748
861
 
749
862
  assert_nil TightDescendant.protected_attributes
750
- assert_equal [ :name, :address, :phone_number ], TightDescendant.accessible_attributes
863
+ assert_equal Set.new([ 'name', 'address', 'phone_number' ]), TightDescendant.accessible_attributes
864
+ end
865
+
866
+ def test_readonly_attributes
867
+ assert_equal Set.new([ 'title' ]), ReadonlyTitlePost.readonly_attributes
868
+
869
+ post = ReadonlyTitlePost.create(:title => "cannot change this", :body => "changeable")
870
+ post.reload
871
+ assert_equal "cannot change this", post.title
872
+
873
+ post.update_attributes(:title => "try to change", :body => "changed")
874
+ post.reload
875
+ assert_equal "cannot change this", post.title
876
+ assert_equal "changed", post.body
751
877
  end
752
878
 
753
879
  def test_multiparameter_attributes_on_date
@@ -867,6 +993,10 @@ class BasicsTest < Test::Unit::TestCase
867
993
  cloned_topic.title["a"] = "c"
868
994
  assert_equal "b", topic.title["a"]
869
995
 
996
+ #test if attributes set as part of after_initialize are cloned correctly
997
+ assert_equal topic.author_email_address, cloned_topic.author_email_address
998
+
999
+ # test if saved clone object differs from original
870
1000
  cloned_topic.save
871
1001
  assert !cloned_topic.new_record?
872
1002
  assert cloned_topic.id != topic.id
@@ -1003,18 +1133,18 @@ class BasicsTest < Test::Unit::TestCase
1003
1133
  # As with migration_test.rb, we should make world_population >= 2**62
1004
1134
  # to cover 64-bit platforms and test it is a Bignum, but the main thing
1005
1135
  # is that it's an Integer.
1006
- unless current_adapter?(:IBM_DBAdapter)
1007
- assert_kind_of Integer, m1.world_population
1008
- else
1009
- assert_kind_of BigDecimal, m1.world_population
1010
- end
1136
+ unless current_adapter?(:IBM_DBAdapter)
1137
+ assert_kind_of Integer, m1.world_population
1138
+ else
1139
+ assert_kind_of BigDecimal, m1.world_population
1140
+ end
1011
1141
  assert_equal 6000000000, m1.world_population
1012
1142
 
1013
- unless current_adapter?(:IBM_DBAdapter)
1014
- assert_kind_of Fixnum, m1.my_house_population
1015
- else
1016
- assert_kind_of BigDecimal, m1.my_house_population
1017
- end
1143
+ unless current_adapter?(:IBM_DBAdapter)
1144
+ assert_kind_of Fixnum, m1.my_house_population
1145
+ else
1146
+ assert_kind_of BigDecimal, m1.my_house_population
1147
+ end
1018
1148
  assert_equal 3, m1.my_house_population
1019
1149
 
1020
1150
  assert_kind_of BigDecimal, m1.bank_balance
@@ -1076,16 +1206,29 @@ class BasicsTest < Test::Unit::TestCase
1076
1206
  assert_equal(myobj, topic.content)
1077
1207
  end
1078
1208
 
1079
- def test_serialized_attribute_with_class_constraint
1209
+ def test_nil_serialized_attribute_with_class_constraint
1080
1210
  myobj = MyObject.new('value1', 'value2')
1081
- topic = Topic.create("content" => myobj)
1082
- Topic.serialize(:content, Hash)
1211
+ topic = Topic.new
1212
+ assert_nil topic.content
1213
+ end
1083
1214
 
1215
+ def test_should_raise_exception_on_serialized_attribute_with_type_mismatch
1216
+ myobj = MyObject.new('value1', 'value2')
1217
+ topic = Topic.new(:content => myobj)
1218
+ assert topic.save
1219
+ Topic.serialize(:content, Hash)
1084
1220
  assert_raise(ActiveRecord::SerializationTypeMismatch) { Topic.find(topic.id).content }
1221
+ ensure
1222
+ Topic.serialize(:content)
1223
+ end
1085
1224
 
1225
+ def test_serialized_attribute_with_class_constraint
1086
1226
  settings = { "color" => "blue" }
1087
- Topic.find(topic.id).update_attribute("content", settings)
1227
+ Topic.serialize(:content, Hash)
1228
+ topic = Topic.new(:content => settings)
1229
+ assert topic.save
1088
1230
  assert_equal(settings, Topic.find(topic.id).content)
1231
+ ensure
1089
1232
  Topic.serialize(:content)
1090
1233
  end
1091
1234
 
@@ -1126,12 +1269,12 @@ class BasicsTest < Test::Unit::TestCase
1126
1269
  end
1127
1270
 
1128
1271
  def test_increment_attribute
1129
- assert_equal 1, topics(:first).replies_count
1130
- topics(:first).increment! :replies_count
1131
- assert_equal 2, topics(:first, :reload).replies_count
1132
-
1133
- topics(:first).increment(:replies_count).increment!(:replies_count)
1134
- assert_equal 4, topics(:first, :reload).replies_count
1272
+ assert_equal 50, accounts(:signals37).credit_limit
1273
+ accounts(:signals37).increment! :credit_limit
1274
+ assert_equal 51, accounts(:signals37, :reload).credit_limit
1275
+
1276
+ accounts(:signals37).increment(:credit_limit).increment!(:credit_limit)
1277
+ assert_equal 53, accounts(:signals37, :reload).credit_limit
1135
1278
  end
1136
1279
 
1137
1280
  def test_increment_nil_attribute
@@ -1141,14 +1284,13 @@ class BasicsTest < Test::Unit::TestCase
1141
1284
  end
1142
1285
 
1143
1286
  def test_decrement_attribute
1144
- topics(:first).increment(:replies_count).increment!(:replies_count)
1145
- assert_equal 3, topics(:first).replies_count
1146
-
1147
- topics(:first).decrement!(:replies_count)
1148
- assert_equal 2, topics(:first, :reload).replies_count
1287
+ assert_equal 50, accounts(:signals37).credit_limit
1149
1288
 
1150
- topics(:first).decrement(:replies_count).decrement!(:replies_count)
1151
- assert_equal 0, topics(:first, :reload).replies_count
1289
+ accounts(:signals37).decrement!(:credit_limit)
1290
+ assert_equal 49, accounts(:signals37, :reload).credit_limit
1291
+
1292
+ accounts(:signals37).decrement(:credit_limit).decrement!(:credit_limit)
1293
+ assert_equal 47, accounts(:signals37, :reload).credit_limit
1152
1294
  end
1153
1295
 
1154
1296
  def test_toggle_attribute
@@ -1227,11 +1369,8 @@ class BasicsTest < Test::Unit::TestCase
1227
1369
 
1228
1370
  def test_count_with_join
1229
1371
  res = Post.count_by_sql "SELECT COUNT(*) FROM posts LEFT JOIN comments ON posts.id=comments.post_id WHERE posts.#{QUOTED_TYPE} = 'Post'"
1230
- res2 = nil
1231
- assert_deprecated 'count' do
1232
- res2 = Post.count("posts.#{QUOTED_TYPE} = 'Post'",
1233
- "LEFT JOIN comments ON posts.id=comments.post_id")
1234
- end
1372
+
1373
+ res2 = Post.count(:conditions => "posts.#{QUOTED_TYPE} = 'Post'", :joins => "LEFT JOIN comments ON posts.id=comments.post_id")
1235
1374
  assert_equal res, res2
1236
1375
 
1237
1376
  res3 = nil
@@ -1251,15 +1390,17 @@ class BasicsTest < Test::Unit::TestCase
1251
1390
 
1252
1391
  assert_equal res4, res5
1253
1392
 
1254
- res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1255
- res7 = nil
1256
- assert_nothing_raised do
1257
- res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
1258
- :joins => "p, comments co",
1259
- :select => "p.id",
1260
- :distinct => true)
1393
+ unless current_adapter?(:SQLite2Adapter, :DeprecatedSQLiteAdapter)
1394
+ res6 = Post.count_by_sql "SELECT COUNT(DISTINCT p.id) FROM posts p, comments co WHERE p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id"
1395
+ res7 = nil
1396
+ assert_nothing_raised do
1397
+ res7 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
1398
+ :joins => "p, comments co",
1399
+ :select => "p.id",
1400
+ :distinct => true)
1401
+ end
1402
+ assert_equal res6, res7
1261
1403
  end
1262
- assert_equal res6, res7
1263
1404
  end
1264
1405
 
1265
1406
  def test_clear_association_cache_stored
@@ -1276,12 +1417,12 @@ class BasicsTest < Test::Unit::TestCase
1276
1417
  client_new = Client.new
1277
1418
  client_new.name = "The Joneses"
1278
1419
  clients = [ client_stored, client_new ]
1279
-
1420
+
1280
1421
  firm.clients << clients
1422
+ assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
1281
1423
 
1282
1424
  firm.clear_association_cache
1283
-
1284
- assert_equal firm.clients.collect{ |x| x.name }.sort, clients.collect{ |x| x.name }.sort
1425
+ assert_equal clients.map(&:name).to_set, firm.clients.map(&:name).to_set
1285
1426
  end
1286
1427
 
1287
1428
  def test_interpolate_sql
@@ -1401,15 +1542,14 @@ class BasicsTest < Test::Unit::TestCase
1401
1542
 
1402
1543
  def test_find_on_abstract_base_class_doesnt_use_type_condition
1403
1544
  old_class = LooseDescendant
1404
-
1405
1545
  Object.send :remove_const, :LooseDescendant
1406
- descendant = old_class.create!
1407
1546
 
1547
+ descendant = old_class.create!
1408
1548
  assert_not_nil LoosePerson.find(descendant.id), "Should have found instance of LooseDescendant when finding abstract LoosePerson: #{descendant.inspect}"
1409
- ensure
1410
- unless Object.const_defined?(:LooseDescendant)
1411
- Object.const_set :LooseDescendant, old_class
1412
- end
1549
+ ensure
1550
+ unless Object.const_defined?(:LooseDescendant)
1551
+ Object.const_set :LooseDescendant, old_class
1552
+ end
1413
1553
  end
1414
1554
 
1415
1555
  def test_assert_queries
@@ -1420,30 +1560,52 @@ class BasicsTest < Test::Unit::TestCase
1420
1560
  end
1421
1561
 
1422
1562
  def test_to_xml
1423
- xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true)
1563
+ xml = REXML::Document.new(topics(:first).to_xml(:indent => 0))
1424
1564
  bonus_time_in_current_timezone = topics(:first).bonus_time.xmlschema
1425
1565
  written_on_in_current_timezone = topics(:first).written_on.xmlschema
1426
1566
  last_read_in_current_timezone = topics(:first).last_read.xmlschema
1427
- assert_equal "<topic>", xml.first(7)
1428
- assert xml.include?(%(<title>The First Topic</title>))
1429
- assert xml.include?(%(<author-name>David</author-name>))
1430
- assert xml.include?(%(<id type="integer">1</id>))
1431
- assert xml.include?(%(<replies-count type="integer">1</replies-count>))
1432
- unless current_adapter?(:IBM_DBAdapter)
1433
- assert xml.include?(%(<written-on type="datetime">#{written_on_in_current_timezone}</written-on>))
1434
- end
1435
- assert xml.include?(%(<content>Have a nice day</content>))
1436
- assert xml.include?(%(<author-email-address>david@loudthinking.com</author-email-address>))
1437
- assert xml.match(%(<parent-id type="integer"></parent-id>))
1567
+
1568
+ assert_equal "topic", xml.root.name
1569
+ assert_equal "The First Topic" , xml.elements["//title"].text
1570
+ assert_equal "David" , xml.elements["//author-name"].text
1571
+
1572
+ assert_equal "1", xml.elements["//id"].text
1573
+ unless ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')
1574
+ assert_equal "integer" , xml.elements["//id"].attributes['type']
1575
+ else
1576
+ assert_equal "serial" , xml.elements["//id"].attributes['type']
1577
+ end
1578
+
1579
+ assert_equal "1", xml.elements["//replies-count"].text
1580
+ assert_equal "integer" , xml.elements["//replies-count"].attributes['type']
1581
+
1582
+ assert_equal written_on_in_current_timezone, xml.elements["//written-on"].text
1583
+ assert_equal "datetime" , xml.elements["//written-on"].attributes['type']
1584
+
1585
+ assert_equal "--- Have a nice day\n" , xml.elements["//content"].text
1586
+ assert_equal "yaml" , xml.elements["//content"].attributes['type']
1587
+
1588
+ assert_equal "david@loudthinking.com", xml.elements["//author-email-address"].text
1589
+
1590
+ assert_equal nil, xml.elements["//parent-id"].text
1591
+ assert_equal "integer", xml.elements["//parent-id"].attributes['type']
1592
+ assert_equal "true", xml.elements["//parent-id"].attributes['nil']
1593
+
1438
1594
  if current_adapter?(:SybaseAdapter, :SQLServerAdapter, :OracleAdapter)
1439
- assert xml.include?(%(<last-read type="datetime">#{last_read_in_current_timezone}</last-read>))
1595
+ assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
1596
+ assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
1440
1597
  else
1441
- assert xml.include?(%(<last-read type="date">2004-04-15</last-read>))
1598
+ assert_equal "2004-04-15", xml.elements["//last-read"].text
1599
+ assert_equal "date" , xml.elements["//last-read"].attributes['type']
1442
1600
  end
1601
+
1443
1602
  # Oracle and DB2 don't have true boolean or time-only fields
1444
- unless current_adapter?(:OracleAdapter, :DB2Adapter, :IBM_DBAdapter)
1445
- assert xml.include?(%(<approved type="boolean">false</approved>)), "Approved should be a boolean"
1446
- assert xml.include?(%(<bonus-time type="datetime">#{bonus_time_in_current_timezone}</bonus-time>))
1603
+ unless current_adapter?(:OracleAdapter, :DB2Adapter)
1604
+ assert_equal "false", xml.elements["//approved"].text
1605
+ assert_equal "boolean" , xml.elements["//approved"].attributes['type']
1606
+
1607
+ assert_equal bonus_time_in_current_timezone, xml.elements["//bonus-time"].text
1608
+ assert_equal "datetime" , xml.elements["//bonus-time"].attributes['type']
1447
1609
  end
1448
1610
  end
1449
1611
 
@@ -1461,13 +1623,13 @@ class BasicsTest < Test::Unit::TestCase
1461
1623
  def test_to_xml_including_has_many_association
1462
1624
  xml = topics(:first).to_xml(:indent => 0, :skip_instruct => true, :include => :replies, :except => :replies_count)
1463
1625
  assert_equal "<topic>", xml.first(7)
1464
- assert xml.include?(%(<replies><reply>))
1626
+ assert xml.include?(%(<replies type="array"><reply>))
1465
1627
  assert xml.include?(%(<title>The Second Topic's of the day</title>))
1466
1628
  end
1467
1629
 
1468
1630
  def test_array_to_xml_including_has_many_association
1469
1631
  xml = [ topics(:first), topics(:second) ].to_xml(:indent => 0, :skip_instruct => true, :include => :replies)
1470
- assert xml.include?(%(<replies><reply>))
1632
+ assert xml.include?(%(<replies type="array"><reply>))
1471
1633
  end
1472
1634
 
1473
1635
  def test_array_to_xml_including_methods
@@ -1501,7 +1663,7 @@ class BasicsTest < Test::Unit::TestCase
1501
1663
  xml = companies(:first_firm).to_xml(:indent => 0, :skip_instruct => true, :include => [ :clients, :account ])
1502
1664
  assert_equal "<firm>", xml.first(6)
1503
1665
  assert xml.include?(%(<account>))
1504
- assert xml.include?(%(<clients><client>))
1666
+ assert xml.include?(%(<clients type="array"><client>))
1505
1667
  end
1506
1668
 
1507
1669
  def test_to_xml_including_multiple_associations_with_options
@@ -1512,7 +1674,7 @@ class BasicsTest < Test::Unit::TestCase
1512
1674
 
1513
1675
  assert_equal "<firm>", xml.first(6)
1514
1676
  assert xml.include?(%(<client><name>Summit</name></client>))
1515
- assert xml.include?(%(<clients><client>))
1677
+ assert xml.include?(%(<clients type="array"><client>))
1516
1678
  end
1517
1679
 
1518
1680
  def test_to_xml_including_methods
@@ -1521,6 +1683,15 @@ class BasicsTest < Test::Unit::TestCase
1521
1683
  assert xml.include?(%(<arbitrary-method>I am Jack's profound disappointment</arbitrary-method>))
1522
1684
  end
1523
1685
 
1686
+ def test_to_xml_with_block
1687
+ value = "Rockin' the block"
1688
+ xml = Company.new.to_xml(:skip_instruct => true) do |xml|
1689
+ xml.tag! "arbitrary-element", value
1690
+ end
1691
+ assert_equal "<company>", xml.first(9)
1692
+ assert xml.include?(%(<arbitrary-element>#{value}</arbitrary-element>))
1693
+ end
1694
+
1524
1695
  def test_except_attributes
1525
1696
  assert_equal(
1526
1697
  %w( author_name type id approved replies_count bonus_time written_on content author_email_address parent_id last_read),
@@ -1546,34 +1717,45 @@ class BasicsTest < Test::Unit::TestCase
1546
1717
  def test_to_param_should_return_string
1547
1718
  assert_kind_of String, Client.find(:first).to_param
1548
1719
  end
1720
+
1721
+ def test_inspect_class
1722
+ assert_equal 'ActiveRecord::Base', ActiveRecord::Base.inspect
1723
+ assert_equal 'LoosePerson(abstract)', LoosePerson.inspect
1724
+ unless ActiveRecord::Base.connection.servertype.class.name.include?('::IBM_IDS')
1725
+ assert_match(/^Topic\(id: integer, title: string/, Topic.inspect)
1726
+ else
1727
+ assert_match(/^Topic\(id: serial, title: string/, Topic.inspect)
1728
+ end
1729
+ end
1730
+
1731
+ def test_inspect_instance
1732
+ topic = topics(:first)
1733
+ assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, type: nil>), topic.inspect
1734
+ end
1735
+
1736
+ def test_inspect_new_instance
1737
+ assert_match /Topic id: nil/, Topic.new.inspect
1738
+ end
1549
1739
 
1550
- # FIXME: this test ought to run, but it needs to run sandboxed so that it
1551
- # doesn't b0rk the current test environment by undefing everything.
1552
- #
1553
- #def test_dev_mode_memory_leak
1554
- # counts = []
1555
- # 2.times do
1556
- # require_dependency 'fixtures/company'
1557
- # Firm.find(:first)
1558
- # Dependencies.clear
1559
- # ActiveRecord::Base.reset_subclasses
1560
- # Dependencies.remove_subclasses_for(ActiveRecord::Base)
1561
- #
1562
- # GC.start
1563
- #
1564
- # count = 0
1565
- # ObjectSpace.each_object(Proc) { count += 1 }
1566
- # counts << count
1567
- # end
1568
- # assert counts.last <= counts.first,
1569
- # "expected last count (#{counts.last}) to be <= first count (#{counts.first})"
1570
- #end
1740
+ def test_inspect_limited_select_instance
1741
+ assert_equal %(#<Topic id: 1>), Topic.find(:first, :select => 'id', :conditions => 'id = 1').inspect
1742
+ assert_equal %(#<Topic id: 1, title: "The First Topic">), Topic.find(:first, :select => 'id, title', :conditions => 'id = 1').inspect
1743
+ end
1571
1744
 
1572
- private
1573
- def assert_readers(model, exceptions)
1574
- expected_readers = Set.new(model.column_names - ['id'])
1575
- expected_readers += expected_readers.map { |col| "#{col}?" }
1576
- expected_readers -= exceptions
1577
- assert_equal expected_readers, model.read_methods
1578
- end
1745
+ def test_inspect_class_without_table
1746
+ assert_equal "NonExistentTable(Table doesn't exist)", NonExistentTable.inspect
1747
+ end
1748
+
1749
+ def test_attribute_for_inspect
1750
+ t = topics(:first)
1751
+ t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
1752
+
1753
+ assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
1754
+ assert_equal '"The First Topic Now Has A Title With\nNewlines And M..."', t.attribute_for_inspect(:title)
1755
+ end
1756
+
1757
+ def test_becomes
1758
+ assert_kind_of Reply, topics(:first).becomes(Reply)
1759
+ assert_equal "The First Topic", topics(:first).becomes(Reply).title
1760
+ end
1579
1761
  end