activerecord 1.11.1 → 1.12.1

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 (102) hide show
  1. data/CHANGELOG +198 -0
  2. data/lib/active_record.rb +19 -14
  3. data/lib/active_record/acts/list.rb +8 -6
  4. data/lib/active_record/acts/tree.rb +33 -10
  5. data/lib/active_record/aggregations.rb +1 -7
  6. data/lib/active_record/associations.rb +151 -82
  7. data/lib/active_record/associations/association_collection.rb +25 -0
  8. data/lib/active_record/associations/association_proxy.rb +9 -8
  9. data/lib/active_record/associations/belongs_to_association.rb +19 -5
  10. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +44 -69
  11. data/lib/active_record/associations/has_many_association.rb +6 -14
  12. data/lib/active_record/associations/has_one_association.rb +5 -3
  13. data/lib/active_record/base.rb +344 -130
  14. data/lib/active_record/callbacks.rb +2 -2
  15. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +128 -0
  16. data/lib/active_record/connection_adapters/abstract/database_statements.rb +104 -0
  17. data/lib/active_record/connection_adapters/abstract/quoting.rb +51 -0
  18. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +249 -0
  19. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +245 -0
  20. data/lib/active_record/connection_adapters/abstract_adapter.rb +29 -464
  21. data/lib/active_record/connection_adapters/db2_adapter.rb +40 -10
  22. data/lib/active_record/connection_adapters/mysql_adapter.rb +131 -60
  23. data/lib/active_record/connection_adapters/oci_adapter.rb +106 -26
  24. data/lib/active_record/connection_adapters/postgresql_adapter.rb +211 -62
  25. data/lib/active_record/connection_adapters/sqlite_adapter.rb +193 -44
  26. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +24 -15
  27. data/lib/active_record/fixtures.rb +47 -24
  28. data/lib/active_record/migration.rb +34 -5
  29. data/lib/active_record/observer.rb +32 -2
  30. data/lib/active_record/query_cache.rb +12 -11
  31. data/lib/active_record/schema.rb +58 -0
  32. data/lib/active_record/schema_dumper.rb +84 -0
  33. data/lib/active_record/transactions.rb +1 -3
  34. data/lib/active_record/validations.rb +40 -26
  35. data/lib/active_record/vendor/mysql.rb +6 -0
  36. data/lib/active_record/version.rb +9 -0
  37. data/rakefile +5 -16
  38. data/test/abstract_unit.rb +6 -11
  39. data/test/adapter_test.rb +58 -0
  40. data/test/ar_schema_test.rb +33 -0
  41. data/test/association_callbacks_test.rb +14 -0
  42. data/test/associations_go_eager_test.rb +56 -14
  43. data/test/associations_test.rb +245 -25
  44. data/test/base_test.rb +205 -34
  45. data/test/binary_test.rb +25 -42
  46. data/test/callbacks_test.rb +75 -0
  47. data/test/conditions_scoping_test.rb +136 -0
  48. data/test/connections/native_mysql/connection.rb +0 -4
  49. data/test/connections/native_sqlite3/in_memory_connection.rb +17 -0
  50. data/test/copy_table_sqlite.rb +64 -0
  51. data/test/deprecated_associations_test.rb +7 -6
  52. data/test/deprecated_finder_test.rb +3 -3
  53. data/test/finder_test.rb +33 -3
  54. data/test/fixtures/accounts.yml +5 -0
  55. data/test/fixtures/categories_ordered.yml +7 -0
  56. data/test/fixtures/category.rb +11 -1
  57. data/test/fixtures/comment.rb +22 -2
  58. data/test/fixtures/comments.yml +6 -0
  59. data/test/fixtures/companies.yml +15 -0
  60. data/test/fixtures/company.rb +24 -1
  61. data/test/fixtures/db_definitions/db2.drop.sql +5 -1
  62. data/test/fixtures/db_definitions/db2.sql +15 -1
  63. data/test/fixtures/db_definitions/mysql.drop.sql +2 -0
  64. data/test/fixtures/db_definitions/mysql.sql +17 -2
  65. data/test/fixtures/db_definitions/oci.drop.sql +37 -5
  66. data/test/fixtures/db_definitions/oci.sql +47 -4
  67. data/test/fixtures/db_definitions/oci2.drop.sql +1 -1
  68. data/test/fixtures/db_definitions/oci2.sql +2 -2
  69. data/test/fixtures/db_definitions/postgresql.drop.sql +4 -0
  70. data/test/fixtures/db_definitions/postgresql.sql +33 -4
  71. data/test/fixtures/db_definitions/sqlite.drop.sql +2 -0
  72. data/test/fixtures/db_definitions/sqlite.sql +16 -2
  73. data/test/fixtures/db_definitions/sqlserver.drop.sql +2 -0
  74. data/test/fixtures/db_definitions/sqlserver.sql +16 -2
  75. data/test/fixtures/developer.rb +1 -1
  76. data/test/fixtures/flowers.jpg +0 -0
  77. data/test/fixtures/keyboard.rb +3 -0
  78. data/test/fixtures/mixins.yml +11 -1
  79. data/test/fixtures/order.rb +4 -0
  80. data/test/fixtures/post.rb +4 -0
  81. data/test/fixtures/posts.yml +7 -0
  82. data/test/fixtures/project.rb +1 -0
  83. data/test/fixtures/subject.rb +4 -0
  84. data/test/fixtures/subscriber.rb +2 -4
  85. data/test/fixtures/topics.yml +2 -2
  86. data/test/fixtures_test.rb +79 -7
  87. data/test/inheritance_test.rb +2 -2
  88. data/test/lifecycle_test.rb +14 -6
  89. data/test/migration_test.rb +164 -6
  90. data/test/mixin_test.rb +78 -2
  91. data/test/pk_test.rb +25 -1
  92. data/test/readonly_test.rb +31 -0
  93. data/test/reflection_test.rb +4 -1
  94. data/test/schema_dumper_test.rb +19 -0
  95. data/test/schema_test_postgresql.rb +3 -2
  96. data/test/synonym_test_oci.rb +17 -0
  97. data/test/threaded_connections_test.rb +2 -1
  98. data/test/transactions_test.rb +109 -10
  99. data/test/validations_test.rb +70 -42
  100. metadata +25 -5
  101. data/test/fixtures/associations.png +0 -0
  102. data/test/thread_safety_test.rb +0 -36
@@ -5,6 +5,7 @@ require 'fixtures/reply'
5
5
 
6
6
  class Topic; def after_find() end end
7
7
  class Developer; def after_find() end end
8
+ class SpecialDeveloper < Developer; end
8
9
 
9
10
  class TopicManualObserver
10
11
  include Singleton
@@ -64,22 +65,22 @@ class LifecycleTest < Test::Unit::TestCase
64
65
  end
65
66
 
66
67
  def test_after_save
67
- topic_observer = TopicManualObserver.instance
68
+ ActiveRecord::Base.observers = :topic_manual_observer
68
69
 
69
70
  topic = Topic.find(1)
70
71
  topic.title = "hello"
71
72
  topic.save
72
73
 
73
- assert topic_observer.has_been_notified?
74
- assert_equal :after_save, topic_observer.callbacks.last["callback_method"]
74
+ assert TopicManualObserver.instance.has_been_notified?
75
+ assert_equal :after_save, TopicManualObserver.instance.callbacks.last["callback_method"]
75
76
  end
76
77
 
77
78
  def test_observer_update_on_save
78
- topic_observer = TopicManualObserver.instance
79
+ ActiveRecord::Base.observers = TopicManualObserver
79
80
 
80
81
  topic = Topic.find(1)
81
- assert topic_observer.has_been_notified?
82
- assert_equal :after_find, topic_observer.callbacks.first["callback_method"]
82
+ assert TopicManualObserver.instance.has_been_notified?
83
+ assert_equal :after_find, TopicManualObserver.instance.callbacks.first["callback_method"]
83
84
  end
84
85
 
85
86
  def test_auto_observer
@@ -105,4 +106,11 @@ class LifecycleTest < Test::Unit::TestCase
105
106
  developer = Developer.find(1)
106
107
  assert_equal multi_observer.record.name, developer.name
107
108
  end
109
+
110
+ def test_observing_subclasses
111
+ multi_observer = MultiObserver.instance
112
+
113
+ developer = SpecialDeveloper.find(1)
114
+ assert_equal multi_observer.record.name, developer.name
115
+ end
108
116
  end
@@ -8,12 +8,14 @@ if ActiveRecord::Base.connection.supports_migrations?
8
8
  class Reminder < ActiveRecord::Base; end
9
9
 
10
10
  class MigrationTest < Test::Unit::TestCase
11
+ self.use_transactional_fixtures = false
12
+
11
13
  def setup
12
14
  end
13
15
 
14
16
  def teardown
15
17
  ActiveRecord::Base.connection.initialize_schema_information
16
- ActiveRecord::Base.connection.update "UPDATE schema_info SET version = 0"
18
+ ActiveRecord::Base.connection.update "UPDATE #{ActiveRecord::Migrator.schema_info_table_name} SET version = 0"
17
19
 
18
20
  Reminder.connection.drop_table("reminders") rescue nil
19
21
  Reminder.connection.drop_table("people_reminders") rescue nil
@@ -32,12 +34,75 @@ if ActiveRecord::Base.connection.supports_migrations?
32
34
 
33
35
  def test_add_index
34
36
  Person.connection.add_column "people", "last_name", :string
37
+ Person.connection.add_column "people", "administrator", :boolean
35
38
 
36
39
  assert_nothing_raised { Person.connection.add_index("people", "last_name") }
37
40
  assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
38
41
 
39
42
  assert_nothing_raised { Person.connection.add_index("people", ["last_name", "first_name"]) }
40
43
  assert_nothing_raised { Person.connection.remove_index("people", "last_name") }
44
+
45
+ assert_nothing_raised { Person.connection.add_index("people", %w(last_name first_name administrator), :name => "named_admin") }
46
+ assert_nothing_raised { Person.connection.remove_index("people", :name => "named_admin") }
47
+ end
48
+
49
+ def test_create_table_adds_id
50
+ Person.connection.create_table :testings do |t|
51
+ t.column :foo, :string
52
+ end
53
+
54
+ assert_equal %w(foo id),
55
+ Person.connection.columns(:testings).map { |c| c.name }.sort
56
+ ensure
57
+ Person.connection.drop_table :testings rescue nil
58
+ end
59
+
60
+ def test_create_table_with_not_null_column
61
+ Person.connection.create_table :testings do |t|
62
+ t.column :foo, :string, :null => false
63
+ end
64
+
65
+ assert_raises(ActiveRecord::StatementInvalid) do
66
+ Person.connection.execute "insert into testings (foo) values (NULL)"
67
+ end
68
+ ensure
69
+ Person.connection.drop_table :testings rescue nil
70
+ end
71
+
72
+ def test_create_table_with_defaults
73
+ Person.connection.create_table :testings do |t|
74
+ t.column :one, :string, :default => "hello"
75
+ t.column :two, :boolean, :default => true
76
+ t.column :three, :boolean, :default => false
77
+ t.column :four, :integer, :default => 1
78
+ end
79
+
80
+ columns = Person.connection.columns(:testings)
81
+ one = columns.detect { |c| c.name == "one" }
82
+ two = columns.detect { |c| c.name == "two" }
83
+ three = columns.detect { |c| c.name == "three" }
84
+ four = columns.detect { |c| c.name == "four" }
85
+
86
+ assert_equal "hello", one.default
87
+ assert_equal true, two.default
88
+ assert_equal false, three.default
89
+ assert_equal 1, four.default
90
+
91
+ ensure
92
+ Person.connection.drop_table :testings rescue nil
93
+ end
94
+
95
+ def test_add_column_not_null
96
+ Person.connection.create_table :testings do |t|
97
+ t.column :foo, :string
98
+ end
99
+ Person.connection.add_column :testings, :bar, :string, :null => false
100
+
101
+ assert_raises(ActiveRecord::StatementInvalid) do
102
+ Person.connection.execute "insert into testings (foo, bar) values ('hello', NULL)"
103
+ end
104
+ ensure
105
+ Person.connection.drop_table :testings rescue nil
41
106
  end
42
107
 
43
108
  def test_native_types
@@ -67,15 +132,29 @@ if ActiveRecord::Base.connection.supports_migrations?
67
132
  assert_equal TrueClass, bob.male?.class
68
133
  end
69
134
 
70
- def test_add_remove_single_field
135
+ def test_add_remove_single_field_using_string_arguments
71
136
  assert !Person.column_methods_hash.include?(:last_name)
72
137
 
73
- PeopleHaveLastNames.up
138
+ ActiveRecord::Migration.add_column 'people', 'last_name', :string
74
139
 
75
140
  Person.reset_column_information
76
141
  assert Person.column_methods_hash.include?(:last_name)
77
142
 
78
- PeopleHaveLastNames.down
143
+ ActiveRecord::Migration.remove_column 'people', 'last_name'
144
+
145
+ Person.reset_column_information
146
+ assert !Person.column_methods_hash.include?(:last_name)
147
+ end
148
+
149
+ def test_add_remove_single_field_using_symbol_arguments
150
+ assert !Person.column_methods_hash.include?(:last_name)
151
+
152
+ ActiveRecord::Migration.add_column :people, :last_name, :string
153
+
154
+ Person.reset_column_information
155
+ assert Person.column_methods_hash.include?(:last_name)
156
+
157
+ ActiveRecord::Migration.remove_column :people, :last_name
79
158
 
80
159
  Person.reset_column_information
81
160
  assert !Person.column_methods_hash.include?(:last_name)
@@ -101,6 +180,25 @@ if ActiveRecord::Base.connection.supports_migrations?
101
180
 
102
181
  end
103
182
 
183
+ def test_rename_table
184
+ begin
185
+ ActiveRecord::Base.connection.create_table :octopuses do |t|
186
+ t.column :url, :string
187
+ end
188
+ ActiveRecord::Base.connection.rename_table :octopuses, :octopi
189
+
190
+ assert_nothing_raised do
191
+ ActiveRecord::Base.connection.execute "INSERT INTO octopi (url) VALUES ('http://www.foreverflying.com/octopus-black7.jpg')"
192
+ end
193
+
194
+ assert_equal 'http://www.foreverflying.com/octopus-black7.jpg', ActiveRecord::Base.connection.select_value("SELECT url FROM octopi WHERE id=1")
195
+
196
+ ensure
197
+ ActiveRecord::Base.connection.drop_table :octopuses rescue nil
198
+ ActiveRecord::Base.connection.drop_table :octopi rescue nil
199
+ end
200
+ end
201
+
104
202
  def test_change_column
105
203
  Person.connection.add_column "people", "bio", :string
106
204
  assert_nothing_raised { Person.connection.change_column "people", "bio", :text }
@@ -197,5 +295,65 @@ if ActiveRecord::Base.connection.supports_migrations?
197
295
  assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
198
296
  assert_equal "hello world", Reminder.find(:first).content
199
297
  end
200
- end
201
- end
298
+
299
+ def test_schema_info_table_name
300
+ ActiveRecord::Base.table_name_prefix = "prefix_"
301
+ ActiveRecord::Base.table_name_suffix = "_suffix"
302
+ Reminder.reset_table_name
303
+ assert_equal "prefix_schema_info_suffix", ActiveRecord::Migrator.schema_info_table_name
304
+ ActiveRecord::Base.table_name_prefix = ""
305
+ ActiveRecord::Base.table_name_suffix = ""
306
+ Reminder.reset_table_name
307
+ assert_equal "schema_info", ActiveRecord::Migrator.schema_info_table_name
308
+ end
309
+
310
+ def test_proper_table_name
311
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name('table')
312
+ assert_equal "table", ActiveRecord::Migrator.proper_table_name(:table)
313
+ assert_equal "reminders", ActiveRecord::Migrator.proper_table_name(Reminder)
314
+ Reminder.reset_table_name
315
+ assert_equal Reminder.table_name, ActiveRecord::Migrator.proper_table_name(Reminder)
316
+
317
+ # Use the model's own prefix/suffix if a model is given
318
+ ActiveRecord::Base.table_name_prefix = "ARprefix_"
319
+ ActiveRecord::Base.table_name_suffix = "_ARsuffix"
320
+ Reminder.table_name_prefix = 'prefix_'
321
+ Reminder.table_name_suffix = '_suffix'
322
+ Reminder.reset_table_name
323
+ assert_equal "prefix_reminders_suffix", ActiveRecord::Migrator.proper_table_name(Reminder)
324
+ Reminder.table_name_prefix = ''
325
+ Reminder.table_name_suffix = ''
326
+ Reminder.reset_table_name
327
+
328
+ # Use AR::Base's prefix/suffix if string or symbol is given
329
+ ActiveRecord::Base.table_name_prefix = "prefix_"
330
+ ActiveRecord::Base.table_name_suffix = "_suffix"
331
+ Reminder.reset_table_name
332
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name('table')
333
+ assert_equal "prefix_table_suffix", ActiveRecord::Migrator.proper_table_name(:table)
334
+ ActiveRecord::Base.table_name_prefix = ""
335
+ ActiveRecord::Base.table_name_suffix = ""
336
+ Reminder.reset_table_name
337
+ end
338
+
339
+ def test_add_drop_table_with_prefix_and_suffix
340
+ assert_raises(ActiveRecord::StatementInvalid) { Reminder.column_methods_hash }
341
+
342
+ ActiveRecord::Base.table_name_prefix = 'prefix_'
343
+ ActiveRecord::Base.table_name_suffix = '_suffix'
344
+ Reminder.reset_table_name
345
+ WeNeedReminders.up
346
+
347
+ assert Reminder.create("content" => "hello world", "remind_at" => Time.now)
348
+ assert_equal "hello world", Reminder.find(:first).content
349
+
350
+ WeNeedReminders.down
351
+ assert_raises(ActiveRecord::StatementInvalid) { Reminder.find(:first) }
352
+ ActiveRecord::Base.table_name_prefix = ''
353
+ ActiveRecord::Base.table_name_suffix = ''
354
+ Reminder.reset_table_name
355
+ end
356
+
357
+ end
358
+
359
+ end
@@ -65,6 +65,22 @@ class ListTest < Test::Unit::TestCase
65
65
  ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
66
66
 
67
67
  end
68
+
69
+ def test_move_to_bottom_with_next_to_last_item
70
+ assert_equal [mixins(:list_1),
71
+ mixins(:list_2),
72
+ mixins(:list_3),
73
+ mixins(:list_4)],
74
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
75
+
76
+ mixins(:list_3).move_to_bottom
77
+
78
+ assert_equal [mixins(:list_1),
79
+ mixins(:list_2),
80
+ mixins(:list_4),
81
+ mixins(:list_3)],
82
+ ListMixin.find(:all, :conditions => 'parent_id = 5', :order => 'pos')
83
+ end
68
84
 
69
85
  def test_next_prev
70
86
  assert_equal mixins(:list_2), mixins(:list_1).lower_item
@@ -126,6 +142,15 @@ class ListTest < Test::Unit::TestCase
126
142
 
127
143
  new4.reload
128
144
  assert_equal 4, new4.pos
145
+
146
+ new5 = ListMixin.create("parent_id" => 20)
147
+ assert_equal 5, new5.pos
148
+
149
+ new5.insert_at(1)
150
+ assert_equal 1, new5.pos
151
+
152
+ new4.reload
153
+ assert_equal 5, new4.pos
129
154
  end
130
155
 
131
156
  def test_delete_middle
@@ -189,6 +214,13 @@ class TreeTest < Test::Unit::TestCase
189
214
  assert_equal mixins(:tree_4).children, []
190
215
  end
191
216
 
217
+ def test_has_parent
218
+ assert_equal false, mixins(:tree_1).has_parent?
219
+ assert_equal true, mixins(:tree_2).has_parent?
220
+ assert_equal true, mixins(:tree_3).has_parent?
221
+ assert_equal true, mixins(:tree_4).has_parent?
222
+ end
223
+
192
224
  def test_parent
193
225
  assert_equal mixins(:tree_2).parent, mixins(:tree_1)
194
226
  assert_equal mixins(:tree_2).parent, mixins(:tree_4).parent
@@ -196,11 +228,14 @@ class TreeTest < Test::Unit::TestCase
196
228
  end
197
229
 
198
230
  def test_delete
199
- assert_equal 4, TreeMixin.count
231
+ assert_equal 6, TreeMixin.count
200
232
  mixins(:tree_1).destroy
233
+ assert_equal 2, TreeMixin.count
234
+ mixins(:tree2_1).destroy
235
+ mixins(:tree3_1).destroy
201
236
  assert_equal 0, TreeMixin.count
202
237
  end
203
-
238
+
204
239
  def test_insert
205
240
  @extra = mixins(:tree_1).children.create
206
241
 
@@ -214,6 +249,46 @@ class TreeTest < Test::Unit::TestCase
214
249
  assert mixins(:tree_1).children.include?(mixins(:tree_4))
215
250
  end
216
251
 
252
+ def test_ancestors
253
+ assert_equal [], mixins(:tree_1).ancestors
254
+ assert_equal [mixins(:tree_1)], mixins(:tree_2).ancestors
255
+ assert_equal [mixins(:tree_2), mixins(:tree_1)], mixins(:tree_3).ancestors
256
+ assert_equal [mixins(:tree_1)], mixins(:tree_4).ancestors
257
+ assert_equal [], mixins(:tree2_1).ancestors
258
+ assert_equal [], mixins(:tree3_1).ancestors
259
+ end
260
+
261
+ def test_root
262
+ assert_equal mixins(:tree_1), TreeMixin.root
263
+ assert_equal mixins(:tree_1), mixins(:tree_1).root
264
+ assert_equal mixins(:tree_1), mixins(:tree_2).root
265
+ assert_equal mixins(:tree_1), mixins(:tree_3).root
266
+ assert_equal mixins(:tree_1), mixins(:tree_4).root
267
+ assert_equal mixins(:tree2_1), mixins(:tree2_1).root
268
+ assert_equal mixins(:tree3_1), mixins(:tree3_1).root
269
+ end
270
+
271
+ def test_roots
272
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], TreeMixin.roots
273
+ end
274
+
275
+ def test_siblings
276
+ assert_equal [mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).siblings
277
+ assert_equal [mixins(:tree_4)], mixins(:tree_2).siblings
278
+ assert_equal [], mixins(:tree_3).siblings
279
+ assert_equal [mixins(:tree_2)], mixins(:tree_4).siblings
280
+ assert_equal [mixins(:tree_1), mixins(:tree3_1)], mixins(:tree2_1).siblings
281
+ assert_equal [mixins(:tree_1), mixins(:tree2_1)], mixins(:tree3_1).siblings
282
+ end
283
+
284
+ def test_self_and_siblings
285
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree_1).self_and_siblings
286
+ assert_equal [mixins(:tree_2), mixins(:tree_4)], mixins(:tree_2).self_and_siblings
287
+ assert_equal [mixins(:tree_3)], mixins(:tree_3).self_and_siblings
288
+ assert_equal [mixins(:tree_2), mixins(:tree_4)], mixins(:tree_4).self_and_siblings
289
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree2_1).self_and_siblings
290
+ assert_equal [mixins(:tree_1), mixins(:tree2_1), mixins(:tree3_1)], mixins(:tree3_1).self_and_siblings
291
+ end
217
292
  end
218
293
 
219
294
  class TouchTest < Test::Unit::TestCase
@@ -264,4 +339,5 @@ class TouchTest < Test::Unit::TestCase
264
339
 
265
340
  Mixin.record_timestamps = true
266
341
  end
342
+
267
343
  end
@@ -2,6 +2,7 @@ require 'abstract_unit'
2
2
  require 'fixtures/topic'
3
3
  require 'fixtures/subscriber'
4
4
  require 'fixtures/movie'
5
+ require 'fixtures/keyboard'
5
6
 
6
7
  class PrimaryKeysTest < Test::Unit::TestCase
7
8
  fixtures :topics, :subscribers, :movies
@@ -22,6 +23,26 @@ class PrimaryKeysTest < Test::Unit::TestCase
22
23
  assert_equal("New Topic", topicReloaded.title)
23
24
  end
24
25
 
26
+ def test_customized_primary_key_auto_assigns_on_save
27
+ keyboard = Keyboard.new(:name => 'HHKB')
28
+ assert_nothing_raised { keyboard.save }
29
+ assert keyboard.id
30
+ assert_equal keyboard.id, Keyboard.find_by_name('HHKB').id
31
+ end
32
+
33
+ def test_customized_primary_key_can_be_get_before_saving
34
+ keyboard = Keyboard.new
35
+ assert_respond_to(keyboard, :key_number)
36
+ assert_nothing_raised { keyboard.key_number }
37
+ end
38
+
39
+ def test_customized_string_primary_key_settable_before_save
40
+ subscriber = Subscriber.new
41
+ assert_nothing_raised { subscriber.id = 'webster123' }
42
+ assert_equal 'webster123', subscriber.id
43
+ assert_equal 'webster123', subscriber.nick
44
+ end
45
+
25
46
  def test_string_key
26
47
  subscriber = Subscriber.find(subscribers(:first).nick)
27
48
  assert_equal(subscribers(:first).name, subscriber.name)
@@ -32,7 +53,7 @@ class PrimaryKeysTest < Test::Unit::TestCase
32
53
  subscriber.id = "jdoe"
33
54
  assert_equal("jdoe", subscriber.id)
34
55
  subscriber.name = "John Doe"
35
- assert_nothing_raised{ subscriber.save }
56
+ assert_nothing_raised { subscriber.save! }
36
57
 
37
58
  subscriberReloaded = Subscriber.find("jdoe")
38
59
  assert_equal("John Doe", subscriberReloaded.name)
@@ -44,12 +65,15 @@ class PrimaryKeysTest < Test::Unit::TestCase
44
65
 
45
66
  def test_primary_key_prefix
46
67
  ActiveRecord::Base.primary_key_prefix_type = :table_name
68
+ Topic.reset_primary_key
47
69
  assert_equal "topicid", Topic.primary_key
48
70
 
49
71
  ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
72
+ Topic.reset_primary_key
50
73
  assert_equal "topic_id", Topic.primary_key
51
74
 
52
75
  ActiveRecord::Base.primary_key_prefix_type = nil
76
+ Topic.reset_primary_key
53
77
  assert_equal "id", Topic.primary_key
54
78
  end
55
79
  end
@@ -0,0 +1,31 @@
1
+ require 'abstract_unit'
2
+ require 'fixtures/topic'
3
+
4
+ class ReadOnlyTest < Test::Unit::TestCase
5
+ fixtures :topics
6
+
7
+ def test_cant_save_readonly_record
8
+ topic = Topic.find(:first)
9
+ assert !topic.readonly?
10
+
11
+ topic.readonly!
12
+ assert topic.readonly?
13
+
14
+ assert_nothing_raised do
15
+ topic.content = 'Luscious forbidden fruit.'
16
+ end
17
+
18
+ assert_raise(ActiveRecord::ReadOnlyRecord) { topic.save }
19
+ assert_raise(ActiveRecord::ReadOnlyRecord) { topic.save! }
20
+ end
21
+
22
+ def test_find_with_readonly_option
23
+ Topic.find(:all).each { |t| assert !t.readonly? }
24
+ Topic.find(:all, :readonly => false).each { |t| assert !t.readonly? }
25
+ Topic.find(:all, :readonly => true).each { |t| assert t.readonly? }
26
+ end
27
+
28
+ def test_find_with_joins_option_implies_readonly
29
+ Topic.find(:all, :joins => '').each { |t| assert t.readonly? }
30
+ end
31
+ end