activerecord 2.0.5 → 2.1.0

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 (289) hide show
  1. data/CHANGELOG +168 -6
  2. data/README +27 -22
  3. data/RUNNING_UNIT_TESTS +7 -4
  4. data/Rakefile +22 -25
  5. data/lib/active_record.rb +8 -2
  6. data/lib/active_record/aggregations.rb +21 -12
  7. data/lib/active_record/association_preload.rb +277 -0
  8. data/lib/active_record/associations.rb +481 -295
  9. data/lib/active_record/associations/association_collection.rb +162 -37
  10. data/lib/active_record/associations/association_proxy.rb +71 -7
  11. data/lib/active_record/associations/belongs_to_association.rb +5 -3
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +5 -6
  13. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +12 -64
  14. data/lib/active_record/associations/has_many_association.rb +8 -73
  15. data/lib/active_record/associations/has_many_through_association.rb +68 -117
  16. data/lib/active_record/associations/has_one_association.rb +7 -5
  17. data/lib/active_record/associations/has_one_through_association.rb +28 -0
  18. data/lib/active_record/attribute_methods.rb +69 -19
  19. data/lib/active_record/base.rb +496 -275
  20. data/lib/active_record/calculations.rb +28 -21
  21. data/lib/active_record/callbacks.rb +9 -38
  22. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +3 -2
  23. data/lib/active_record/connection_adapters/abstract/database_statements.rb +2 -2
  24. data/lib/active_record/connection_adapters/abstract/query_cache.rb +6 -0
  25. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +232 -45
  26. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +141 -27
  27. data/lib/active_record/connection_adapters/abstract_adapter.rb +9 -13
  28. data/lib/active_record/connection_adapters/mysql_adapter.rb +57 -24
  29. data/lib/active_record/connection_adapters/postgresql_adapter.rb +143 -42
  30. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
  31. data/lib/active_record/connection_adapters/sqlite_adapter.rb +18 -10
  32. data/lib/active_record/dirty.rb +158 -0
  33. data/lib/active_record/fixtures.rb +121 -156
  34. data/lib/active_record/locking/optimistic.rb +14 -11
  35. data/lib/active_record/locking/pessimistic.rb +2 -2
  36. data/lib/active_record/migration.rb +157 -77
  37. data/lib/active_record/named_scope.rb +163 -0
  38. data/lib/active_record/observer.rb +19 -5
  39. data/lib/active_record/reflection.rb +34 -14
  40. data/lib/active_record/schema.rb +7 -14
  41. data/lib/active_record/schema_dumper.rb +4 -4
  42. data/lib/active_record/serialization.rb +5 -5
  43. data/lib/active_record/serializers/json_serializer.rb +37 -28
  44. data/lib/active_record/serializers/xml_serializer.rb +52 -29
  45. data/lib/active_record/test_case.rb +36 -0
  46. data/lib/active_record/timestamp.rb +4 -4
  47. data/lib/active_record/transactions.rb +3 -3
  48. data/lib/active_record/validations.rb +182 -248
  49. data/lib/active_record/version.rb +2 -2
  50. data/test/{fixtures → assets}/example.log +0 -0
  51. data/test/{fixtures → assets}/flowers.jpg +0 -0
  52. data/test/cases/aaa_create_tables_test.rb +24 -0
  53. data/test/cases/active_schema_test_mysql.rb +95 -0
  54. data/test/cases/active_schema_test_postgresql.rb +24 -0
  55. data/test/{adapter_test.rb → cases/adapter_test.rb} +15 -14
  56. data/test/{adapter_test_sqlserver.rb → cases/adapter_test_sqlserver.rb} +95 -95
  57. data/test/{aggregations_test.rb → cases/aggregations_test.rb} +20 -20
  58. data/test/{ar_schema_test.rb → cases/ar_schema_test.rb} +6 -6
  59. data/test/cases/associations/belongs_to_associations_test.rb +412 -0
  60. data/test/{associations → cases/associations}/callbacks_test.rb +24 -10
  61. data/test/{associations → cases/associations}/cascaded_eager_loading_test.rb +18 -17
  62. data/test/cases/associations/eager_load_nested_include_test.rb +83 -0
  63. data/test/{associations → cases/associations}/eager_singularization_test.rb +5 -5
  64. data/test/{associations → cases/associations}/eager_test.rb +216 -51
  65. data/test/{associations → cases/associations}/extension_test.rb +8 -8
  66. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +684 -0
  67. data/test/cases/associations/has_many_associations_test.rb +932 -0
  68. data/test/cases/associations/has_many_through_associations_test.rb +190 -0
  69. data/test/cases/associations/has_one_associations_test.rb +323 -0
  70. data/test/cases/associations/has_one_through_associations_test.rb +74 -0
  71. data/test/{associations → cases/associations}/inner_join_association_test.rb +20 -20
  72. data/test/{associations → cases/associations}/join_model_test.rb +175 -35
  73. data/test/cases/associations_test.rb +262 -0
  74. data/test/{attribute_methods_test.rb → cases/attribute_methods_test.rb} +103 -11
  75. data/test/{base_test.rb → cases/base_test.rb} +338 -191
  76. data/test/{binary_test.rb → cases/binary_test.rb} +6 -4
  77. data/test/{calculations_test.rb → cases/calculations_test.rb} +35 -23
  78. data/test/{callbacks_test.rb → cases/callbacks_test.rb} +7 -7
  79. data/test/{class_inheritable_attributes_test.rb → cases/class_inheritable_attributes_test.rb} +3 -3
  80. data/test/{column_alias_test.rb → cases/column_alias_test.rb} +3 -3
  81. data/test/{connection_test_firebird.rb → cases/connection_test_firebird.rb} +2 -2
  82. data/test/{connection_test_mysql.rb → cases/connection_test_mysql.rb} +2 -2
  83. data/test/{copy_table_test_sqlite.rb → cases/copy_table_test_sqlite.rb} +13 -13
  84. data/test/{datatype_test_postgresql.rb → cases/datatype_test_postgresql.rb} +8 -8
  85. data/test/{date_time_test.rb → cases/date_time_test.rb} +5 -5
  86. data/test/{default_test_firebird.rb → cases/default_test_firebird.rb} +3 -3
  87. data/test/{defaults_test.rb → cases/defaults_test.rb} +8 -6
  88. data/test/{deprecated_finder_test.rb → cases/deprecated_finder_test.rb} +3 -3
  89. data/test/cases/dirty_test.rb +163 -0
  90. data/test/cases/finder_respond_to_test.rb +76 -0
  91. data/test/{finder_test.rb → cases/finder_test.rb} +266 -33
  92. data/test/{fixtures_test.rb → cases/fixtures_test.rb} +88 -72
  93. data/test/cases/helper.rb +47 -0
  94. data/test/{inheritance_test.rb → cases/inheritance_test.rb} +61 -17
  95. data/test/cases/invalid_date_test.rb +24 -0
  96. data/test/{json_serialization_test.rb → cases/json_serialization_test.rb} +36 -11
  97. data/test/{lifecycle_test.rb → cases/lifecycle_test.rb} +16 -13
  98. data/test/{locking_test.rb → cases/locking_test.rb} +17 -10
  99. data/test/{method_scoping_test.rb → cases/method_scoping_test.rb} +75 -39
  100. data/test/{migration_test.rb → cases/migration_test.rb} +420 -80
  101. data/test/{migration_test_firebird.rb → cases/migration_test_firebird.rb} +3 -3
  102. data/test/{mixin_test.rb → cases/mixin_test.rb} +7 -6
  103. data/test/{modules_test.rb → cases/modules_test.rb} +11 -6
  104. data/test/{multiple_db_test.rb → cases/multiple_db_test.rb} +5 -5
  105. data/test/cases/named_scope_test.rb +157 -0
  106. data/test/{pk_test.rb → cases/pk_test.rb} +10 -10
  107. data/test/{query_cache_test.rb → cases/query_cache_test.rb} +12 -10
  108. data/test/{readonly_test.rb → cases/readonly_test.rb} +11 -11
  109. data/test/{reflection_test.rb → cases/reflection_test.rb} +15 -14
  110. data/test/{reserved_word_test_mysql.rb → cases/reserved_word_test_mysql.rb} +4 -5
  111. data/test/{schema_authorization_test_postgresql.rb → cases/schema_authorization_test_postgresql.rb} +5 -5
  112. data/test/cases/schema_dumper_test.rb +138 -0
  113. data/test/cases/schema_test_postgresql.rb +102 -0
  114. data/test/{serialization_test.rb → cases/serialization_test.rb} +7 -7
  115. data/test/{synonym_test_oracle.rb → cases/synonym_test_oracle.rb} +5 -5
  116. data/test/{table_name_test_sqlserver.rb → cases/table_name_test_sqlserver.rb} +3 -3
  117. data/test/{threaded_connections_test.rb → cases/threaded_connections_test.rb} +7 -7
  118. data/test/{transactions_test.rb → cases/transactions_test.rb} +31 -5
  119. data/test/{unconnected_test.rb → cases/unconnected_test.rb} +2 -2
  120. data/test/{validations_test.rb → cases/validations_test.rb} +141 -39
  121. data/test/{xml_serialization_test.rb → cases/xml_serialization_test.rb} +12 -12
  122. data/test/config.rb +5 -0
  123. data/test/connections/native_db2/connection.rb +1 -1
  124. data/test/connections/native_firebird/connection.rb +1 -1
  125. data/test/connections/native_frontbase/connection.rb +1 -1
  126. data/test/connections/native_mysql/connection.rb +1 -1
  127. data/test/connections/native_openbase/connection.rb +1 -1
  128. data/test/connections/native_oracle/connection.rb +1 -1
  129. data/test/connections/native_postgresql/connection.rb +1 -3
  130. data/test/connections/native_sqlite/connection.rb +2 -2
  131. data/test/connections/native_sqlite3/connection.rb +2 -2
  132. data/test/connections/native_sqlite3/in_memory_connection.rb +3 -3
  133. data/test/connections/native_sybase/connection.rb +1 -1
  134. data/test/fixtures/author_addresses.yml +5 -0
  135. data/test/fixtures/authors.yml +2 -0
  136. data/test/fixtures/clubs.yml +6 -0
  137. data/test/fixtures/jobs.yml +7 -0
  138. data/test/fixtures/members.yml +4 -0
  139. data/test/fixtures/memberships.yml +20 -0
  140. data/test/fixtures/owners.yml +7 -0
  141. data/test/fixtures/people.yml +4 -1
  142. data/test/fixtures/pets.yml +14 -0
  143. data/test/fixtures/posts.yml +1 -0
  144. data/test/fixtures/price_estimates.yml +7 -0
  145. data/test/fixtures/readers.yml +5 -0
  146. data/test/fixtures/references.yml +17 -0
  147. data/test/fixtures/sponsors.yml +9 -0
  148. data/test/fixtures/subscribers.yml +7 -0
  149. data/test/fixtures/subscriptions.yml +12 -0
  150. data/test/fixtures/taggings.yml +4 -1
  151. data/test/fixtures/topics.yml +22 -2
  152. data/test/fixtures/warehouse-things.yml +3 -0
  153. data/test/{fixtures/migrations_with_decimal → migrations/decimal}/1_give_me_big_numbers.rb +0 -0
  154. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/1_people_have_last_names.rb +1 -1
  155. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/2_we_need_reminders.rb +1 -1
  156. data/test/{fixtures/migrations_with_duplicate → migrations/duplicate}/3_foo.rb +0 -0
  157. data/test/{fixtures/migrations → migrations/duplicate}/3_innocent_jointable.rb +0 -0
  158. data/test/migrations/duplicate_names/20080507052938_chunky.rb +7 -0
  159. data/test/migrations/duplicate_names/20080507053028_chunky.rb +7 -0
  160. data/test/{fixtures/migrations_with_duplicate → migrations/interleaved/pass_1}/3_innocent_jointable.rb +0 -0
  161. data/test/{fixtures/migrations → migrations/interleaved/pass_2}/1_people_have_last_names.rb +1 -1
  162. data/test/{fixtures/migrations_with_missing_versions/4_innocent_jointable.rb → migrations/interleaved/pass_2/3_innocent_jointable.rb} +0 -0
  163. data/test/{fixtures/migrations_with_missing_versions → migrations/interleaved/pass_3}/1_people_have_last_names.rb +1 -1
  164. data/test/migrations/interleaved/pass_3/2_i_raise_on_down.rb +8 -0
  165. data/test/migrations/interleaved/pass_3/3_innocent_jointable.rb +12 -0
  166. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/1000_people_have_middle_names.rb +1 -1
  167. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  168. data/test/{fixtures/migrations_with_missing_versions → migrations/missing}/3_we_need_reminders.rb +1 -1
  169. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  170. data/test/migrations/valid/1_people_have_last_names.rb +9 -0
  171. data/test/{fixtures/migrations → migrations/valid}/2_we_need_reminders.rb +1 -1
  172. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  173. data/test/{fixtures → models}/author.rb +28 -4
  174. data/test/{fixtures → models}/auto_id.rb +0 -0
  175. data/test/{fixtures → models}/binary.rb +0 -0
  176. data/test/{fixtures → models}/book.rb +0 -0
  177. data/test/{fixtures → models}/categorization.rb +0 -0
  178. data/test/{fixtures → models}/category.rb +8 -5
  179. data/test/{fixtures → models}/citation.rb +0 -0
  180. data/test/models/club.rb +7 -0
  181. data/test/{fixtures → models}/column_name.rb +0 -0
  182. data/test/{fixtures → models}/comment.rb +5 -3
  183. data/test/{fixtures → models}/company.rb +15 -6
  184. data/test/{fixtures → models}/company_in_module.rb +5 -3
  185. data/test/{fixtures → models}/computer.rb +0 -1
  186. data/test/{fixtures → models}/contact.rb +1 -1
  187. data/test/{fixtures → models}/course.rb +0 -0
  188. data/test/{fixtures → models}/customer.rb +8 -8
  189. data/test/{fixtures → models}/default.rb +0 -0
  190. data/test/{fixtures → models}/developer.rb +14 -10
  191. data/test/{fixtures → models}/edge.rb +0 -0
  192. data/test/{fixtures → models}/entrant.rb +0 -0
  193. data/test/models/guid.rb +2 -0
  194. data/test/{fixtures → models}/item.rb +0 -0
  195. data/test/models/job.rb +5 -0
  196. data/test/{fixtures → models}/joke.rb +0 -0
  197. data/test/{fixtures → models}/keyboard.rb +0 -0
  198. data/test/{fixtures → models}/legacy_thing.rb +0 -0
  199. data/test/{fixtures → models}/matey.rb +0 -0
  200. data/test/models/member.rb +9 -0
  201. data/test/models/membership.rb +9 -0
  202. data/test/{fixtures → models}/minimalistic.rb +0 -0
  203. data/test/{fixtures → models}/mixed_case_monkey.rb +0 -0
  204. data/test/{fixtures → models}/movie.rb +0 -0
  205. data/test/{fixtures → models}/order.rb +2 -2
  206. data/test/models/owner.rb +4 -0
  207. data/test/{fixtures → models}/parrot.rb +0 -0
  208. data/test/models/person.rb +10 -0
  209. data/test/models/pet.rb +4 -0
  210. data/test/models/pirate.rb +9 -0
  211. data/test/{fixtures → models}/post.rb +23 -2
  212. data/test/models/price_estimate.rb +3 -0
  213. data/test/{fixtures → models}/project.rb +1 -0
  214. data/test/{fixtures → models}/reader.rb +0 -0
  215. data/test/models/reference.rb +4 -0
  216. data/test/{fixtures → models}/reply.rb +7 -5
  217. data/test/{fixtures → models}/ship.rb +0 -0
  218. data/test/models/sponsor.rb +4 -0
  219. data/test/{fixtures → models}/subject.rb +0 -0
  220. data/test/{fixtures → models}/subscriber.rb +2 -0
  221. data/test/models/subscription.rb +4 -0
  222. data/test/{fixtures → models}/tag.rb +0 -0
  223. data/test/{fixtures → models}/tagging.rb +0 -0
  224. data/test/{fixtures → models}/task.rb +0 -0
  225. data/test/{fixtures → models}/topic.rb +32 -4
  226. data/test/{fixtures → models}/treasure.rb +2 -0
  227. data/test/{fixtures → models}/vertex.rb +0 -0
  228. data/test/models/warehouse_thing.rb +5 -0
  229. data/test/schema/mysql_specific_schema.rb +12 -0
  230. data/test/schema/postgresql_specific_schema.rb +103 -0
  231. data/test/schema/schema.rb +421 -0
  232. data/test/schema/schema2.rb +6 -0
  233. data/test/schema/sqlite_specific_schema.rb +25 -0
  234. data/test/schema/sqlserver_specific_schema.rb +5 -0
  235. metadata +192 -176
  236. data/test/aaa_create_tables_test.rb +0 -72
  237. data/test/abstract_unit.rb +0 -84
  238. data/test/active_schema_test_mysql.rb +0 -46
  239. data/test/all.sh +0 -8
  240. data/test/association_inheritance_reload.rb +0 -14
  241. data/test/associations_test.rb +0 -2177
  242. data/test/fixtures/bad_fixtures/attr_with_numeric_first_char +0 -1
  243. data/test/fixtures/bad_fixtures/attr_with_spaces +0 -1
  244. data/test/fixtures/bad_fixtures/blank_line +0 -3
  245. data/test/fixtures/bad_fixtures/duplicate_attributes +0 -3
  246. data/test/fixtures/bad_fixtures/missing_value +0 -1
  247. data/test/fixtures/db_definitions/db2.drop.sql +0 -33
  248. data/test/fixtures/db_definitions/db2.sql +0 -235
  249. data/test/fixtures/db_definitions/db22.drop.sql +0 -2
  250. data/test/fixtures/db_definitions/db22.sql +0 -5
  251. data/test/fixtures/db_definitions/firebird.drop.sql +0 -65
  252. data/test/fixtures/db_definitions/firebird.sql +0 -310
  253. data/test/fixtures/db_definitions/firebird2.drop.sql +0 -2
  254. data/test/fixtures/db_definitions/firebird2.sql +0 -6
  255. data/test/fixtures/db_definitions/frontbase.drop.sql +0 -33
  256. data/test/fixtures/db_definitions/frontbase.sql +0 -273
  257. data/test/fixtures/db_definitions/frontbase2.drop.sql +0 -1
  258. data/test/fixtures/db_definitions/frontbase2.sql +0 -4
  259. data/test/fixtures/db_definitions/openbase.drop.sql +0 -2
  260. data/test/fixtures/db_definitions/openbase.sql +0 -318
  261. data/test/fixtures/db_definitions/openbase2.drop.sql +0 -2
  262. data/test/fixtures/db_definitions/openbase2.sql +0 -7
  263. data/test/fixtures/db_definitions/oracle.drop.sql +0 -67
  264. data/test/fixtures/db_definitions/oracle.sql +0 -330
  265. data/test/fixtures/db_definitions/oracle2.drop.sql +0 -2
  266. data/test/fixtures/db_definitions/oracle2.sql +0 -6
  267. data/test/fixtures/db_definitions/postgresql.drop.sql +0 -44
  268. data/test/fixtures/db_definitions/postgresql.sql +0 -292
  269. data/test/fixtures/db_definitions/postgresql2.drop.sql +0 -2
  270. data/test/fixtures/db_definitions/postgresql2.sql +0 -4
  271. data/test/fixtures/db_definitions/schema.rb +0 -354
  272. data/test/fixtures/db_definitions/schema2.rb +0 -11
  273. data/test/fixtures/db_definitions/sqlite.drop.sql +0 -33
  274. data/test/fixtures/db_definitions/sqlite.sql +0 -219
  275. data/test/fixtures/db_definitions/sqlite2.drop.sql +0 -2
  276. data/test/fixtures/db_definitions/sqlite2.sql +0 -5
  277. data/test/fixtures/db_definitions/sybase.drop.sql +0 -35
  278. data/test/fixtures/db_definitions/sybase.sql +0 -222
  279. data/test/fixtures/db_definitions/sybase2.drop.sql +0 -4
  280. data/test/fixtures/db_definitions/sybase2.sql +0 -5
  281. data/test/fixtures/developers_projects/david_action_controller +0 -3
  282. data/test/fixtures/developers_projects/david_active_record +0 -3
  283. data/test/fixtures/developers_projects/jamis_active_record +0 -2
  284. data/test/fixtures/person.rb +0 -4
  285. data/test/fixtures/pirate.rb +0 -5
  286. data/test/fixtures/subscribers/first +0 -2
  287. data/test/fixtures/subscribers/second +0 -2
  288. data/test/schema_dumper_test.rb +0 -131
  289. data/test/schema_test_postgresql.rb +0 -64
@@ -1,9 +1,9 @@
1
- require 'abstract_unit'
2
- require "#{File.dirname(__FILE__)}/../lib/active_record/schema"
1
+ require "cases/helper"
2
+ require 'active_record/schema'
3
3
 
4
- if ActiveRecord::Base.connection.supports_migrations?
4
+ if ActiveRecord::Base.connection.supports_migrations?
5
5
 
6
- class ActiveRecordSchemaTest < Test::Unit::TestCase
6
+ class ActiveRecordSchemaTest < ActiveRecord::TestCase
7
7
  self.use_transactional_fixtures = false
8
8
 
9
9
  def setup
@@ -25,8 +25,8 @@ if ActiveRecord::Base.connection.supports_migrations?
25
25
  end
26
26
 
27
27
  assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
28
- assert_nothing_raised { @connection.select_all "SELECT * FROM schema_info" }
29
- assert_equal 7, @connection.select_one("SELECT version FROM schema_info")['version'].to_i
28
+ assert_nothing_raised { @connection.select_all "SELECT * FROM schema_migrations" }
29
+ assert_equal 7, ActiveRecord::Migrator::current_version
30
30
  end
31
31
  end
32
32
 
@@ -0,0 +1,412 @@
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/project'
4
+ require 'models/company'
5
+ require 'models/topic'
6
+ require 'models/reply'
7
+ require 'models/computer'
8
+ require 'models/customer'
9
+ require 'models/order'
10
+ require 'models/post'
11
+ require 'models/author'
12
+ require 'models/tag'
13
+ require 'models/tagging'
14
+ require 'models/comment'
15
+ require 'models/sponsor'
16
+ require 'models/member'
17
+
18
+ class BelongsToAssociationsTest < ActiveRecord::TestCase
19
+ fixtures :accounts, :companies, :developers, :projects, :topics,
20
+ :developers_projects, :computers, :authors, :posts, :tags, :taggings, :comments
21
+
22
+ def test_belongs_to
23
+ Client.find(3).firm.name
24
+ assert_equal companies(:first_firm).name, Client.find(3).firm.name
25
+ assert !Client.find(3).firm.nil?, "Microsoft should have a firm"
26
+ end
27
+
28
+ def test_proxy_assignment
29
+ account = Account.find(1)
30
+ assert_nothing_raised { account.firm = account.firm }
31
+ end
32
+
33
+ def test_triple_equality
34
+ assert Client.find(3).firm === Firm
35
+ assert Firm === Client.find(3).firm
36
+ end
37
+
38
+ def test_type_mismatch
39
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
40
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
41
+ end
42
+
43
+ def test_natural_assignment
44
+ apple = Firm.create("name" => "Apple")
45
+ citibank = Account.create("credit_limit" => 10)
46
+ citibank.firm = apple
47
+ assert_equal apple.id, citibank.firm_id
48
+ end
49
+
50
+ def test_no_unexpected_aliasing
51
+ first_firm = companies(:first_firm)
52
+ another_firm = companies(:another_firm)
53
+
54
+ citibank = Account.create("credit_limit" => 10)
55
+ citibank.firm = first_firm
56
+ original_proxy = citibank.firm
57
+ citibank.firm = another_firm
58
+
59
+ assert_equal first_firm.object_id, original_proxy.target.object_id
60
+ assert_equal another_firm.object_id, citibank.firm.target.object_id
61
+ end
62
+
63
+ def test_creating_the_belonging_object
64
+ citibank = Account.create("credit_limit" => 10)
65
+ apple = citibank.create_firm("name" => "Apple")
66
+ assert_equal apple, citibank.firm
67
+ citibank.save
68
+ citibank.reload
69
+ assert_equal apple, citibank.firm
70
+ end
71
+
72
+ def test_building_the_belonging_object
73
+ citibank = Account.create("credit_limit" => 10)
74
+ apple = citibank.build_firm("name" => "Apple")
75
+ citibank.save
76
+ assert_equal apple.id, citibank.firm_id
77
+ end
78
+
79
+ def test_natural_assignment_to_nil
80
+ client = Client.find(3)
81
+ client.firm = nil
82
+ client.save
83
+ assert_nil client.firm(true)
84
+ assert_nil client.client_of
85
+ end
86
+
87
+ def test_with_different_class_name
88
+ assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
89
+ assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
90
+ end
91
+
92
+ def test_with_condition
93
+ assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
94
+ assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
95
+ end
96
+
97
+ def test_with_select
98
+ assert_equal Company.find(2).firm_with_select.attributes.size, 1
99
+ assert_equal Company.find(2, :include => :firm_with_select ).firm_with_select.attributes.size, 1
100
+ end
101
+
102
+ def test_belongs_to_counter
103
+ debate = Topic.create("title" => "debate")
104
+ assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
105
+
106
+ trash = debate.replies.create("title" => "blah!", "content" => "world around!")
107
+ assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created"
108
+
109
+ trash.destroy
110
+ assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
111
+ end
112
+
113
+ def test_belongs_to_counter_with_assigning_nil
114
+ p = Post.find(1)
115
+ c = Comment.find(1)
116
+
117
+ assert_equal p.id, c.post_id
118
+ assert_equal 2, Post.find(p.id).comments.size
119
+
120
+ c.post = nil
121
+
122
+ assert_equal 1, Post.find(p.id).comments.size
123
+ end
124
+
125
+ def test_belongs_to_counter_with_reassigning
126
+ t1 = Topic.create("title" => "t1")
127
+ t2 = Topic.create("title" => "t2")
128
+ r1 = Reply.new("title" => "r1", "content" => "r1")
129
+ r1.topic = t1
130
+
131
+ assert r1.save
132
+ assert_equal 1, Topic.find(t1.id).replies.size
133
+ assert_equal 0, Topic.find(t2.id).replies.size
134
+
135
+ r1.topic = Topic.find(t2.id)
136
+
137
+ assert r1.save
138
+ assert_equal 0, Topic.find(t1.id).replies.size
139
+ assert_equal 1, Topic.find(t2.id).replies.size
140
+
141
+ r1.topic = nil
142
+
143
+ assert_equal 0, Topic.find(t1.id).replies.size
144
+ assert_equal 0, Topic.find(t2.id).replies.size
145
+
146
+ r1.topic = t1
147
+
148
+ assert_equal 1, Topic.find(t1.id).replies.size
149
+ assert_equal 0, Topic.find(t2.id).replies.size
150
+
151
+ r1.destroy
152
+
153
+ assert_equal 0, Topic.find(t1.id).replies.size
154
+ assert_equal 0, Topic.find(t2.id).replies.size
155
+ end
156
+
157
+ def test_belongs_to_counter_after_save
158
+ topic = Topic.create!(:title => "monday night")
159
+ topic.replies.create!(:title => "re: monday night", :content => "football")
160
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
161
+
162
+ topic.save!
163
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
164
+ end
165
+
166
+ def test_belongs_to_counter_after_update_attributes
167
+ topic = Topic.create!(:title => "37s")
168
+ topic.replies.create!(:title => "re: 37s", :content => "rails")
169
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
170
+
171
+ topic.update_attributes(:title => "37signals")
172
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
173
+ end
174
+
175
+ def test_belongs_to_counter_after_save
176
+ topic = Topic.create("title" => "monday night")
177
+ topic.replies.create("title" => "re: monday night", "content" => "football")
178
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
179
+
180
+ topic.save
181
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
182
+ end
183
+
184
+ def test_belongs_to_counter_after_update_attributes
185
+ topic = Topic.create("title" => "37s")
186
+ topic.replies.create("title" => "re: 37s", "content" => "rails")
187
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
188
+
189
+ topic.update_attributes("title" => "37signals")
190
+ assert_equal 1, Topic.find(topic.id).send(:read_attribute, "replies_count")
191
+ end
192
+
193
+ def test_assignment_before_parent_saved
194
+ client = Client.find(:first)
195
+ apple = Firm.new("name" => "Apple")
196
+ client.firm = apple
197
+ assert_equal apple, client.firm
198
+ assert apple.new_record?
199
+ assert client.save
200
+ assert apple.save
201
+ assert !apple.new_record?
202
+ assert_equal apple, client.firm
203
+ assert_equal apple, client.firm(true)
204
+ end
205
+
206
+ def test_assignment_before_child_saved
207
+ final_cut = Client.new("name" => "Final Cut")
208
+ firm = Firm.find(1)
209
+ final_cut.firm = firm
210
+ assert final_cut.new_record?
211
+ assert final_cut.save
212
+ assert !final_cut.new_record?
213
+ assert !firm.new_record?
214
+ assert_equal firm, final_cut.firm
215
+ assert_equal firm, final_cut.firm(true)
216
+ end
217
+
218
+ def test_assignment_before_either_saved
219
+ final_cut = Client.new("name" => "Final Cut")
220
+ apple = Firm.new("name" => "Apple")
221
+ final_cut.firm = apple
222
+ assert final_cut.new_record?
223
+ assert apple.new_record?
224
+ assert final_cut.save
225
+ assert !final_cut.new_record?
226
+ assert !apple.new_record?
227
+ assert_equal apple, final_cut.firm
228
+ assert_equal apple, final_cut.firm(true)
229
+ end
230
+
231
+ def test_new_record_with_foreign_key_but_no_object
232
+ c = Client.new("firm_id" => 1)
233
+ assert_equal Firm.find(:first), c.firm_with_basic_id
234
+ end
235
+
236
+ def test_forgetting_the_load_when_foreign_key_enters_late
237
+ c = Client.new
238
+ assert_nil c.firm_with_basic_id
239
+
240
+ c.firm_id = 1
241
+ assert_equal Firm.find(:first), c.firm_with_basic_id
242
+ end
243
+
244
+ def test_field_name_same_as_foreign_key
245
+ computer = Computer.find(1)
246
+ assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
247
+ end
248
+
249
+ def test_counter_cache
250
+ topic = Topic.create :title => "Zoom-zoom-zoom"
251
+ assert_equal 0, topic[:replies_count]
252
+
253
+ reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
254
+ reply.topic = topic
255
+
256
+ assert_equal 1, topic.reload[:replies_count]
257
+ assert_equal 1, topic.replies.size
258
+
259
+ topic[:replies_count] = 15
260
+ assert_equal 15, topic.replies.size
261
+ end
262
+
263
+ def test_custom_counter_cache
264
+ reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
265
+ assert_equal 0, reply[:replies_count]
266
+
267
+ silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
268
+ silly.reply = reply
269
+
270
+ assert_equal 1, reply.reload[:replies_count]
271
+ assert_equal 1, reply.replies.size
272
+
273
+ reply[:replies_count] = 17
274
+ assert_equal 17, reply.replies.size
275
+ end
276
+
277
+ def test_store_two_association_with_one_save
278
+ num_orders = Order.count
279
+ num_customers = Customer.count
280
+ order = Order.new
281
+
282
+ customer1 = order.billing = Customer.new
283
+ customer2 = order.shipping = Customer.new
284
+ assert order.save
285
+ assert_equal customer1, order.billing
286
+ assert_equal customer2, order.shipping
287
+
288
+ order.reload
289
+
290
+ assert_equal customer1, order.billing
291
+ assert_equal customer2, order.shipping
292
+
293
+ assert_equal num_orders +1, Order.count
294
+ assert_equal num_customers +2, Customer.count
295
+ end
296
+
297
+
298
+ def test_store_association_in_two_relations_with_one_save
299
+ num_orders = Order.count
300
+ num_customers = Customer.count
301
+ order = Order.new
302
+
303
+ customer = order.billing = order.shipping = Customer.new
304
+ assert order.save
305
+ assert_equal customer, order.billing
306
+ assert_equal customer, order.shipping
307
+
308
+ order.reload
309
+
310
+ assert_equal customer, order.billing
311
+ assert_equal customer, order.shipping
312
+
313
+ assert_equal num_orders +1, Order.count
314
+ assert_equal num_customers +1, Customer.count
315
+ end
316
+
317
+ def test_store_association_in_two_relations_with_one_save_in_existing_object
318
+ num_orders = Order.count
319
+ num_customers = Customer.count
320
+ order = Order.create
321
+
322
+ customer = order.billing = order.shipping = Customer.new
323
+ assert order.save
324
+ assert_equal customer, order.billing
325
+ assert_equal customer, order.shipping
326
+
327
+ order.reload
328
+
329
+ assert_equal customer, order.billing
330
+ assert_equal customer, order.shipping
331
+
332
+ assert_equal num_orders +1, Order.count
333
+ assert_equal num_customers +1, Customer.count
334
+ end
335
+
336
+ def test_store_association_in_two_relations_with_one_save_in_existing_object_with_values
337
+ num_orders = Order.count
338
+ num_customers = Customer.count
339
+ order = Order.create
340
+
341
+ customer = order.billing = order.shipping = Customer.new
342
+ assert order.save
343
+ assert_equal customer, order.billing
344
+ assert_equal customer, order.shipping
345
+
346
+ order.reload
347
+
348
+ customer = order.billing = order.shipping = Customer.new
349
+
350
+ assert order.save
351
+ order.reload
352
+
353
+ assert_equal customer, order.billing
354
+ assert_equal customer, order.shipping
355
+
356
+ assert_equal num_orders +1, Order.count
357
+ assert_equal num_customers +2, Customer.count
358
+ end
359
+
360
+
361
+ def test_association_assignment_sticks
362
+ post = Post.find(:first)
363
+
364
+ author1, author2 = Author.find(:all, :limit => 2)
365
+ assert_not_nil author1
366
+ assert_not_nil author2
367
+
368
+ # make sure the association is loaded
369
+ post.author
370
+
371
+ # set the association by id, directly
372
+ post.author_id = author2.id
373
+
374
+ # save and reload
375
+ post.save!
376
+ post.reload
377
+
378
+ # the author id of the post should be the id we set
379
+ assert_equal post.author_id, author2.id
380
+ end
381
+
382
+ def test_cant_save_readonly_association
383
+ assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
384
+ assert companies(:first_client).readonly_firm.readonly?
385
+ end
386
+
387
+ def test_polymorphic_assignment_foreign_type_field_updating
388
+ # should update when assigning a saved record
389
+ sponsor = Sponsor.new
390
+ member = Member.create
391
+ sponsor.sponsorable = member
392
+ assert_equal "Member", sponsor.sponsorable_type
393
+
394
+ # should update when assigning a new record
395
+ sponsor = Sponsor.new
396
+ member = Member.new
397
+ sponsor.sponsorable = member
398
+ assert_equal "Member", sponsor.sponsorable_type
399
+ end
400
+
401
+ def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
402
+ sponsor = Sponsor.new
403
+ saved_member = Member.create
404
+ new_member = Member.new
405
+
406
+ sponsor.sponsorable = saved_member
407
+ assert_equal saved_member.id, sponsor.sponsorable_id
408
+
409
+ sponsor.sponsorable = new_member
410
+ assert_equal nil, sponsor.sponsorable_id
411
+ end
412
+ end
@@ -1,12 +1,12 @@
1
- require 'abstract_unit'
2
- require 'fixtures/post'
3
- require 'fixtures/comment'
4
- require 'fixtures/author'
5
- require 'fixtures/category'
6
- require 'fixtures/project'
7
- require 'fixtures/developer'
8
-
9
- class AssociationCallbacksTest < Test::Unit::TestCase
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/comment'
4
+ require 'models/author'
5
+ require 'models/category'
6
+ require 'models/project'
7
+ require 'models/developer'
8
+
9
+ class AssociationCallbacksTest < ActiveRecord::TestCase
10
10
  fixtures :posts, :authors, :projects, :developers
11
11
 
12
12
  def setup
@@ -94,6 +94,21 @@ class AssociationCallbacksTest < Test::Unit::TestCase
94
94
  "after_adding#{david.id}"], ar.developers_log
95
95
  end
96
96
 
97
+ def test_has_and_belongs_to_many_after_add_called_after_save
98
+ ar = projects(:active_record)
99
+ assert ar.developers_log.empty?
100
+ alice = Developer.new(:name => 'alice')
101
+ ar.developers_with_callbacks << alice
102
+ assert_equal"after_adding#{alice.id}", ar.developers_log.last
103
+
104
+ bob = ar.developers_with_callbacks.create(:name => 'bob')
105
+ assert_equal "after_adding#{bob.id}", ar.developers_log.last
106
+
107
+ ar.developers_with_callbacks.build(:name => 'charlie')
108
+ assert_equal "after_adding<new>", ar.developers_log.last
109
+ end
110
+
111
+
97
112
  def test_has_and_belongs_to_many_remove_callback
98
113
  david = developers(:david)
99
114
  jamis = developers(:jamis)
@@ -144,4 +159,3 @@ class AssociationCallbacksTest < Test::Unit::TestCase
144
159
  assert !@david.unchangable_posts.include?(@authorless)
145
160
  end
146
161
  end
147
-