activerecord 2.3.3 → 2.3.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (70) hide show
  1. data/CHANGELOG +8 -1
  2. data/Rakefile +32 -15
  3. data/examples/performance.rb +162 -0
  4. data/lib/active_record/associations.rb +37 -5
  5. data/lib/active_record/associations/association_collection.rb +1 -0
  6. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +16 -0
  7. data/lib/active_record/associations/has_many_association.rb +1 -0
  8. data/lib/active_record/associations/has_many_through_association.rb +13 -3
  9. data/lib/active_record/associations/has_one_through_association.rb +8 -2
  10. data/lib/active_record/autosave_association.rb +4 -3
  11. data/lib/active_record/base.rb +18 -10
  12. data/lib/active_record/calculations.rb +2 -0
  13. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +16 -2
  14. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +2 -2
  15. data/lib/active_record/connection_adapters/abstract_adapter.rb +7 -0
  16. data/lib/active_record/connection_adapters/mysql_adapter.rb +17 -8
  17. data/lib/active_record/connection_adapters/postgresql_adapter.rb +32 -13
  18. data/lib/active_record/connection_adapters/sqlite_adapter.rb +12 -0
  19. data/lib/active_record/dirty.rb +1 -1
  20. data/lib/active_record/fixtures.rb +9 -7
  21. data/lib/active_record/i18n_interpolation_deprecation.rb +1 -1
  22. data/lib/active_record/locale/en.yml +4 -0
  23. data/lib/active_record/named_scope.rb +1 -6
  24. data/lib/active_record/reflection.rb +1 -1
  25. data/lib/active_record/schema_dumper.rb +1 -2
  26. data/lib/active_record/serializers/json_serializer.rb +5 -3
  27. data/lib/active_record/serializers/xml_serializer.rb +6 -2
  28. data/lib/active_record/validations.rb +148 -79
  29. data/lib/active_record/version.rb +1 -1
  30. data/test/cases/adapter_test.rb +12 -0
  31. data/test/cases/associations/belongs_to_associations_test.rb +0 -18
  32. data/test/cases/associations/eager_load_nested_include_test.rb +5 -5
  33. data/test/cases/associations/habtm_join_table_test.rb +56 -0
  34. data/test/cases/associations/has_many_associations_test.rb +56 -2
  35. data/test/cases/associations/has_many_through_associations_test.rb +46 -1
  36. data/test/cases/associations/has_one_through_associations_test.rb +10 -0
  37. data/test/cases/associations/join_model_test.rb +4 -4
  38. data/test/cases/base_test.rb +49 -4
  39. data/test/cases/calculations_test.rb +6 -0
  40. data/test/cases/column_definition_test.rb +34 -0
  41. data/test/cases/dirty_test.rb +10 -0
  42. data/test/cases/finder_test.rb +15 -50
  43. data/test/cases/fixtures_test.rb +1 -1
  44. data/test/cases/i18n_test.rb +5 -0
  45. data/test/cases/method_scoping_test.rb +1 -1
  46. data/test/cases/migration_test.rb +39 -11
  47. data/test/cases/modules_test.rb +42 -0
  48. data/test/cases/named_scope_test.rb +6 -4
  49. data/test/cases/pk_test.rb +18 -0
  50. data/test/cases/reflection_test.rb +2 -2
  51. data/test/cases/schema_dumper_test.rb +19 -1
  52. data/test/cases/validations_i18n_test.rb +656 -624
  53. data/test/cases/validations_test.rb +12 -2
  54. data/test/cases/xml_serialization_test.rb +20 -0
  55. data/test/fixtures/fixture_database.sqlite +0 -0
  56. data/test/fixtures/fixture_database.sqlite3 +0 -0
  57. data/test/fixtures/fixture_database_2.sqlite +0 -0
  58. data/test/fixtures/fixture_database_2.sqlite3 +0 -0
  59. data/test/fixtures/posts.yml +3 -0
  60. data/test/models/author.rb +1 -0
  61. data/test/models/comment.rb +5 -1
  62. data/test/models/company.rb +2 -0
  63. data/test/models/company_in_module.rb +1 -1
  64. data/test/models/contract.rb +5 -0
  65. data/test/models/organization.rb +2 -0
  66. data/test/models/topic.rb +0 -2
  67. data/test/schema/postgresql_specific_schema.rb +13 -2
  68. data/test/schema/schema.rb +4 -0
  69. metadata +12 -54
  70. data/test/debug.log +0 -415
@@ -33,4 +33,38 @@ class ColumnDefinitionTest < ActiveRecord::TestCase
33
33
  column.limit, column.precision, column.scale, column.default, column.null)
34
34
  assert_equal %Q{title varchar(20) DEFAULT 'Hello' NOT NULL}, column_def.to_sql
35
35
  end
36
+
37
+ if current_adapter?(:MysqlAdapter)
38
+ def test_should_set_default_for_mysql_binary_data_types
39
+ binary_column = ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", "a", "binary(1)")
40
+ assert_equal "a", binary_column.default
41
+
42
+ varbinary_column = ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", "a", "varbinary(1)")
43
+ assert_equal "a", varbinary_column.default
44
+ end
45
+
46
+ def test_should_not_set_default_for_blob_and_text_data_types
47
+ assert_raise ArgumentError do
48
+ ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", "a", "blob")
49
+ end
50
+
51
+ assert_raise ArgumentError do
52
+ ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", "Hello", "text")
53
+ end
54
+
55
+ text_column = ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", nil, "text")
56
+ assert_equal nil, text_column.default
57
+
58
+ not_null_text_column = ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", nil, "text", false)
59
+ assert_equal "", not_null_text_column.default
60
+ end
61
+
62
+ def test_has_default_should_return_false_for_blog_and_test_data_types
63
+ blob_column = ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", nil, "blob")
64
+ assert !blob_column.has_default?
65
+
66
+ text_column = ActiveRecord::ConnectionAdapters::MysqlColumn.new("title", nil, "text")
67
+ assert !text_column.has_default?
68
+ end
69
+ end
36
70
  end
@@ -288,6 +288,16 @@ class DirtyTest < ActiveRecord::TestCase
288
288
  end
289
289
  end
290
290
 
291
+ def test_save_should_not_save_serialized_attribute_with_partial_updates_if_not_present
292
+ with_partial_updates(Topic) do
293
+ Topic.create!(:author_name => 'Bill', :content => {:a => "a"})
294
+ topic = Topic.first(:select => 'id, author_name')
295
+ topic.update_attribute :author_name, 'John'
296
+ topic = Topic.first
297
+ assert_not_nil topic.content
298
+ end
299
+ end
300
+
291
301
  private
292
302
  def with_partial_updates(klass, on = true)
293
303
  old = klass.partial_updates?
@@ -1,4 +1,5 @@
1
1
  require "cases/helper"
2
+ require 'models/post'
2
3
  require 'models/author'
3
4
  require 'models/categorization'
4
5
  require 'models/comment'
@@ -7,7 +8,6 @@ require 'models/topic'
7
8
  require 'models/reply'
8
9
  require 'models/entrant'
9
10
  require 'models/developer'
10
- require 'models/post'
11
11
  require 'models/customer'
12
12
  require 'models/job'
13
13
  require 'models/categorization'
@@ -94,16 +94,16 @@ class FinderTest < ActiveRecord::TestCase
94
94
 
95
95
  assert_raise(NoMethodError) { Topic.exists?([1,2]) }
96
96
  end
97
-
97
+
98
98
  def test_exists_returns_true_with_one_record_and_no_args
99
99
  assert Topic.exists?
100
100
  end
101
-
101
+
102
102
  def test_does_not_exist_with_empty_table_and_no_args_given
103
103
  Topic.delete_all
104
104
  assert !Topic.exists?
105
105
  end
106
-
106
+
107
107
  def test_exists_with_aggregate_having_three_mappings
108
108
  existing_address = customers(:david).address
109
109
  assert Customer.exists?(:address => existing_address)
@@ -156,10 +156,8 @@ class FinderTest < ActiveRecord::TestCase
156
156
  end
157
157
 
158
158
  def test_find_all_with_limit
159
- entrants = Entrant.find(:all, :order => "id ASC", :limit => 2)
160
-
161
- assert_equal(2, entrants.size)
162
- assert_equal(entrants(:first).name, entrants.first.name)
159
+ assert_equal(2, Entrant.find(:all, :limit => 2).size)
160
+ assert_equal(0, Entrant.find(:all, :limit => 0).size)
163
161
  end
164
162
 
165
163
  def test_find_all_with_prepared_limit_and_offset
@@ -168,22 +166,23 @@ class FinderTest < ActiveRecord::TestCase
168
166
  assert_equal(2, entrants.size)
169
167
  assert_equal(entrants(:second).name, entrants.first.name)
170
168
 
169
+ assert_equal 3, Entrant.count
171
170
  entrants = Entrant.find(:all, :order => "id ASC", :limit => 2, :offset => 2)
172
171
  assert_equal(1, entrants.size)
173
172
  assert_equal(entrants(:third).name, entrants.first.name)
174
173
  end
175
174
 
176
- def test_find_all_with_limit_and_offset_and_multiple_orderings
177
- developers = Developer.find(:all, :order => "salary ASC, id DESC", :limit => 3, :offset => 1)
178
- assert_equal ["David", "fixture_10", "fixture_9"], developers.collect {|d| d.name}
179
- end
175
+ def test_find_all_with_limit_and_offset_and_multiple_order_clauses
176
+ first_three_posts = Post.find :all, :order => 'author_id, id', :limit => 3, :offset => 0
177
+ second_three_posts = Post.find :all, :order => ' author_id,id ', :limit => 3, :offset => 3
178
+ last_posts = Post.find :all, :order => ' author_id, id ', :limit => 3, :offset => 6
180
179
 
181
- def test_find_with_limit_and_condition
182
- developers = Developer.find(:all, :order => "id DESC", :conditions => "salary = 100000", :limit => 3, :offset =>7)
183
- assert_equal(1, developers.size)
184
- assert_equal("fixture_3", developers.first.name)
180
+ assert_equal [[0,3],[1,1],[1,2]], first_three_posts.map { |p| [p.author_id, p.id] }
181
+ assert_equal [[1,4],[1,5],[1,6]], second_three_posts.map { |p| [p.author_id, p.id] }
182
+ assert_equal [[2,7]], last_posts.map { |p| [p.author_id, p.id] }
185
183
  end
186
184
 
185
+
187
186
  def test_find_with_group
188
187
  developers = Developer.find(:all, :group => "salary", :select => "salary")
189
188
  assert_equal 4, developers.size
@@ -941,40 +940,6 @@ class FinderTest < ActiveRecord::TestCase
941
940
  assert_raise(ArgumentError) { Topic.find_by_title 'No Title', :join => "It should be `joins'" }
942
941
  end
943
942
 
944
- def test_find_all_with_limit
945
- first_five_developers = Developer.find :all, :order => 'id ASC', :limit => 5
946
- assert_equal 5, first_five_developers.length
947
- assert_equal 'David', first_five_developers.first.name
948
- assert_equal 'fixture_5', first_five_developers.last.name
949
-
950
- no_developers = Developer.find :all, :order => 'id ASC', :limit => 0
951
- assert_equal 0, no_developers.length
952
- end
953
-
954
- def test_find_all_with_limit_and_offset
955
- first_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 0
956
- second_three_developers = Developer.find :all, :order => 'id ASC', :limit => 3, :offset => 3
957
- last_two_developers = Developer.find :all, :order => 'id ASC', :limit => 2, :offset => 8
958
-
959
- assert_equal 3, first_three_developers.length
960
- assert_equal 3, second_three_developers.length
961
- assert_equal 2, last_two_developers.length
962
-
963
- assert_equal 'David', first_three_developers.first.name
964
- assert_equal 'fixture_4', second_three_developers.first.name
965
- assert_equal 'fixture_9', last_two_developers.first.name
966
- end
967
-
968
- def test_find_all_with_limit_and_offset_and_multiple_order_clauses
969
- first_three_posts = Post.find :all, :order => 'author_id, id', :limit => 3, :offset => 0
970
- second_three_posts = Post.find :all, :order => ' author_id,id ', :limit => 3, :offset => 3
971
- last_posts = Post.find :all, :order => ' author_id, id ', :limit => 3, :offset => 6
972
-
973
- assert_equal [[0,3],[1,1],[1,2]], first_three_posts.map { |p| [p.author_id, p.id] }
974
- assert_equal [[1,4],[1,5],[1,6]], second_three_posts.map { |p| [p.author_id, p.id] }
975
- assert_equal [[2,7]], last_posts.map { |p| [p.author_id, p.id] }
976
- end
977
-
978
943
  def test_find_all_with_join
979
944
  developers_on_project_one = Developer.find(
980
945
  :all,
@@ -185,7 +185,7 @@ class FixturesTest < ActiveRecord::TestCase
185
185
 
186
186
  def test_binary_in_fixtures
187
187
  assert_equal 1, @binaries.size
188
- data = File.read(ASSETS_ROOT + "/flowers.jpg")
188
+ data = File.open(ASSETS_ROOT + "/flowers.jpg", 'rb') { |f| f.read }
189
189
  data.force_encoding('ASCII-8BIT') if data.respond_to?(:force_encoding)
190
190
  data.freeze
191
191
  assert_equal data, @flowers.data
@@ -12,6 +12,11 @@ class ActiveRecordI18nTests < Test::Unit::TestCase
12
12
  I18n.backend.store_translations 'en', :activerecord => {:attributes => {:topic => {:title => 'topic title attribute'} } }
13
13
  assert_equal 'topic title attribute', Topic.human_attribute_name('title')
14
14
  end
15
+
16
+ def test_translated_model_attributes_with_symbols
17
+ I18n.backend.store_translations 'en', :activerecord => {:attributes => {:topic => {:title => 'topic title attribute'} } }
18
+ assert_equal 'topic title attribute', Topic.human_attribute_name(:title)
19
+ end
15
20
 
16
21
  def test_translated_model_attributes_with_sti
17
22
  I18n.backend.store_translations 'en', :activerecord => {:attributes => {:reply => {:title => 'reply title attribute'} } }
@@ -1,9 +1,9 @@
1
1
  require "cases/helper"
2
+ require 'models/post'
2
3
  require 'models/author'
3
4
  require 'models/developer'
4
5
  require 'models/project'
5
6
  require 'models/comment'
6
- require 'models/post'
7
7
  require 'models/category'
8
8
 
9
9
  class MethodScopingTest < ActiveRecord::TestCase
@@ -25,6 +25,24 @@ if ActiveRecord::Base.connection.supports_migrations?
25
25
  end
26
26
  end
27
27
 
28
+ class MigrationTableAndIndexTest < ActiveRecord::TestCase
29
+ def test_add_schema_info_respects_prefix_and_suffix
30
+ conn = ActiveRecord::Base.connection
31
+
32
+ conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
33
+ ActiveRecord::Base.table_name_prefix = 'foo_'
34
+ ActiveRecord::Base.table_name_suffix = '_bar'
35
+ conn.drop_table(ActiveRecord::Migrator.schema_migrations_table_name) if conn.table_exists?(ActiveRecord::Migrator.schema_migrations_table_name)
36
+
37
+ conn.initialize_schema_migrations_table
38
+
39
+ assert_equal "foo_unique_schema_migrations_bar", conn.indexes(ActiveRecord::Migrator.schema_migrations_table_name)[0][:name]
40
+ ensure
41
+ ActiveRecord::Base.table_name_prefix = ""
42
+ ActiveRecord::Base.table_name_suffix = ""
43
+ end
44
+ end
45
+
28
46
  class MigrationTest < ActiveRecord::TestCase
29
47
  self.use_transactional_fixtures = false
30
48
 
@@ -224,7 +242,7 @@ if ActiveRecord::Base.connection.supports_migrations?
224
242
  t.column :foo, :string
225
243
  end
226
244
 
227
- assert_equal %w(foo testings_id), Person.connection.columns(:testings).map { |c| c.name }.sort
245
+ assert_equal %w(foo testing_id), Person.connection.columns(:testings).map { |c| c.name }.sort
228
246
  ensure
229
247
  Person.connection.drop_table :testings rescue nil
230
248
  ActiveRecord::Base.primary_key_prefix_type = nil
@@ -237,7 +255,7 @@ if ActiveRecord::Base.connection.supports_migrations?
237
255
  t.column :foo, :string
238
256
  end
239
257
 
240
- assert_equal %w(foo testingsid), Person.connection.columns(:testings).map { |c| c.name }.sort
258
+ assert_equal %w(foo testingid), Person.connection.columns(:testings).map { |c| c.name }.sort
241
259
  ensure
242
260
  Person.connection.drop_table :testings rescue nil
243
261
  ActiveRecord::Base.primary_key_prefix_type = nil
@@ -389,7 +407,7 @@ if ActiveRecord::Base.connection.supports_migrations?
389
407
  assert_equal 9, wealth_column.precision
390
408
  assert_equal 7, wealth_column.scale
391
409
  end
392
-
410
+
393
411
  def test_native_types
394
412
  Person.delete_all
395
413
  Person.connection.add_column "people", "last_name", :string
@@ -921,9 +939,9 @@ if ActiveRecord::Base.connection.supports_migrations?
921
939
 
922
940
  def test_migrator_one_down
923
941
  ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid")
924
-
942
+
925
943
  ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", 1)
926
-
944
+
927
945
  Person.reset_column_information
928
946
  assert Person.column_methods_hash.include?(:last_name)
929
947
  assert !Reminder.table_exists?
@@ -1059,20 +1077,20 @@ if ActiveRecord::Base.connection.supports_migrations?
1059
1077
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
1060
1078
  assert_equal "hello world", Reminder.find(:first).content
1061
1079
  end
1062
-
1080
+
1063
1081
  def test_migrator_rollback
1064
1082
  ActiveRecord::Migrator.migrate(MIGRATIONS_ROOT + "/valid")
1065
1083
  assert_equal(3, ActiveRecord::Migrator.current_version)
1066
-
1084
+
1067
1085
  ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1068
1086
  assert_equal(2, ActiveRecord::Migrator.current_version)
1069
-
1087
+
1070
1088
  ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1071
1089
  assert_equal(1, ActiveRecord::Migrator.current_version)
1072
-
1090
+
1073
1091
  ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1074
1092
  assert_equal(0, ActiveRecord::Migrator.current_version)
1075
-
1093
+
1076
1094
  ActiveRecord::Migrator.rollback(MIGRATIONS_ROOT + "/valid")
1077
1095
  assert_equal(0, ActiveRecord::Migrator.current_version)
1078
1096
  end
@@ -1224,7 +1242,7 @@ if ActiveRecord::Base.connection.supports_migrations?
1224
1242
  end
1225
1243
 
1226
1244
  end
1227
-
1245
+
1228
1246
  class SexyMigrationsTest < ActiveRecord::TestCase
1229
1247
  def test_references_column_type_adds_id
1230
1248
  with_new_table do |t|
@@ -1280,6 +1298,15 @@ if ActiveRecord::Base.connection.supports_migrations?
1280
1298
  end
1281
1299
  end
1282
1300
 
1301
+ if current_adapter?(:PostgreSQLAdapter)
1302
+ def test_xml_creates_xml_column
1303
+ with_new_table do |t|
1304
+ t.expects(:column).with(:data, 'xml', {})
1305
+ t.xml :data
1306
+ end
1307
+ end
1308
+ end
1309
+
1283
1310
  protected
1284
1311
  def with_new_table
1285
1312
  Person.connection.create_table :delete_me, :force => true do |t|
@@ -1493,3 +1520,4 @@ if ActiveRecord::Base.connection.supports_migrations?
1493
1520
  end
1494
1521
  end
1495
1522
  end
1523
+
@@ -4,6 +4,23 @@ require 'models/company_in_module'
4
4
  class ModulesTest < ActiveRecord::TestCase
5
5
  fixtures :accounts, :companies, :projects, :developers
6
6
 
7
+ def setup
8
+ # need to make sure Object::Firm and Object::Client are not defined,
9
+ # so that constantize will not be able to cheat when having to load namespaced classes
10
+ @undefined_consts = {}
11
+
12
+ [:Firm, :Client].each do |const|
13
+ @undefined_consts.merge! const => Object.send(:remove_const, const) if Object.const_defined?(const)
14
+ end
15
+ end
16
+
17
+ def teardown
18
+ # reinstate the constants that we undefined in the setup
19
+ @undefined_consts.each do |constant, value|
20
+ Object.send :const_set, constant, value unless value.nil?
21
+ end
22
+ end
23
+
7
24
  def test_module_spanning_associations
8
25
  firm = MyApplication::Business::Firm.find(:first)
9
26
  assert !firm.clients.empty?, "Firm should have clients"
@@ -36,4 +53,29 @@ class ModulesTest < ActiveRecord::TestCase
36
53
  assert_equal 'companies', MyApplication::Business::Client.table_name, 'table_name for ActiveRecord model subclass'
37
54
  assert_equal 'company_contacts', MyApplication::Business::Client::Contact.table_name, 'table_name for ActiveRecord model enclosed by another ActiveRecord model'
38
55
  end
56
+
57
+ def test_assign_ids
58
+ firm = MyApplication::Business::Firm.first
59
+
60
+ assert_nothing_raised NameError, "Should be able to resolve all class constants via reflection" do
61
+ firm.client_ids = [MyApplication::Business::Client.first.id]
62
+ end
63
+ end
64
+
65
+ # need to add an eager loading condition to force the eager loading model into
66
+ # the old join model, to test that. See http://dev.rubyonrails.org/ticket/9640
67
+ def test_eager_loading_in_modules
68
+ clients = []
69
+
70
+ assert_nothing_raised NameError, "Should be able to resolve all class constants via reflection" do
71
+ clients << MyApplication::Business::Client.find(3, :include => {:firm => :account}, :conditions => 'accounts.id IS NOT NULL')
72
+ clients << MyApplication::Business::Client.find(3, :include => {:firm => :account})
73
+ end
74
+
75
+ clients.each do |client|
76
+ assert_no_queries do
77
+ assert_not_nil(client.firm.account)
78
+ end
79
+ end
80
+ end
39
81
  end
@@ -319,10 +319,6 @@ class NamedScopeTest < ActiveRecord::TestCase
319
319
  assert_equal [posts(:sti_comments)], Post.with_special_comments.with_post(4).all.uniq
320
320
  end
321
321
 
322
- def test_methods_invoked_within_scopes_should_respect_scope
323
- assert_equal [], Topic.approved.by_rejected_ids.proxy_options[:conditions][:id]
324
- end
325
-
326
322
  def test_named_scopes_batch_finders
327
323
  assert_equal 3, Topic.approved.count
328
324
 
@@ -336,6 +332,12 @@ class NamedScopeTest < ActiveRecord::TestCase
336
332
  end
337
333
  end
338
334
  end
335
+
336
+ def test_table_names_for_chaining_scopes_with_and_without_table_name_included
337
+ assert_nothing_raised do
338
+ Comment.for_first_post.for_first_author.all
339
+ end
340
+ end
339
341
  end
340
342
 
341
343
  class DynamicScopeMatchTest < ActiveRecord::TestCase
@@ -98,4 +98,22 @@ class PrimaryKeysTest < ActiveRecord::TestCase
98
98
  def test_instance_destroy_should_quote_pkey
99
99
  assert_nothing_raised { MixedCaseMonkey.find(1).destroy }
100
100
  end
101
+
102
+ def test_supports_primary_key
103
+ assert_nothing_raised NoMethodError do
104
+ ActiveRecord::Base.connection.supports_primary_key?
105
+ end
106
+ end
107
+
108
+ def test_primary_key_returns_value_if_it_exists
109
+ if ActiveRecord::Base.connection.supports_primary_key?
110
+ assert_equal 'id', ActiveRecord::Base.connection.primary_key('developers')
111
+ end
112
+ end
113
+
114
+ def test_primary_key_returns_nil_if_it_does_not_exist
115
+ if ActiveRecord::Base.connection.supports_primary_key?
116
+ assert_nil ActiveRecord::Base.connection.primary_key('developers_projects')
117
+ end
118
+ end
101
119
  end
@@ -170,8 +170,8 @@ class ReflectionTest < ActiveRecord::TestCase
170
170
 
171
171
  def test_reflection_of_all_associations
172
172
  # FIXME these assertions bust a lot
173
- assert_equal 28, Firm.reflect_on_all_associations.size
174
- assert_equal 21, Firm.reflect_on_all_associations(:has_many).size
173
+ assert_equal 30, Firm.reflect_on_all_associations.size
174
+ assert_equal 23, Firm.reflect_on_all_associations(:has_many).size
175
175
  assert_equal 7, Firm.reflect_on_all_associations(:has_one).size
176
176
  assert_equal 0, Firm.reflect_on_all_associations(:belongs_to).size
177
177
  end
@@ -156,7 +156,7 @@ class SchemaDumperTest < ActiveRecord::TestCase
156
156
  index_definition = standard_dump.split(/\n/).grep(/add_index.*companies/).first.strip
157
157
  assert_equal 'add_index "companies", ["firm_id", "type", "rating", "ruby_type"], :name => "company_index"', index_definition
158
158
  end
159
-
159
+
160
160
  def test_schema_dump_should_honor_nonstandard_primary_keys
161
161
  output = standard_dump
162
162
  match = output.match(%r{create_table "movies"(.*)do})
@@ -190,4 +190,22 @@ class SchemaDumperTest < ActiveRecord::TestCase
190
190
  output = stream.string
191
191
  assert_match %r{:precision => 3,[[:space:]]+:scale => 2,[[:space:]]+:default => 2.78}, output
192
192
  end
193
+
194
+ if current_adapter?(:PostgreSQLAdapter)
195
+ def test_schema_dump_includes_xml_shorthand_definition
196
+ output = standard_dump
197
+ if %r{create_table "postgresql_xml_data_type"} =~ output
198
+ assert_match %r{t.xml "data"}, output
199
+ end
200
+ end
201
+ end
202
+
203
+ def test_schema_dump_keeps_id_column_when_id_is_false_and_id_column_added
204
+ output = standard_dump
205
+ match = output.match(%r{create_table "goofy_string_id"(.*)do.*\n(.*)\n})
206
+ assert_not_nil(match, "goofy_string_id table not found")
207
+ assert_match %r(:id => false), match[1], "no table id not preserved"
208
+ assert_match %r{t.string[[:space:]]+"id",[[:space:]]+:null => false$}, match[2], "non-primary key id column not preserved"
209
+ end
193
210
  end
211
+