ibm_db 3.0.0-x86-mingw32 → 3.0.1-x86-mingw32

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/OLD/extconf.rb +264 -0
  8. data/ext/{extconf_MacOS.rb → OLD/extconf_MacOS.rb} +269 -269
  9. data/ext/extconf.rb +291 -264
  10. data/ext/ibm_db.c +2 -2
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4 -4
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +115 -115
  19. data/test/active_record/connection_adapters/fake_adapter.rb +46 -0
  20. data/test/assets/example.log +1 -0
  21. data/test/assets/flowers.jpg +0 -0
  22. data/test/assets/test.txt +1 -0
  23. data/test/cases/adapter_test.rb +261 -207
  24. data/test/cases/aggregations_test.rb +158 -0
  25. data/test/cases/ar_schema_test.rb +161 -0
  26. data/test/cases/associations/association_scope_test.rb +21 -0
  27. data/test/cases/associations/belongs_to_associations_test.rb +1029 -711
  28. data/test/cases/associations/callbacks_test.rb +192 -0
  29. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -181
  30. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -0
  31. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  32. data/test/cases/associations/eager_load_nested_include_test.rb +128 -0
  33. data/test/cases/associations/eager_singularization_test.rb +148 -0
  34. data/test/cases/associations/eager_test.rb +1411 -0
  35. data/test/cases/associations/extension_test.rb +82 -0
  36. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +932 -851
  37. data/test/cases/associations/has_many_associations_test.rb +2162 -0
  38. data/test/cases/associations/has_many_through_associations_test.rb +1204 -0
  39. data/test/cases/associations/has_one_associations_test.rb +610 -0
  40. data/test/cases/associations/has_one_through_associations_test.rb +380 -0
  41. data/test/cases/associations/inner_join_association_test.rb +139 -0
  42. data/test/cases/associations/inverse_associations_test.rb +693 -0
  43. data/test/cases/associations/join_model_test.rb +754 -743
  44. data/test/cases/associations/nested_through_associations_test.rb +579 -0
  45. data/test/cases/associations/required_test.rb +82 -0
  46. data/test/cases/associations_test.rb +380 -0
  47. data/test/cases/attribute_decorators_test.rb +125 -0
  48. data/test/cases/attribute_methods/read_test.rb +60 -0
  49. data/test/cases/attribute_methods/serialization_test.rb +29 -0
  50. data/test/cases/attribute_methods_test.rb +952 -822
  51. data/test/cases/attribute_set_test.rb +200 -0
  52. data/test/cases/attribute_test.rb +180 -0
  53. data/test/cases/attributes_test.rb +136 -0
  54. data/test/cases/autosave_association_test.rb +1595 -0
  55. data/test/cases/base_test.rb +1638 -2133
  56. data/test/cases/batches_test.rb +212 -0
  57. data/test/cases/binary_test.rb +52 -0
  58. data/test/cases/bind_parameter_test.rb +100 -0
  59. data/test/cases/calculations_test.rb +646 -482
  60. data/test/cases/callbacks_test.rb +543 -0
  61. data/test/cases/clone_test.rb +40 -0
  62. data/test/cases/coders/yaml_column_test.rb +63 -0
  63. data/test/cases/column_alias_test.rb +17 -0
  64. data/test/cases/column_definition_test.rb +123 -0
  65. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -0
  66. data/test/cases/connection_adapters/connection_handler_test.rb +53 -0
  67. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  68. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -0
  69. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -0
  70. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  71. data/test/cases/connection_adapters/schema_cache_test.rb +56 -0
  72. data/test/cases/connection_adapters/type_lookup_test.rb +110 -0
  73. data/test/cases/connection_management_test.rb +122 -0
  74. data/test/cases/connection_pool_test.rb +346 -0
  75. data/test/cases/connection_specification/resolver_test.rb +116 -0
  76. data/test/cases/core_test.rb +112 -0
  77. data/test/cases/counter_cache_test.rb +209 -0
  78. data/test/cases/custom_locking_test.rb +17 -0
  79. data/test/cases/database_statements_test.rb +19 -0
  80. data/test/cases/date_time_test.rb +61 -0
  81. data/test/cases/defaults_test.rb +223 -0
  82. data/test/cases/dirty_test.rb +775 -0
  83. data/test/cases/disconnected_test.rb +28 -0
  84. data/test/cases/dup_test.rb +157 -0
  85. data/test/cases/enum_test.rb +290 -0
  86. data/test/cases/explain_subscriber_test.rb +64 -0
  87. data/test/cases/explain_test.rb +76 -0
  88. data/test/cases/finder_respond_to_test.rb +60 -0
  89. data/test/cases/finder_test.rb +1166 -0
  90. data/test/cases/fixture_set/file_test.rb +138 -0
  91. data/test/cases/fixtures_test.rb +897 -0
  92. data/test/cases/forbidden_attributes_protection_test.rb +99 -0
  93. data/test/cases/habtm_destroy_order_test.rb +61 -0
  94. data/test/cases/helper.rb +210 -0
  95. data/test/cases/hot_compatibility_test.rb +54 -0
  96. data/test/cases/i18n_test.rb +45 -0
  97. data/test/cases/inheritance_test.rb +375 -0
  98. data/test/cases/integration_test.rb +139 -0
  99. data/test/cases/invalid_connection_test.rb +22 -0
  100. data/test/cases/invalid_date_test.rb +32 -0
  101. data/test/cases/invertible_migration_test.rb +295 -0
  102. data/test/cases/json_serialization_test.rb +302 -0
  103. data/test/cases/locking_test.rb +477 -0
  104. data/test/cases/log_subscriber_test.rb +136 -0
  105. data/test/cases/migration/change_schema_test - Copy.rb +448 -0
  106. data/test/cases/migration/change_schema_test.rb +472 -0
  107. data/test/cases/migration/change_table_test.rb +224 -0
  108. data/test/cases/migration/column_attributes_test.rb +192 -0
  109. data/test/cases/migration/column_positioning_test.rb +56 -0
  110. data/test/cases/migration/columns_test.rb +304 -0
  111. data/test/cases/migration/command_recorder_test.rb +305 -0
  112. data/test/cases/migration/create_join_table_test.rb +148 -0
  113. data/test/cases/migration/foreign_key_test - Changed.rb +325 -0
  114. data/test/cases/migration/foreign_key_test.rb +360 -0
  115. data/test/cases/migration/helper.rb +39 -0
  116. data/test/cases/migration/index_test.rb +216 -0
  117. data/test/cases/migration/logger_test.rb +36 -0
  118. data/test/cases/migration/pending_migrations_test.rb +53 -0
  119. data/test/cases/migration/references_foreign_key_test.rb +214 -0
  120. data/test/cases/migration/references_index_test.rb +101 -0
  121. data/test/cases/migration/references_statements_test.rb +116 -0
  122. data/test/cases/migration/rename_table_test.rb +93 -0
  123. data/test/cases/migration/table_and_index_test.rb +24 -0
  124. data/test/cases/migration_test.rb +959 -2408
  125. data/test/cases/migrator_test.rb +388 -0
  126. data/test/cases/mixin_test.rb +70 -0
  127. data/test/cases/modules_test.rb +173 -0
  128. data/test/cases/multiparameter_attributes_test.rb +350 -0
  129. data/test/cases/multiple_db_test.rb +115 -0
  130. data/test/cases/nested_attributes_test.rb +1057 -0
  131. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -0
  132. data/test/cases/persistence_test.rb +909 -642
  133. data/test/cases/pooled_connections_test.rb +81 -0
  134. data/test/cases/primary_keys_test.rb +237 -0
  135. data/test/cases/query_cache_test.rb +326 -257
  136. data/test/cases/quoting_test.rb +156 -0
  137. data/test/cases/readonly_test.rb +118 -0
  138. data/test/cases/reaper_test.rb +85 -0
  139. data/test/cases/reflection_test.rb +454 -0
  140. data/test/cases/relation/delegation_test.rb +68 -0
  141. data/test/cases/relation/merging_test.rb +161 -0
  142. data/test/cases/relation/mutation_test.rb +165 -0
  143. data/test/cases/relation/predicate_builder_test.rb +14 -0
  144. data/test/cases/relation/where_chain_test.rb +181 -0
  145. data/test/cases/relation/where_test.rb +300 -0
  146. data/test/cases/relation/where_test2.rb +36 -0
  147. data/test/cases/relation_test.rb +297 -0
  148. data/test/cases/relations_test.rb +1815 -1182
  149. data/test/cases/reload_models_test.rb +22 -0
  150. data/test/cases/result_test.rb +80 -0
  151. data/test/cases/sanitize_test.rb +83 -0
  152. data/test/cases/schema_dumper_test.rb +463 -256
  153. data/test/cases/scoping/default_scoping_test.rb +454 -0
  154. data/test/cases/scoping/named_scoping_test.rb +524 -0
  155. data/test/cases/scoping/relation_scoping_test.rb +357 -0
  156. data/test/cases/serialization_test.rb +104 -0
  157. data/test/cases/serialized_attribute_test.rb +277 -0
  158. data/test/cases/statement_cache_test.rb +98 -0
  159. data/test/cases/store_test.rb +194 -0
  160. data/test/cases/tasks/database_tasks_test.rb +396 -0
  161. data/test/cases/tasks/mysql_rake_test.rb +311 -0
  162. data/test/cases/tasks/postgresql_rake_test.rb +245 -0
  163. data/test/cases/tasks/sqlite_rake_test.rb +193 -0
  164. data/test/cases/test_case.rb +123 -0
  165. data/test/cases/timestamp_test.rb +468 -0
  166. data/test/cases/transaction_callbacks_test.rb +452 -300
  167. data/test/cases/transaction_isolation_test.rb +106 -0
  168. data/test/cases/transactions_test.rb +817 -0
  169. data/test/cases/type/decimal_test.rb +51 -0
  170. data/test/cases/type/integer_test.rb +121 -0
  171. data/test/cases/type/string_test.rb +36 -0
  172. data/test/cases/type/type_map_test.rb +177 -0
  173. data/test/cases/type/unsigned_integer_test.rb +18 -0
  174. data/test/cases/types_test.rb +141 -0
  175. data/test/cases/unconnected_test.rb +33 -0
  176. data/test/cases/validations/association_validation_test.rb +86 -0
  177. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -0
  178. data/test/cases/validations/i18n_validation_test.rb +90 -0
  179. data/test/cases/validations/length_validation_test.rb +47 -0
  180. data/test/cases/validations/presence_validation_test.rb +68 -0
  181. data/test/cases/validations/uniqueness_validation_test.rb +434 -299
  182. data/test/cases/validations_repair_helper.rb +23 -0
  183. data/test/cases/validations_test.rb +165 -0
  184. data/test/cases/view_test.rb +113 -0
  185. data/test/cases/xml_serialization_test.rb +457 -408
  186. data/test/cases/yaml_serialization_test.rb +86 -0
  187. data/test/config.rb +5 -0
  188. data/test/config.yml +154 -154
  189. data/test/connections/native_ibm_db/connection.rb +43 -43
  190. data/test/fixtures/accounts.yml +29 -0
  191. data/test/fixtures/admin/accounts.yml +2 -0
  192. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  193. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  194. data/test/fixtures/admin/users.yml +10 -0
  195. data/test/fixtures/all/admin +1 -0
  196. data/test/fixtures/all/developers.yml +0 -0
  197. data/test/fixtures/all/people.yml +0 -0
  198. data/test/fixtures/all/tasks.yml +0 -0
  199. data/test/fixtures/author_addresses.yml +18 -0
  200. data/test/fixtures/author_favorites.yml +4 -0
  201. data/test/fixtures/authors.yml +23 -0
  202. data/test/fixtures/binaries.yml +133 -0
  203. data/test/fixtures/books.yml +11 -0
  204. data/test/fixtures/bulbs.yml +5 -0
  205. data/test/fixtures/cars.yml +9 -0
  206. data/test/fixtures/categories.yml +19 -0
  207. data/test/fixtures/categories/special_categories.yml +9 -0
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  209. data/test/fixtures/categories_ordered.yml +7 -0
  210. data/test/fixtures/categories_posts.yml +31 -0
  211. data/test/fixtures/categorizations.yml +23 -0
  212. data/test/fixtures/clubs.yml +8 -0
  213. data/test/fixtures/collections.yml +3 -0
  214. data/test/fixtures/colleges.yml +3 -0
  215. data/test/fixtures/comments.yml +65 -0
  216. data/test/fixtures/companies.yml +67 -0
  217. data/test/fixtures/computers.yml +10 -0
  218. data/test/fixtures/courses.yml +8 -0
  219. data/test/fixtures/customers.yml +26 -0
  220. data/test/fixtures/dashboards.yml +6 -0
  221. data/test/fixtures/developers.yml +22 -0
  222. data/test/fixtures/developers_projects.yml +17 -0
  223. data/test/fixtures/dog_lovers.yml +7 -0
  224. data/test/fixtures/dogs.yml +4 -0
  225. data/test/fixtures/doubloons.yml +3 -0
  226. data/test/fixtures/edges.yml +5 -0
  227. data/test/fixtures/entrants.yml +14 -0
  228. data/test/fixtures/essays.yml +6 -0
  229. data/test/fixtures/faces.yml +11 -0
  230. data/test/fixtures/fk_test_has_fk.yml +3 -0
  231. data/test/fixtures/fk_test_has_pk.yml +2 -0
  232. data/test/fixtures/friendships.yml +4 -0
  233. data/test/fixtures/funny_jokes.yml +10 -0
  234. data/test/fixtures/interests.yml +33 -0
  235. data/test/fixtures/items.yml +3 -0
  236. data/test/fixtures/jobs.yml +7 -0
  237. data/test/fixtures/legacy_things.yml +3 -0
  238. data/test/fixtures/mateys.yml +4 -0
  239. data/test/fixtures/member_details.yml +8 -0
  240. data/test/fixtures/member_types.yml +6 -0
  241. data/test/fixtures/members.yml +11 -0
  242. data/test/fixtures/memberships.yml +34 -0
  243. data/test/fixtures/men.yml +5 -0
  244. data/test/fixtures/minimalistics.yml +2 -0
  245. data/test/fixtures/minivans.yml +5 -0
  246. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  247. data/test/fixtures/mixins.yml +29 -0
  248. data/test/fixtures/movies.yml +7 -0
  249. data/test/fixtures/naked/csv/accounts.csv +1 -0
  250. data/test/fixtures/naked/yml/accounts.yml +1 -0
  251. data/test/fixtures/naked/yml/companies.yml +1 -0
  252. data/test/fixtures/naked/yml/courses.yml +1 -0
  253. data/test/fixtures/organizations.yml +5 -0
  254. data/test/fixtures/other_topics.yml +42 -0
  255. data/test/fixtures/owners.yml +9 -0
  256. data/test/fixtures/parrots.yml +27 -0
  257. data/test/fixtures/parrots_pirates.yml +7 -0
  258. data/test/fixtures/people.yml +24 -0
  259. data/test/fixtures/peoples_treasures.yml +3 -0
  260. data/test/fixtures/pets.yml +19 -0
  261. data/test/fixtures/pirates.yml +12 -0
  262. data/test/fixtures/posts.yml +80 -0
  263. data/test/fixtures/price_estimates.yml +7 -0
  264. data/test/fixtures/products.yml +4 -0
  265. data/test/fixtures/projects.yml +7 -0
  266. data/test/fixtures/randomly_named_a9.yml +7 -0
  267. data/test/fixtures/ratings.yml +14 -0
  268. data/test/fixtures/readers.yml +11 -0
  269. data/test/fixtures/references.yml +17 -0
  270. data/test/fixtures/reserved_words/distinct.yml +5 -0
  271. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  272. data/test/fixtures/reserved_words/group.yml +14 -0
  273. data/test/fixtures/reserved_words/select.yml +8 -0
  274. data/test/fixtures/reserved_words/values.yml +7 -0
  275. data/test/fixtures/ships.yml +6 -0
  276. data/test/fixtures/speedometers.yml +8 -0
  277. data/test/fixtures/sponsors.yml +12 -0
  278. data/test/fixtures/string_key_objects.yml +7 -0
  279. data/test/fixtures/subscribers.yml +11 -0
  280. data/test/fixtures/subscriptions.yml +12 -0
  281. data/test/fixtures/taggings.yml +78 -0
  282. data/test/fixtures/tags.yml +11 -0
  283. data/test/fixtures/tasks.yml +7 -0
  284. data/test/fixtures/teapots.yml +3 -0
  285. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  286. data/test/fixtures/to_be_linked/users.yml +10 -0
  287. data/test/fixtures/topics.yml +49 -0
  288. data/test/fixtures/toys.yml +14 -0
  289. data/test/fixtures/traffic_lights.yml +10 -0
  290. data/test/fixtures/treasures.yml +10 -0
  291. data/test/fixtures/uuid_children.yml +3 -0
  292. data/test/fixtures/uuid_parents.yml +2 -0
  293. data/test/fixtures/variants.yml +4 -0
  294. data/test/fixtures/vegetables.yml +20 -0
  295. data/test/fixtures/vertices.yml +4 -0
  296. data/test/fixtures/warehouse_things.yml +3 -0
  297. data/test/fixtures/zines.yml +5 -0
  298. data/test/ibm_db_test.rb +24 -24
  299. data/test/migrations/10_urban/9_add_expressions.rb +11 -0
  300. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  301. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -0
  302. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  303. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  304. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  305. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  306. data/test/migrations/rename/1_we_need_things.rb +11 -0
  307. data/test/migrations/rename/2_rename_things.rb +9 -0
  308. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -0
  309. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -0
  310. data/test/migrations/to_copy2/1_create_articles.rb +7 -0
  311. data/test/migrations/to_copy2/2_create_comments.rb +7 -0
  312. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -0
  313. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -0
  314. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -0
  315. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -0
  316. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -0
  317. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -0
  318. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  319. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  320. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -0
  321. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -0
  322. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -0
  323. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -0
  324. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -0
  325. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -0
  326. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -0
  327. data/test/models/admin.rb +5 -0
  328. data/test/models/admin/account.rb +3 -0
  329. data/test/models/admin/randomly_named_c1.rb +3 -0
  330. data/test/models/admin/user.rb +40 -0
  331. data/test/models/aircraft.rb +4 -0
  332. data/test/models/arunit2_model.rb +3 -0
  333. data/test/models/author.rb +212 -0
  334. data/test/models/auto_id.rb +4 -0
  335. data/test/models/autoloadable/extra_firm.rb +2 -0
  336. data/test/models/binary.rb +2 -0
  337. data/test/models/bird.rb +12 -0
  338. data/test/models/book.rb +18 -0
  339. data/test/models/boolean.rb +2 -0
  340. data/test/models/bulb.rb +51 -0
  341. data/test/models/cake_designer.rb +3 -0
  342. data/test/models/car.rb +26 -0
  343. data/test/models/carrier.rb +2 -0
  344. data/test/models/categorization.rb +19 -0
  345. data/test/models/category.rb +35 -0
  346. data/test/models/chef.rb +3 -0
  347. data/test/models/citation.rb +3 -0
  348. data/test/models/club.rb +23 -0
  349. data/test/models/college.rb +10 -0
  350. data/test/models/column.rb +3 -0
  351. data/test/models/column_name.rb +3 -0
  352. data/test/models/comment.rb +64 -0
  353. data/test/models/company.rb +225 -0
  354. data/test/models/company_in_module.rb +98 -0
  355. data/test/models/computer.rb +3 -0
  356. data/test/models/contact.rb +41 -0
  357. data/test/models/contract.rb +20 -0
  358. data/test/models/country.rb +7 -0
  359. data/test/models/course.rb +6 -0
  360. data/test/models/customer.rb +77 -0
  361. data/test/models/customer_carrier.rb +14 -0
  362. data/test/models/dashboard.rb +3 -0
  363. data/test/models/default.rb +2 -0
  364. data/test/models/department.rb +4 -0
  365. data/test/models/developer.rb +252 -0
  366. data/test/models/dog.rb +5 -0
  367. data/test/models/dog_lover.rb +5 -0
  368. data/test/models/doubloon.rb +12 -0
  369. data/test/models/drink_designer.rb +3 -0
  370. data/test/models/edge.rb +5 -0
  371. data/test/models/electron.rb +5 -0
  372. data/test/models/engine.rb +4 -0
  373. data/test/models/entrant.rb +3 -0
  374. data/test/models/essay.rb +5 -0
  375. data/test/models/event.rb +3 -0
  376. data/test/models/eye.rb +37 -0
  377. data/test/models/face.rb +9 -0
  378. data/test/models/friendship.rb +6 -0
  379. data/test/models/guid.rb +2 -0
  380. data/test/models/hotel.rb +6 -0
  381. data/test/models/image.rb +3 -0
  382. data/test/models/interest.rb +5 -0
  383. data/test/models/invoice.rb +4 -0
  384. data/test/models/item.rb +7 -0
  385. data/test/models/job.rb +7 -0
  386. data/test/models/joke.rb +7 -0
  387. data/test/models/keyboard.rb +3 -0
  388. data/test/models/legacy_thing.rb +3 -0
  389. data/test/models/lesson.rb +11 -0
  390. data/test/models/line_item.rb +3 -0
  391. data/test/models/liquid.rb +4 -0
  392. data/test/models/man.rb +11 -0
  393. data/test/models/matey.rb +4 -0
  394. data/test/models/member.rb +41 -0
  395. data/test/models/member_detail.rb +7 -0
  396. data/test/models/member_type.rb +3 -0
  397. data/test/models/membership.rb +35 -0
  398. data/test/models/minimalistic.rb +2 -0
  399. data/test/models/minivan.rb +9 -0
  400. data/test/models/mixed_case_monkey.rb +3 -0
  401. data/test/models/molecule.rb +6 -0
  402. data/test/models/movie.rb +5 -0
  403. data/test/models/order.rb +4 -0
  404. data/test/models/organization.rb +14 -0
  405. data/test/models/owner.rb +34 -0
  406. data/test/models/parrot.rb +29 -0
  407. data/test/models/person.rb +143 -0
  408. data/test/models/personal_legacy_thing.rb +4 -0
  409. data/test/models/pet.rb +15 -0
  410. data/test/models/pirate.rb +92 -0
  411. data/test/models/possession.rb +3 -0
  412. data/test/models/post.rb +264 -0
  413. data/test/models/price_estimate.rb +4 -0
  414. data/test/models/professor.rb +5 -0
  415. data/test/models/project.rb +29 -0
  416. data/test/models/publisher.rb +2 -0
  417. data/test/models/publisher/article.rb +4 -0
  418. data/test/models/publisher/magazine.rb +3 -0
  419. data/test/models/randomly_named_c1.rb +3 -0
  420. data/test/models/rating.rb +4 -0
  421. data/test/models/reader.rb +23 -0
  422. data/test/models/record.rb +2 -0
  423. data/test/models/reference.rb +22 -0
  424. data/test/models/reply.rb +61 -0
  425. data/test/models/ship.rb +33 -0
  426. data/test/models/ship_part.rb +8 -0
  427. data/test/models/shop.rb +17 -0
  428. data/test/models/shop_account.rb +6 -0
  429. data/test/models/speedometer.rb +6 -0
  430. data/test/models/sponsor.rb +7 -0
  431. data/test/models/string_key_object.rb +3 -0
  432. data/test/models/student.rb +4 -0
  433. data/test/models/subject.rb +16 -0
  434. data/test/models/subscriber.rb +8 -0
  435. data/test/models/subscription.rb +4 -0
  436. data/test/models/tag.rb +7 -0
  437. data/test/models/tagging.rb +13 -0
  438. data/test/models/task.rb +5 -0
  439. data/test/models/topic.rb +124 -0
  440. data/test/models/toy.rb +6 -0
  441. data/test/models/traffic_light.rb +4 -0
  442. data/test/models/treasure.rb +14 -0
  443. data/test/models/treaty.rb +7 -0
  444. data/test/models/tyre.rb +11 -0
  445. data/test/models/uuid_child.rb +3 -0
  446. data/test/models/uuid_parent.rb +3 -0
  447. data/test/models/vegetables.rb +24 -0
  448. data/test/models/vehicle.rb +7 -0
  449. data/test/models/vertex.rb +9 -0
  450. data/test/models/warehouse_thing.rb +5 -5
  451. data/test/models/wheel.rb +3 -0
  452. data/test/models/without_table.rb +3 -0
  453. data/test/models/zine.rb +3 -0
  454. data/test/schema/mysql2_specific_schema.rb +58 -0
  455. data/test/schema/mysql_specific_schema.rb +70 -0
  456. data/test/schema/oracle_specific_schema.rb +43 -0
  457. data/test/schema/postgresql_specific_schema.rb +202 -0
  458. data/test/schema/schema.rb +938 -751
  459. data/test/schema/sqlite_specific_schema.rb +22 -0
  460. data/test/support/config.rb +43 -0
  461. data/test/support/connection.rb +22 -0
  462. data/test/support/connection_helper.rb +14 -0
  463. data/test/support/ddl_helper.rb +8 -0
  464. data/test/support/schema_dumping_helper.rb +20 -0
  465. metadata +444 -18
@@ -0,0 +1,158 @@
1
+ require "cases/helper"
2
+ require 'models/customer'
3
+
4
+ class AggregationsTest < ActiveRecord::TestCase
5
+ fixtures :customers
6
+
7
+ def test_find_single_value_object
8
+ assert_equal 50, customers(:david).balance.amount
9
+ assert_kind_of Money, customers(:david).balance
10
+ assert_equal 300, customers(:david).balance.exchange_to("DKK").amount
11
+ end
12
+
13
+ def test_find_multiple_value_object
14
+ assert_equal customers(:david).address_street, customers(:david).address.street
15
+ assert(
16
+ customers(:david).address.close_to?(Address.new("Different Street", customers(:david).address_city, customers(:david).address_country))
17
+ )
18
+ end
19
+
20
+ def test_change_single_value_object
21
+ customers(:david).balance = Money.new(100)
22
+ customers(:david).save
23
+ assert_equal 100, customers(:david).reload.balance.amount
24
+ end
25
+
26
+ def test_immutable_value_objects
27
+ customers(:david).balance = Money.new(100)
28
+ assert_raise(RuntimeError) { customers(:david).balance.instance_eval { @amount = 20 } }
29
+ end
30
+
31
+ def test_inferred_mapping
32
+ assert_equal "35.544623640962634", customers(:david).gps_location.latitude
33
+ assert_equal "-105.9309951055148", customers(:david).gps_location.longitude
34
+
35
+ customers(:david).gps_location = GpsLocation.new("39x-110")
36
+
37
+ assert_equal "39", customers(:david).gps_location.latitude
38
+ assert_equal "-110", customers(:david).gps_location.longitude
39
+
40
+ customers(:david).save
41
+
42
+ customers(:david).reload
43
+
44
+ assert_equal "39", customers(:david).gps_location.latitude
45
+ assert_equal "-110", customers(:david).gps_location.longitude
46
+ end
47
+
48
+ def test_reloaded_instance_refreshes_aggregations
49
+ assert_equal "35.544623640962634", customers(:david).gps_location.latitude
50
+ assert_equal "-105.9309951055148", customers(:david).gps_location.longitude
51
+
52
+ Customer.update_all("gps_location = '24x113'")
53
+ customers(:david).reload
54
+ assert_equal '24x113', customers(:david)['gps_location']
55
+
56
+ assert_equal GpsLocation.new('24x113'), customers(:david).gps_location
57
+ end
58
+
59
+ def test_gps_equality
60
+ assert_equal GpsLocation.new('39x110'), GpsLocation.new('39x110')
61
+ end
62
+
63
+ def test_gps_inequality
64
+ assert_not_equal GpsLocation.new('39x110'), GpsLocation.new('39x111')
65
+ end
66
+
67
+ def test_allow_nil_gps_is_nil
68
+ assert_nil customers(:zaphod).gps_location
69
+ end
70
+
71
+ def test_allow_nil_gps_set_to_nil
72
+ customers(:david).gps_location = nil
73
+ customers(:david).save
74
+ customers(:david).reload
75
+ assert_nil customers(:david).gps_location
76
+ end
77
+
78
+ def test_allow_nil_set_address_attributes_to_nil
79
+ customers(:zaphod).address = nil
80
+ assert_nil customers(:zaphod).attributes[:address_street]
81
+ assert_nil customers(:zaphod).attributes[:address_city]
82
+ assert_nil customers(:zaphod).attributes[:address_country]
83
+ end
84
+
85
+ def test_allow_nil_address_set_to_nil
86
+ customers(:zaphod).address = nil
87
+ customers(:zaphod).save
88
+ customers(:zaphod).reload
89
+ assert_nil customers(:zaphod).address
90
+ end
91
+
92
+ def test_nil_raises_error_when_allow_nil_is_false
93
+ assert_raise(NoMethodError) { customers(:david).balance = nil }
94
+ end
95
+
96
+ def test_allow_nil_address_loaded_when_only_some_attributes_are_nil
97
+ customers(:zaphod).address_street = nil
98
+ customers(:zaphod).save
99
+ customers(:zaphod).reload
100
+ assert_kind_of Address, customers(:zaphod).address
101
+ assert_nil customers(:zaphod).address.street
102
+ end
103
+
104
+ def test_nil_assignment_results_in_nil
105
+ customers(:david).gps_location = GpsLocation.new('39x111')
106
+ assert_not_nil customers(:david).gps_location
107
+ customers(:david).gps_location = nil
108
+ assert_nil customers(:david).gps_location
109
+ end
110
+
111
+ def test_nil_return_from_converter_is_respected_when_allow_nil_is_true
112
+ customers(:david).non_blank_gps_location = ""
113
+ customers(:david).save
114
+ customers(:david).reload
115
+ assert_nil customers(:david).non_blank_gps_location
116
+ ensure
117
+ Customer.gps_conversion_was_run = nil
118
+ end
119
+
120
+ def test_nil_return_from_converter_results_in_failure_when_allow_nil_is_false
121
+ assert_raises(NoMethodError) do
122
+ customers(:barney).gps_location = ""
123
+ end
124
+ end
125
+
126
+ def test_do_not_run_the_converter_when_nil_was_set
127
+ customers(:david).non_blank_gps_location = nil
128
+ assert_nil Customer.gps_conversion_was_run
129
+ end
130
+
131
+ def test_custom_constructor
132
+ assert_equal 'Barney GUMBLE', customers(:barney).fullname.to_s
133
+ assert_kind_of Fullname, customers(:barney).fullname
134
+ end
135
+
136
+ def test_custom_converter
137
+ customers(:barney).fullname = 'Barnoit Gumbleau'
138
+ assert_equal 'Barnoit GUMBLEAU', customers(:barney).fullname.to_s
139
+ assert_kind_of Fullname, customers(:barney).fullname
140
+ end
141
+ end
142
+
143
+ class OverridingAggregationsTest < ActiveRecord::TestCase
144
+ class DifferentName; end
145
+
146
+ class Person < ActiveRecord::Base
147
+ composed_of :composed_of, :mapping => %w(person_first_name first_name)
148
+ end
149
+
150
+ class DifferentPerson < Person
151
+ composed_of :composed_of, :class_name => 'DifferentName', :mapping => %w(different_person_first_name first_name)
152
+ end
153
+
154
+ def test_composed_of_aggregation_redefinition_reflections_should_differ_and_not_inherited
155
+ assert_not_equal Person.reflect_on_aggregation(:composed_of),
156
+ DifferentPerson.reflect_on_aggregation(:composed_of)
157
+ end
158
+ end
@@ -0,0 +1,161 @@
1
+ require "cases/helper"
2
+
3
+ if ActiveRecord::Base.connection.supports_migrations?
4
+
5
+ class ActiveRecordSchemaTest < ActiveRecord::TestCase
6
+ self.use_transactional_fixtures = false
7
+
8
+ setup do
9
+ @original_verbose = ActiveRecord::Migration.verbose
10
+ ActiveRecord::Migration.verbose = false
11
+ @connection = ActiveRecord::Base.connection
12
+ ActiveRecord::SchemaMigration.drop_table
13
+ end
14
+
15
+ teardown do
16
+ @connection.drop_table :fruits rescue nil
17
+ @connection.drop_table :nep_fruits rescue nil
18
+ @connection.drop_table :nep_schema_migrations rescue nil
19
+ @connection.drop_table :has_timestamps rescue nil
20
+ ActiveRecord::SchemaMigration.delete_all rescue nil
21
+ ActiveRecord::Migration.verbose = @original_verbose
22
+ end
23
+
24
+ def test_has_no_primary_key
25
+ old_primary_key_prefix_type = ActiveRecord::Base.primary_key_prefix_type
26
+ ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
27
+ assert_nil ActiveRecord::SchemaMigration.primary_key
28
+
29
+ ActiveRecord::SchemaMigration.create_table
30
+ assert_difference "ActiveRecord::SchemaMigration.count", 1 do
31
+ ActiveRecord::SchemaMigration.create version: 12
32
+ end
33
+ ensure
34
+ ActiveRecord::SchemaMigration.drop_table
35
+ ActiveRecord::Base.primary_key_prefix_type = old_primary_key_prefix_type
36
+ end
37
+
38
+ def test_schema_define
39
+ ActiveRecord::Schema.define(:version => 7) do
40
+ create_table :fruits do |t|
41
+ t.column :color, :string
42
+ t.column :fruit_size, :string # NOTE: "size" is reserved in Oracle
43
+ t.column :texture, :string
44
+ t.column :flavor, :string
45
+ end
46
+ end
47
+
48
+ assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
49
+ assert_nothing_raised { @connection.select_all "SELECT * FROM schema_migrations" }
50
+ assert_equal 7, ActiveRecord::Migrator::current_version
51
+ end
52
+
53
+ def test_schema_define_w_table_name_prefix
54
+ table_name = ActiveRecord::SchemaMigration.table_name
55
+ old_table_name_prefix = ActiveRecord::Base.table_name_prefix
56
+ ActiveRecord::Base.table_name_prefix = "nep_"
57
+ ActiveRecord::SchemaMigration.table_name = "nep_#{table_name}"
58
+ ActiveRecord::Schema.define(:version => 7) do
59
+ create_table :fruits do |t|
60
+ t.column :color, :string
61
+ t.column :fruit_size, :string # NOTE: "size" is reserved in Oracle
62
+ t.column :texture, :string
63
+ t.column :flavor, :string
64
+ end
65
+ end
66
+ assert_equal 7, ActiveRecord::Migrator::current_version
67
+ ensure
68
+ ActiveRecord::Base.table_name_prefix = old_table_name_prefix
69
+ ActiveRecord::SchemaMigration.table_name = table_name
70
+ end
71
+
72
+ def test_schema_raises_an_error_for_invalid_column_type
73
+ assert_raise NoMethodError do
74
+ ActiveRecord::Schema.define(:version => 8) do
75
+ create_table :vegetables do |t|
76
+ t.unknown :color
77
+ end
78
+ end
79
+ end
80
+ end
81
+
82
+ def test_schema_subclass
83
+ Class.new(ActiveRecord::Schema).define(:version => 9) do
84
+ create_table :fruits
85
+ end
86
+ assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
87
+ end
88
+
89
+ def test_normalize_version
90
+ assert_equal "118", ActiveRecord::SchemaMigration.normalize_migration_number("0000118")
91
+ assert_equal "002", ActiveRecord::SchemaMigration.normalize_migration_number("2")
92
+ assert_equal "017", ActiveRecord::SchemaMigration.normalize_migration_number("0017")
93
+ assert_equal "20131219224947", ActiveRecord::SchemaMigration.normalize_migration_number("20131219224947")
94
+ end
95
+
96
+ def test_timestamps_without_null_is_deprecated_on_create_table
97
+ assert_deprecated do
98
+ ActiveRecord::Schema.define do
99
+ create_table :has_timestamps do |t|
100
+ t.timestamps
101
+ end
102
+ end
103
+ end
104
+ end
105
+
106
+ def test_timestamps_without_null_is_deprecated_on_change_table
107
+ assert_deprecated do
108
+ ActiveRecord::Schema.define do
109
+ create_table :has_timestamps
110
+
111
+ change_table :has_timestamps do |t|
112
+ t.timestamps
113
+ end
114
+ end
115
+ end
116
+ end
117
+
118
+ def test_timestamps_without_null_is_deprecated_on_add_timestamps
119
+ assert_deprecated do
120
+ ActiveRecord::Schema.define do
121
+ create_table :has_timestamps
122
+ add_timestamps :has_timestamps
123
+ end
124
+ end
125
+ end
126
+
127
+ def test_no_deprecation_warning_from_timestamps_on_create_table
128
+ assert_not_deprecated do
129
+ ActiveRecord::Schema.define do
130
+ create_table :has_timestamps do |t|
131
+ t.timestamps null: true
132
+ end
133
+
134
+ drop_table :has_timestamps
135
+
136
+ create_table :has_timestamps do |t|
137
+ t.timestamps null: false
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ def test_no_deprecation_warning_from_timestamps_on_change_table
144
+ assert_not_deprecated do
145
+ ActiveRecord::Schema.define do
146
+ create_table :has_timestamps
147
+ change_table :has_timestamps do |t|
148
+ t.timestamps null: true
149
+ end
150
+
151
+ drop_table :has_timestamps
152
+
153
+ create_table :has_timestamps
154
+ change_table :has_timestamps do |t|
155
+ t.timestamps null: false, default: Time.now
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,21 @@
1
+ require 'cases/helper'
2
+ require 'models/post'
3
+ require 'models/author'
4
+
5
+ module ActiveRecord
6
+ module Associations
7
+ class AssociationScopeTest < ActiveRecord::TestCase
8
+ test 'does not duplicate conditions' do
9
+ scope = AssociationScope.scope(Author.new.association(:welcome_posts),
10
+ Author.connection)
11
+ wheres = scope.where_values.map(&:right)
12
+ binds = scope.bind_values.map(&:last)
13
+ wheres = scope.where_values.map(&:right).reject { |node|
14
+ Arel::Nodes::BindParam === node
15
+ }
16
+ assert_equal wheres.uniq, wheres
17
+ assert_equal binds.uniq, binds
18
+ end
19
+ end
20
+ end
21
+ end
@@ -1,711 +1,1029 @@
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/post'
9
- require 'models/author'
10
- require 'models/tag'
11
- require 'models/tagging'
12
- require 'models/comment'
13
- require 'models/sponsor'
14
- require 'models/member'
15
- require 'models/essay'
16
- require 'models/toy'
17
-
18
- class BelongsToAssociationsTest < ActiveRecord::TestCase
19
- fixtures :accounts, :companies, :developers, :projects, :topics,
20
- :developers_projects, :computers, :authors, :author_addresses,
21
- :posts, :tags, :taggings, :comments, :sponsors, :members
22
-
23
- def test_belongs_to
24
- Client.find(3).firm.name
25
- assert_equal companies(:first_firm).name, Client.find(3).firm.name
26
- assert_not_nil Client.find(3).firm, "Microsoft should have a firm"
27
- end
28
-
29
- def test_belongs_to_with_primary_key
30
- client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
31
- assert_equal companies(:first_firm).name, client.firm_with_primary_key.name
32
- end
33
-
34
- def test_belongs_to_with_primary_key_joins_on_correct_column
35
- sql = Client.joins(:firm_with_primary_key).to_sql
36
- if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter)
37
- assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
38
- assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
39
- elsif current_adapter?(:OracleAdapter)
40
- # on Oracle aliases are truncated to 30 characters and are quoted in uppercase
41
- assert_no_match(/"firm_with_primary_keys_compani"\."id"/i, sql)
42
- assert_match(/"firm_with_primary_keys_compani"\."name"/i, sql)
43
- elsif current_adapter?(:IBM_DBAdapter)
44
- # Quoting of column names is not necessary for IBM_DB
45
- assert_no_match(/firm_with_primary_keys_companies\.id/i, sql)
46
- assert_match(/firm_with_primary_keys_companies\.name/i, sql)
47
- else
48
- assert_no_match(/"firm_with_primary_keys_companies"\."id"/, sql)
49
- assert_match(/"firm_with_primary_keys_companies"\."name"/, sql)
50
- end
51
- end
52
-
53
- def test_proxy_assignment
54
- account = Account.find(1)
55
- assert_nothing_raised { account.firm = account.firm }
56
- end
57
-
58
- def test_type_mismatch
59
- assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
60
- assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
61
- end
62
-
63
- def test_natural_assignment
64
- apple = Firm.create("name" => "Apple")
65
- citibank = Account.create("credit_limit" => 10)
66
- citibank.firm = apple
67
- assert_equal apple.id, citibank.firm_id
68
- end
69
-
70
- def test_natural_assignment_with_primary_key
71
- apple = Firm.create("name" => "Apple")
72
- citibank = Client.create("name" => "Primary key client")
73
- citibank.firm_with_primary_key = apple
74
- assert_equal apple.name, citibank.firm_name
75
- end
76
-
77
- def test_eager_loading_with_primary_key
78
- Firm.create("name" => "Apple")
79
- Client.create("name" => "Citibank", :firm_name => "Apple")
80
- citibank_result = Client.find(:first, :conditions => {:name => "Citibank"}, :include => :firm_with_primary_key)
81
- assert citibank_result.association_cache.key?(:firm_with_primary_key)
82
- end
83
-
84
- def test_eager_loading_with_primary_key_as_symbol
85
- Firm.create("name" => "Apple")
86
- Client.create("name" => "Citibank", :firm_name => "Apple")
87
- citibank_result = Client.find(:first, :conditions => {:name => "Citibank"}, :include => :firm_with_primary_key_symbols)
88
- assert citibank_result.association_cache.key?(:firm_with_primary_key_symbols)
89
- end
90
-
91
- def test_creating_the_belonging_object
92
- citibank = Account.create("credit_limit" => 10)
93
- apple = citibank.create_firm("name" => "Apple")
94
- assert_equal apple, citibank.firm
95
- citibank.save
96
- citibank.reload
97
- assert_equal apple, citibank.firm
98
- end
99
-
100
- def test_creating_the_belonging_object_with_primary_key
101
- client = Client.create(:name => "Primary key client")
102
- apple = client.create_firm_with_primary_key("name" => "Apple")
103
- assert_equal apple, client.firm_with_primary_key
104
- client.save
105
- client.reload
106
- assert_equal apple, client.firm_with_primary_key
107
- end
108
-
109
- def test_building_the_belonging_object
110
- citibank = Account.create("credit_limit" => 10)
111
- apple = citibank.build_firm("name" => "Apple")
112
- citibank.save
113
- assert_equal apple.id, citibank.firm_id
114
- end
115
-
116
- def test_building_the_belonging_object_with_primary_key
117
- client = Client.create(:name => "Primary key client")
118
- apple = client.build_firm_with_primary_key("name" => "Apple")
119
- client.save
120
- assert_equal apple.name, client.firm_name
121
- end
122
-
123
- def test_create!
124
- client = Client.create!(:name => "Jimmy")
125
- account = client.create_account!(:credit_limit => 10)
126
- assert_equal account, client.account
127
- assert account.persisted?
128
- client.save
129
- client.reload
130
- assert_equal account, client.account
131
- end
132
-
133
- def test_failing_create!
134
- client = Client.create!(:name => "Jimmy")
135
- assert_raise(ActiveRecord::RecordInvalid) { client.create_account! }
136
- assert_not_nil client.account
137
- assert client.account.new_record?
138
- end
139
-
140
- def test_natural_assignment_to_nil
141
- client = Client.find(3)
142
- client.firm = nil
143
- client.save
144
- assert_nil client.firm(true)
145
- assert_nil client.client_of
146
- end
147
-
148
- def test_natural_assignment_to_nil_with_primary_key
149
- client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
150
- client.firm_with_primary_key = nil
151
- client.save
152
- assert_nil client.firm_with_primary_key(true)
153
- assert_nil client.client_of
154
- end
155
-
156
- def test_with_different_class_name
157
- assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
158
- assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
159
- end
160
-
161
- def test_with_condition
162
- assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
163
- assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
164
- end
165
-
166
- def test_polymorphic_association_class
167
- sponsor = Sponsor.new
168
- assert_nil sponsor.association(:sponsorable).send(:klass)
169
-
170
- sponsor.sponsorable_type = '' # the column doesn't have to be declared NOT NULL
171
- assert_nil sponsor.association(:sponsorable).send(:klass)
172
-
173
- sponsor.sponsorable = Member.new :name => "Bert"
174
- assert_equal Member, sponsor.association(:sponsorable).send(:klass)
175
- end
176
-
177
- def test_with_polymorphic_and_condition
178
- sponsor = Sponsor.create
179
- member = Member.create :name => "Bert"
180
- sponsor.sponsorable = member
181
-
182
- assert_equal member, sponsor.sponsorable
183
- assert_nil sponsor.sponsorable_with_conditions
184
- end
185
-
186
- def test_with_select
187
- assert_equal Company.find(2).firm_with_select.attributes.size, 1
188
- assert_equal Company.find(2, :include => :firm_with_select ).firm_with_select.attributes.size, 1
189
- end
190
-
191
- def test_belongs_to_counter
192
- debate = Topic.create("title" => "debate")
193
- assert_equal 0, debate.send(:read_attribute, "replies_count"), "No replies yet"
194
-
195
- trash = debate.replies.create("title" => "blah!", "content" => "world around!")
196
- assert_equal 1, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply created"
197
-
198
- trash.destroy
199
- assert_equal 0, Topic.find(debate.id).send(:read_attribute, "replies_count"), "First reply deleted"
200
- end
201
-
202
- def test_belongs_to_counter_with_assigning_nil
203
- p = Post.find(1)
204
- c = Comment.find(1)
205
-
206
- assert_equal p.id, c.post_id
207
- assert_equal 2, Post.find(p.id).comments.size
208
-
209
- c.post = nil
210
-
211
- assert_equal 1, Post.find(p.id).comments.size
212
- end
213
-
214
- def test_belongs_to_with_primary_key_counter
215
- debate = Topic.create("title" => "debate")
216
- debate2 = Topic.create("title" => "debate2")
217
- reply = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate")
218
-
219
- assert_equal 1, debate.reload.replies_count
220
- assert_equal 0, debate2.reload.replies_count
221
-
222
- reply.topic_with_primary_key = debate2
223
-
224
- assert_equal 0, debate.reload.replies_count
225
- assert_equal 1, debate2.reload.replies_count
226
-
227
- reply.topic_with_primary_key = nil
228
-
229
- assert_equal 0, debate.reload.replies_count
230
- assert_equal 0, debate2.reload.replies_count
231
- end
232
-
233
- def test_belongs_to_counter_with_reassigning
234
- t1 = Topic.create("title" => "t1")
235
- t2 = Topic.create("title" => "t2")
236
- r1 = Reply.new("title" => "r1", "content" => "r1")
237
- r1.topic = t1
238
-
239
- assert r1.save
240
- assert_equal 1, Topic.find(t1.id).replies.size
241
- assert_equal 0, Topic.find(t2.id).replies.size
242
-
243
- r1.topic = Topic.find(t2.id)
244
-
245
- assert_no_queries do
246
- r1.topic = t2
247
- end
248
-
249
- assert r1.save
250
- assert_equal 0, Topic.find(t1.id).replies.size
251
- assert_equal 1, Topic.find(t2.id).replies.size
252
-
253
- r1.topic = nil
254
-
255
- assert_equal 0, Topic.find(t1.id).replies.size
256
- assert_equal 0, Topic.find(t2.id).replies.size
257
-
258
- r1.topic = t1
259
-
260
- assert_equal 1, Topic.find(t1.id).replies.size
261
- assert_equal 0, Topic.find(t2.id).replies.size
262
-
263
- r1.destroy
264
-
265
- assert_equal 0, Topic.find(t1.id).replies.size
266
- assert_equal 0, Topic.find(t2.id).replies.size
267
- end
268
-
269
- def test_belongs_to_reassign_with_namespaced_models_and_counters
270
- t1 = Web::Topic.create("title" => "t1")
271
- t2 = Web::Topic.create("title" => "t2")
272
- r1 = Web::Reply.new("title" => "r1", "content" => "r1")
273
- r1.topic = t1
274
-
275
- assert r1.save
276
- assert_equal 1, Web::Topic.find(t1.id).replies.size
277
- assert_equal 0, Web::Topic.find(t2.id).replies.size
278
-
279
- r1.topic = Web::Topic.find(t2.id)
280
-
281
- assert r1.save
282
- assert_equal 0, Web::Topic.find(t1.id).replies.size
283
- assert_equal 1, Web::Topic.find(t2.id).replies.size
284
- end
285
-
286
- def test_belongs_to_counter_after_save
287
- topic = Topic.create!(:title => "monday night")
288
- topic.replies.create!(:title => "re: monday night", :content => "football")
289
- assert_equal 1, Topic.find(topic.id)[:replies_count]
290
-
291
- topic.save!
292
- assert_equal 1, Topic.find(topic.id)[:replies_count]
293
- end
294
-
295
- def test_belongs_to_counter_after_update_attributes
296
- topic = Topic.create!(:title => "37s")
297
- topic.replies.create!(:title => "re: 37s", :content => "rails")
298
- assert_equal 1, Topic.find(topic.id)[:replies_count]
299
-
300
- topic.update_attributes(:title => "37signals")
301
- assert_equal 1, Topic.find(topic.id)[:replies_count]
302
- end
303
-
304
- def test_belongs_to_counter_when_update_column
305
- topic = Topic.create!(:title => "37s")
306
- topic.replies.create!(:title => "re: 37s", :content => "rails")
307
- assert_equal 1, Topic.find(topic.id)[:replies_count]
308
-
309
- topic.update_column(:content, "rails is wonderfull")
310
- assert_equal 1, Topic.find(topic.id)[:replies_count]
311
- end
312
-
313
- def test_assignment_before_child_saved
314
- final_cut = Client.new("name" => "Final Cut")
315
- firm = Firm.find(1)
316
- final_cut.firm = firm
317
- assert !final_cut.persisted?
318
- assert final_cut.save
319
- assert final_cut.persisted?
320
- assert firm.persisted?
321
- assert_equal firm, final_cut.firm
322
- assert_equal firm, final_cut.firm(true)
323
- end
324
-
325
- def test_assignment_before_child_saved_with_primary_key
326
- final_cut = Client.new("name" => "Final Cut")
327
- firm = Firm.find(1)
328
- final_cut.firm_with_primary_key = firm
329
- assert !final_cut.persisted?
330
- assert final_cut.save
331
- assert final_cut.persisted?
332
- assert firm.persisted?
333
- assert_equal firm, final_cut.firm_with_primary_key
334
- assert_equal firm, final_cut.firm_with_primary_key(true)
335
- end
336
-
337
- def test_new_record_with_foreign_key_but_no_object
338
- c = Client.new("firm_id" => 1)
339
- # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
340
- assert_equal Firm.find(:first, :order => "id"), c.firm_with_basic_id
341
- end
342
-
343
- def test_setting_foreign_key_after_nil_target_loaded
344
- client = Client.new
345
- client.firm_with_basic_id
346
- client.firm_id = 1
347
-
348
- assert_equal companies(:first_firm), client.firm_with_basic_id
349
- end
350
-
351
- def test_polymorphic_setting_foreign_key_after_nil_target_loaded
352
- sponsor = Sponsor.new
353
- sponsor.sponsorable
354
- sponsor.sponsorable_id = 1
355
- sponsor.sponsorable_type = "Member"
356
-
357
- assert_equal members(:groucho), sponsor.sponsorable
358
- end
359
-
360
- def test_dont_find_target_when_foreign_key_is_null
361
- tagging = taggings(:thinking_general)
362
- queries = assert_sql { tagging.super_tag }
363
- assert_equal 0, queries.length
364
- end
365
-
366
- def test_field_name_same_as_foreign_key
367
- computer = Computer.find(1)
368
- assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
369
- end
370
-
371
- def test_counter_cache
372
- topic = Topic.create :title => "Zoom-zoom-zoom"
373
- assert_equal 0, topic[:replies_count]
374
-
375
- reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
376
- reply.topic = topic
377
-
378
- assert_equal 1, topic.reload[:replies_count]
379
- assert_equal 1, topic.replies.size
380
-
381
- topic[:replies_count] = 15
382
- assert_equal 15, topic.replies.size
383
- end
384
-
385
- def test_custom_counter_cache
386
- reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
387
- assert_equal 0, reply[:replies_count]
388
-
389
- silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
390
- silly.reply = reply
391
-
392
- assert_equal 1, reply.reload[:replies_count]
393
- assert_equal 1, reply.replies.size
394
-
395
- reply[:replies_count] = 17
396
- assert_equal 17, reply.replies.size
397
- end
398
-
399
- def test_association_assignment_sticks
400
- post = Post.find(:first)
401
-
402
- author1, author2 = Author.find(:all, :limit => 2)
403
- assert_not_nil author1
404
- assert_not_nil author2
405
-
406
- # make sure the association is loaded
407
- post.author
408
-
409
- # set the association by id, directly
410
- post.author_id = author2.id
411
-
412
- # save and reload
413
- post.save!
414
- post.reload
415
-
416
- # the author id of the post should be the id we set
417
- assert_equal post.author_id, author2.id
418
- end
419
-
420
- def test_cant_save_readonly_association
421
- assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
422
- assert companies(:first_client).readonly_firm.readonly?
423
- end
424
-
425
- def test_polymorphic_assignment_foreign_type_field_updating
426
- # should update when assigning a saved record
427
- sponsor = Sponsor.new
428
- member = Member.create
429
- sponsor.sponsorable = member
430
- assert_equal "Member", sponsor.sponsorable_type
431
-
432
- # should update when assigning a new record
433
- sponsor = Sponsor.new
434
- member = Member.new
435
- sponsor.sponsorable = member
436
- assert_equal "Member", sponsor.sponsorable_type
437
- end
438
-
439
- def test_polymorphic_assignment_with_primary_key_foreign_type_field_updating
440
- # should update when assigning a saved record
441
- essay = Essay.new
442
- writer = Author.create(:name => "David")
443
- essay.writer = writer
444
- assert_equal "Author", essay.writer_type
445
-
446
- # should update when assigning a new record
447
- essay = Essay.new
448
- writer = Author.new
449
- essay.writer = writer
450
- assert_equal "Author", essay.writer_type
451
- end
452
-
453
- def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
454
- sponsor = Sponsor.new
455
- saved_member = Member.create
456
- new_member = Member.new
457
-
458
- sponsor.sponsorable = saved_member
459
- assert_equal saved_member.id, sponsor.sponsorable_id
460
-
461
- sponsor.sponsorable = new_member
462
- assert_nil sponsor.sponsorable_id
463
- end
464
-
465
- def test_assignment_updates_foreign_id_field_for_new_and_saved_records
466
- client = Client.new
467
- saved_firm = Firm.create :name => "Saved"
468
- new_firm = Firm.new
469
-
470
- client.firm = saved_firm
471
- assert_equal saved_firm.id, client.client_of
472
-
473
- client.firm = new_firm
474
- assert_nil client.client_of
475
- end
476
-
477
- def test_polymorphic_assignment_with_primary_key_updates_foreign_id_field_for_new_and_saved_records
478
- essay = Essay.new
479
- saved_writer = Author.create(:name => "David")
480
- new_writer = Author.new
481
-
482
- essay.writer = saved_writer
483
- assert_equal saved_writer.name, essay.writer_id
484
-
485
- essay.writer = new_writer
486
- assert_nil essay.writer_id
487
- end
488
-
489
- def test_belongs_to_proxy_should_not_respond_to_private_methods
490
- assert_raise(NoMethodError) { companies(:first_firm).private_method }
491
- assert_raise(NoMethodError) { companies(:second_client).firm.private_method }
492
- end
493
-
494
- def test_belongs_to_proxy_should_respond_to_private_methods_via_send
495
- companies(:first_firm).send(:private_method)
496
- companies(:second_client).firm.send(:private_method)
497
- end
498
-
499
- def test_save_of_record_with_loaded_belongs_to
500
- @account = companies(:first_firm).account
501
-
502
- assert_nothing_raised do
503
- Account.find(@account.id).save!
504
- Account.find(@account.id, :include => :firm).save!
505
- end
506
-
507
- @account.firm.delete
508
-
509
- assert_nothing_raised do
510
- Account.find(@account.id).save!
511
- Account.find(@account.id, :include => :firm).save!
512
- end
513
- end
514
-
515
- def test_dependent_delete_and_destroy_with_belongs_to
516
- author_address = author_addresses(:david_address)
517
- author_address_extra = author_addresses(:david_address_extra)
518
- assert_equal [], AuthorAddress.destroyed_author_address_ids
519
-
520
- assert_difference "AuthorAddress.count", -2 do
521
- authors(:david).destroy
522
- end
523
-
524
- assert_equal [], AuthorAddress.find_all_by_id([author_address.id, author_address_extra.id])
525
- assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids
526
- end
527
-
528
- def test_invalid_belongs_to_dependent_option_nullify_raises_exception
529
- assert_raise ArgumentError do
530
- Author.belongs_to :special_author_address, :dependent => :nullify
531
- end
532
- end
533
-
534
- def test_invalid_belongs_to_dependent_option_restrict_raises_exception
535
- assert_raise ArgumentError do
536
- Author.belongs_to :special_author_address, :dependent => :restrict
537
- end
538
- end
539
-
540
- def test_attributes_are_being_set_when_initialized_from_belongs_to_association_with_where_clause
541
- new_firm = accounts(:signals37).build_firm(:name => 'Apple')
542
- assert_equal new_firm.name, "Apple"
543
- end
544
-
545
- def test_reassigning_the_parent_id_updates_the_object
546
- client = companies(:second_client)
547
-
548
- client.firm
549
- client.firm_with_condition
550
- firm_proxy = client.send(:association_instance_get, :firm)
551
- firm_with_condition_proxy = client.send(:association_instance_get, :firm_with_condition)
552
-
553
- assert !firm_proxy.stale_target?
554
- assert !firm_with_condition_proxy.stale_target?
555
- assert_equal companies(:first_firm), client.firm
556
- assert_equal companies(:first_firm), client.firm_with_condition
557
-
558
- client.client_of = companies(:another_firm).id
559
-
560
- assert firm_proxy.stale_target?
561
- assert firm_with_condition_proxy.stale_target?
562
- assert_equal companies(:another_firm), client.firm
563
- assert_equal companies(:another_firm), client.firm_with_condition
564
- end
565
-
566
- def test_polymorphic_reassignment_of_associated_id_updates_the_object
567
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
568
-
569
- sponsor.sponsorable
570
- proxy = sponsor.send(:association_instance_get, :sponsorable)
571
-
572
- assert !proxy.stale_target?
573
- assert_equal members(:groucho), sponsor.sponsorable
574
-
575
- sponsor.sponsorable_id = members(:some_other_guy).id
576
-
577
- assert proxy.stale_target?
578
- assert_equal members(:some_other_guy), sponsor.sponsorable
579
- end
580
-
581
- def test_polymorphic_reassignment_of_associated_type_updates_the_object
582
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
583
-
584
- sponsor.sponsorable
585
- proxy = sponsor.send(:association_instance_get, :sponsorable)
586
-
587
- assert !proxy.stale_target?
588
- assert_equal members(:groucho), sponsor.sponsorable
589
-
590
- sponsor.sponsorable_type = 'Firm'
591
-
592
- assert proxy.stale_target?
593
- assert_equal companies(:first_firm), sponsor.sponsorable
594
- end
595
-
596
- def test_reloading_association_with_key_change
597
- client = companies(:second_client)
598
- firm = client.association(:firm)
599
-
600
- client.firm = companies(:another_firm)
601
- firm.reload
602
- assert_equal companies(:another_firm), firm.target
603
-
604
- client.client_of = companies(:first_firm).id
605
- firm.reload
606
- assert_equal companies(:first_firm), firm.target
607
- end
608
-
609
- def test_polymorphic_counter_cache
610
- tagging = taggings(:welcome_general)
611
- post = posts(:welcome)
612
- comment = comments(:greetings)
613
-
614
- assert_difference lambda { post.reload.taggings_count }, -1 do
615
- assert_difference 'comment.reload.taggings_count', +1 do
616
- tagging.taggable = comment
617
- end
618
- end
619
- end
620
-
621
- def test_polymorphic_with_custom_foreign_type
622
- sponsor = sponsors(:moustache_club_sponsor_for_groucho)
623
- groucho = members(:groucho)
624
- other = members(:some_other_guy)
625
-
626
- assert_equal groucho, sponsor.sponsorable
627
- assert_equal groucho, sponsor.thing
628
-
629
- sponsor.thing = other
630
-
631
- assert_equal other, sponsor.sponsorable
632
- assert_equal other, sponsor.thing
633
-
634
- sponsor.sponsorable = groucho
635
-
636
- assert_equal groucho, sponsor.sponsorable
637
- assert_equal groucho, sponsor.thing
638
- end
639
-
640
- def test_build_with_conditions
641
- client = companies(:second_client)
642
- firm = client.build_bob_firm
643
-
644
- assert_equal "Bob", firm.name
645
- end
646
-
647
- def test_create_with_conditions
648
- client = companies(:second_client)
649
- firm = client.create_bob_firm
650
-
651
- assert_equal "Bob", firm.name
652
- end
653
-
654
- def test_create_bang_with_conditions
655
- client = companies(:second_client)
656
- firm = client.create_bob_firm!
657
-
658
- assert_equal "Bob", firm.name
659
- end
660
-
661
- def test_build_with_block
662
- client = Client.create(:name => 'Client Company')
663
-
664
- firm = client.build_firm{ |f| f.name = 'Agency Company' }
665
- assert_equal 'Agency Company', firm.name
666
- end
667
-
668
- def test_create_with_block
669
- client = Client.create(:name => 'Client Company')
670
-
671
- firm = client.create_firm{ |f| f.name = 'Agency Company' }
672
- assert_equal 'Agency Company', firm.name
673
- end
674
-
675
- def test_create_bang_with_block
676
- client = Client.create(:name => 'Client Company')
677
-
678
- firm = client.create_firm!{ |f| f.name = 'Agency Company' }
679
- assert_equal 'Agency Company', firm.name
680
- end
681
-
682
- def test_should_set_foreign_key_on_create_association
683
- client = Client.create! :name => "fuu"
684
-
685
- firm = client.create_firm :name => "baa"
686
- assert_equal firm.id, client.client_of
687
- end
688
-
689
- def test_should_set_foreign_key_on_create_association!
690
- client = Client.create! :name => "fuu"
691
-
692
- firm = client.create_firm! :name => "baa"
693
- assert_equal firm.id, client.client_of
694
- end
695
-
696
- def test_self_referential_belongs_to_with_counter_cache_assigning_nil
697
- comment = Comment.create! :post => posts(:thinking), :body => "fuu"
698
- comment.parent = nil
699
- comment.save!
700
-
701
- assert_equal nil, comment.reload.parent
702
- assert_equal 0, comments(:greetings).reload.children_count
703
- end
704
-
705
- def test_polymorphic_with_custom_primary_key
706
- toy = Toy.create!
707
- sponsor = Sponsor.create!(:sponsorable => toy)
708
-
709
- assert_equal toy, sponsor.reload.sponsorable
710
- end
711
- end
1
+ require 'cases/helper'
2
+ require 'models/developer'
3
+ require 'models/computer'
4
+ require 'models/project'
5
+ require 'models/company'
6
+ require 'models/topic'
7
+ require 'models/reply'
8
+ require 'models/computer'
9
+ require 'models/post'
10
+ require 'models/author'
11
+ require 'models/tag'
12
+ require 'models/tagging'
13
+ require 'models/comment'
14
+ require 'models/sponsor'
15
+ require 'models/member'
16
+ require 'models/essay'
17
+ require 'models/toy'
18
+ require 'models/invoice'
19
+ require 'models/line_item'
20
+ require 'models/column'
21
+ require 'models/record'
22
+ require 'models/admin'
23
+ require 'models/admin/user'
24
+ require 'models/ship'
25
+ require 'models/treasure'
26
+ require 'models/parrot'
27
+
28
+ class BelongsToAssociationsTest < ActiveRecord::TestCase
29
+ fixtures :accounts, :companies, :developers, :projects, :topics,
30
+ :developers_projects, :computers, :authors, :author_addresses,
31
+ :posts, :tags, :taggings, :comments, :sponsors, :members
32
+
33
+ def test_belongs_to
34
+ firm = Client.find(3).firm
35
+ assert_not_nil firm
36
+ assert_equal companies(:first_firm).name, firm.name
37
+ end
38
+
39
+ def test_belongs_to_does_not_use_order_by
40
+ ActiveRecord::SQLCounter.clear_log
41
+ Client.find(3).firm
42
+ ensure
43
+ assert ActiveRecord::SQLCounter.log_all.all? { |sql| /order by/i !~ sql }, 'ORDER BY was used in the query'
44
+ end
45
+
46
+ def test_belongs_to_with_primary_key
47
+ client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
48
+ assert_equal companies(:first_firm).name, client.firm_with_primary_key.name
49
+ end
50
+
51
+ def test_belongs_to_with_primary_key_joins_on_correct_column
52
+ sql = Client.joins(:firm_with_primary_key).to_sql
53
+ if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
54
+ assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql)
55
+ assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql)
56
+ elsif current_adapter?(:OracleAdapter)
57
+ # on Oracle aliases are truncated to 30 characters and are quoted in uppercase
58
+ assert_no_match(/"firm_with_primary_keys_compani"\."id"/i, sql)
59
+ assert_match(/"firm_with_primary_keys_compani"\."name"/i, sql)
60
+ elsif current_adapter?(:IBM_DBAdapter)
61
+ # Quoting of column names is not necessary for IBM_DB
62
+ assert_no_match(/firm_with_primary_keys_companies\.id/i, sql)
63
+ assert_match(/firm_with_primary_keys_companies\.name/i, sql)
64
+ else
65
+ assert_no_match(/"firm_with_primary_keys_companies"\."id"/, sql)
66
+ assert_match(/"firm_with_primary_keys_companies"\."name"/, sql)
67
+ end
68
+ end
69
+
70
+ def test_default_scope_on_relations_is_not_cached
71
+ counter = 0
72
+
73
+ comments = Class.new(ActiveRecord::Base) {
74
+ self.table_name = 'comments'
75
+ self.inheritance_column = 'not_there'
76
+
77
+ posts = Class.new(ActiveRecord::Base) {
78
+ self.table_name = 'posts'
79
+ self.inheritance_column = 'not_there'
80
+
81
+ default_scope -> {
82
+ counter += 1
83
+ where("id = :inc", :inc => counter)
84
+ }
85
+
86
+ has_many :comments, :anonymous_class => comments
87
+ }
88
+ belongs_to :post, :anonymous_class => posts, :inverse_of => false
89
+ }
90
+
91
+ assert_equal 0, counter
92
+ comment = comments.first
93
+ assert_equal 0, counter
94
+ sql = capture_sql { comment.post }
95
+ comment.reload
96
+ assert_not_equal sql, capture_sql { comment.post }
97
+ end
98
+
99
+ def test_proxy_assignment
100
+ account = Account.find(1)
101
+ assert_nothing_raised { account.firm = account.firm }
102
+ end
103
+
104
+ def test_type_mismatch
105
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = 1 }
106
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { Account.find(1).firm = Project.find(1) }
107
+ end
108
+
109
+ def test_raises_type_mismatch_with_namespaced_class
110
+ assert_nil defined?(Region), "This test requires that there is no top-level Region class"
111
+
112
+ ActiveRecord::Base.connection.instance_eval do
113
+ create_table(:admin_regions) { |t| t.string :name }
114
+ add_column :admin_users, :region_id, :integer
115
+ end
116
+ Admin.const_set "RegionalUser", Class.new(Admin::User) { belongs_to(:region) }
117
+ Admin.const_set "Region", Class.new(ActiveRecord::Base)
118
+
119
+ e = assert_raise(ActiveRecord::AssociationTypeMismatch) {
120
+ Admin::RegionalUser.new(region: 'wrong value')
121
+ }
122
+ assert_match(/^Region\([^)]+\) expected, got String\([^)]+\)$/, e.message)
123
+ ensure
124
+ Admin.send :remove_const, "Region" if Admin.const_defined?("Region")
125
+ Admin.send :remove_const, "RegionalUser" if Admin.const_defined?("RegionalUser")
126
+
127
+ ActiveRecord::Base.connection.instance_eval do
128
+ remove_column :admin_users, :region_id if column_exists?(:admin_users, :region_id)
129
+ drop_table :admin_regions, if_exists: true
130
+ end
131
+ end
132
+
133
+ def test_natural_assignment
134
+ apple = Firm.create("name" => "Apple")
135
+ citibank = Account.create("credit_limit" => 10)
136
+ citibank.firm = apple
137
+ assert_equal apple.id, citibank.firm_id
138
+ end
139
+
140
+ def test_id_assignment
141
+ apple = Firm.create("name" => "Apple")
142
+ citibank = Account.create("credit_limit" => 10)
143
+ citibank.firm_id = apple
144
+ assert_nil citibank.firm_id
145
+ end
146
+
147
+ def test_natural_assignment_with_primary_key
148
+ apple = Firm.create("name" => "Apple")
149
+ citibank = Client.create("name" => "Primary key client")
150
+ citibank.firm_with_primary_key = apple
151
+ assert_equal apple.name, citibank.firm_name
152
+ end
153
+
154
+ def test_eager_loading_with_primary_key
155
+ Firm.create("name" => "Apple")
156
+ Client.create("name" => "Citibank", :firm_name => "Apple")
157
+ citibank_result = Client.all.merge!(:where => {:name => "Citibank"}, :includes => :firm_with_primary_key).first
158
+ assert citibank_result.association(:firm_with_primary_key).loaded?
159
+ end
160
+
161
+ def test_eager_loading_with_primary_key_as_symbol
162
+ Firm.create("name" => "Apple")
163
+ Client.create("name" => "Citibank", :firm_name => "Apple")
164
+ citibank_result = Client.all.merge!(:where => {:name => "Citibank"}, :includes => :firm_with_primary_key_symbols).first
165
+ assert citibank_result.association(:firm_with_primary_key_symbols).loaded?
166
+ end
167
+
168
+ def test_creating_the_belonging_object
169
+ citibank = Account.create("credit_limit" => 10)
170
+ apple = citibank.create_firm("name" => "Apple")
171
+ assert_equal apple, citibank.firm
172
+ citibank.save
173
+ citibank.reload
174
+ assert_equal apple, citibank.firm
175
+ end
176
+
177
+ def test_creating_the_belonging_object_with_primary_key
178
+ client = Client.create(:name => "Primary key client")
179
+ apple = client.create_firm_with_primary_key("name" => "Apple")
180
+ assert_equal apple, client.firm_with_primary_key
181
+ client.save
182
+ client.reload
183
+ assert_equal apple, client.firm_with_primary_key
184
+ end
185
+
186
+ def test_building_the_belonging_object
187
+ citibank = Account.create("credit_limit" => 10)
188
+ apple = citibank.build_firm("name" => "Apple")
189
+ citibank.save
190
+ assert_equal apple.id, citibank.firm_id
191
+ end
192
+
193
+ def test_building_the_belonging_object_with_implicit_sti_base_class
194
+ account = Account.new
195
+ company = account.build_firm
196
+ assert_kind_of Company, company, "Expected #{company.class} to be a Company"
197
+ end
198
+
199
+ def test_building_the_belonging_object_with_explicit_sti_base_class
200
+ account = Account.new
201
+ company = account.build_firm(:type => "Company")
202
+ assert_kind_of Company, company, "Expected #{company.class} to be a Company"
203
+ end
204
+
205
+ def test_building_the_belonging_object_with_sti_subclass
206
+ account = Account.new
207
+ company = account.build_firm(:type => "Firm")
208
+ assert_kind_of Firm, company, "Expected #{company.class} to be a Firm"
209
+ end
210
+
211
+ def test_building_the_belonging_object_with_an_invalid_type
212
+ account = Account.new
213
+ assert_raise(ActiveRecord::SubclassNotFound) { account.build_firm(:type => "InvalidType") }
214
+ end
215
+
216
+ def test_building_the_belonging_object_with_an_unrelated_type
217
+ account = Account.new
218
+ assert_raise(ActiveRecord::SubclassNotFound) { account.build_firm(:type => "Account") }
219
+ end
220
+
221
+ def test_building_the_belonging_object_with_primary_key
222
+ client = Client.create(:name => "Primary key client")
223
+ apple = client.build_firm_with_primary_key("name" => "Apple")
224
+ client.save
225
+ assert_equal apple.name, client.firm_name
226
+ end
227
+
228
+ def test_create!
229
+ client = Client.create!(:name => "Jimmy")
230
+ account = client.create_account!(:credit_limit => 10)
231
+ assert_equal account, client.account
232
+ assert account.persisted?
233
+ client.save
234
+ client.reload
235
+ assert_equal account, client.account
236
+ end
237
+
238
+ def test_failing_create!
239
+ client = Client.create!(:name => "Jimmy")
240
+ assert_raise(ActiveRecord::RecordInvalid) { client.create_account! }
241
+ assert_not_nil client.account
242
+ assert client.account.new_record?
243
+ end
244
+
245
+ def test_natural_assignment_to_nil
246
+ client = Client.find(3)
247
+ client.firm = nil
248
+ client.save
249
+ assert_nil client.firm(true)
250
+ assert_nil client.client_of
251
+ end
252
+
253
+ def test_natural_assignment_to_nil_with_primary_key
254
+ client = Client.create(:name => "Primary key client", :firm_name => companies(:first_firm).name)
255
+ client.firm_with_primary_key = nil
256
+ client.save
257
+ assert_nil client.firm_with_primary_key(true)
258
+ assert_nil client.client_of
259
+ end
260
+
261
+ def test_with_different_class_name
262
+ assert_equal Company.find(1).name, Company.find(3).firm_with_other_name.name
263
+ assert_not_nil Company.find(3).firm_with_other_name, "Microsoft should have a firm"
264
+ end
265
+
266
+ def test_with_condition
267
+ assert_equal Company.find(1).name, Company.find(3).firm_with_condition.name
268
+ assert_not_nil Company.find(3).firm_with_condition, "Microsoft should have a firm"
269
+ end
270
+
271
+ def test_polymorphic_association_class
272
+ sponsor = Sponsor.new
273
+ assert_nil sponsor.association(:sponsorable).send(:klass)
274
+ assert_nil sponsor.sponsorable(force_reload: true)
275
+
276
+ sponsor.sponsorable_type = '' # the column doesn't have to be declared NOT NULL
277
+ assert_nil sponsor.association(:sponsorable).send(:klass)
278
+ assert_nil sponsor.sponsorable(force_reload: true)
279
+
280
+ sponsor.sponsorable = Member.new :name => "Bert"
281
+ assert_equal Member, sponsor.association(:sponsorable).send(:klass)
282
+ assert_equal "members", sponsor.association(:sponsorable).aliased_table_name
283
+ end
284
+
285
+ def test_with_polymorphic_and_condition
286
+ sponsor = Sponsor.create
287
+ member = Member.create :name => "Bert"
288
+ sponsor.sponsorable = member
289
+
290
+ assert_equal member, sponsor.sponsorable
291
+ assert_nil sponsor.sponsorable_with_conditions
292
+ end
293
+
294
+ def test_with_select
295
+ assert_equal 1, Company.find(2).firm_with_select.attributes.size
296
+ assert_equal 1, Company.all.merge!(:includes => :firm_with_select ).find(2).firm_with_select.attributes.size
297
+ end
298
+
299
+ def test_belongs_to_without_counter_cache_option
300
+ # Ship has a conventionally named `treasures_count` column, but the counter_cache
301
+ # option is not given on the association.
302
+ ship = Ship.create(name: 'Countless')
303
+
304
+ assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed unless counter_cache is given on the relation" do
305
+ treasure = Treasure.new(name: 'Gold', ship: ship)
306
+ treasure.save
307
+ end
308
+
309
+ assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed unless counter_cache is given on the relation" do
310
+ treasure = ship.treasures.first
311
+ treasure.destroy
312
+ end
313
+ end
314
+
315
+ def test_belongs_to_counter
316
+ debate = Topic.create("title" => "debate")
317
+ assert_equal 0, debate.read_attribute("replies_count"), "No replies yet"
318
+
319
+ trash = debate.replies.create("title" => "blah!", "content" => "world around!")
320
+ assert_equal 1, Topic.find(debate.id).read_attribute("replies_count"), "First reply created"
321
+
322
+ trash.destroy
323
+ assert_equal 0, Topic.find(debate.id).read_attribute("replies_count"), "First reply deleted"
324
+ end
325
+
326
+ def test_belongs_to_counter_with_assigning_nil
327
+ post = Post.find(1)
328
+ comment = Comment.find(1)
329
+
330
+ assert_equal post.id, comment.post_id
331
+ assert_equal 2, Post.find(post.id).comments.size
332
+
333
+ comment.post = nil
334
+
335
+ assert_equal 1, Post.find(post.id).comments.size
336
+ end
337
+
338
+ def test_belongs_to_with_primary_key_counter
339
+ debate = Topic.create("title" => "debate")
340
+ debate2 = Topic.create("title" => "debate2")
341
+ reply = Reply.create("title" => "blah!", "content" => "world around!", "parent_title" => "debate")
342
+
343
+ assert_equal 1, debate.reload.replies_count
344
+ assert_equal 0, debate2.reload.replies_count
345
+
346
+ reply.topic_with_primary_key = debate2
347
+
348
+ assert_equal 0, debate.reload.replies_count
349
+ assert_equal 1, debate2.reload.replies_count
350
+
351
+ reply.topic_with_primary_key = nil
352
+
353
+ assert_equal 0, debate.reload.replies_count
354
+ assert_equal 0, debate2.reload.replies_count
355
+ end
356
+
357
+ def test_belongs_to_counter_with_reassigning
358
+ topic1 = Topic.create("title" => "t1")
359
+ topic2 = Topic.create("title" => "t2")
360
+ reply1 = Reply.new("title" => "r1", "content" => "r1")
361
+ reply1.topic = topic1
362
+
363
+ assert reply1.save
364
+ assert_equal 1, Topic.find(topic1.id).replies.size
365
+ assert_equal 0, Topic.find(topic2.id).replies.size
366
+
367
+ reply1.topic = Topic.find(topic2.id)
368
+
369
+ assert_no_queries do
370
+ reply1.topic = topic2
371
+ end
372
+
373
+ assert reply1.save
374
+ assert_equal 0, Topic.find(topic1.id).replies.size
375
+ assert_equal 1, Topic.find(topic2.id).replies.size
376
+
377
+ reply1.topic = nil
378
+
379
+ assert_equal 0, Topic.find(topic1.id).replies.size
380
+ assert_equal 0, Topic.find(topic2.id).replies.size
381
+
382
+ reply1.topic = topic1
383
+
384
+ assert_equal 1, Topic.find(topic1.id).replies.size
385
+ assert_equal 0, Topic.find(topic2.id).replies.size
386
+
387
+ reply1.destroy
388
+
389
+ assert_equal 0, Topic.find(topic1.id).replies.size
390
+ assert_equal 0, Topic.find(topic2.id).replies.size
391
+ end
392
+
393
+ def test_belongs_to_reassign_with_namespaced_models_and_counters
394
+ topic1 = Web::Topic.create("title" => "t1")
395
+ topic2 = Web::Topic.create("title" => "t2")
396
+ reply1 = Web::Reply.new("title" => "r1", "content" => "r1")
397
+ reply1.topic = topic1
398
+
399
+ assert reply1.save
400
+ assert_equal 1, Web::Topic.find(topic1.id).replies.size
401
+ assert_equal 0, Web::Topic.find(topic2.id).replies.size
402
+
403
+ reply1.topic = Web::Topic.find(topic2.id)
404
+
405
+ assert reply1.save
406
+ assert_equal 0, Web::Topic.find(topic1.id).replies.size
407
+ assert_equal 1, Web::Topic.find(topic2.id).replies.size
408
+ end
409
+
410
+ def test_belongs_to_counter_after_save
411
+ topic = Topic.create!(:title => "monday night")
412
+ topic.replies.create!(:title => "re: monday night", :content => "football")
413
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
414
+
415
+ topic.save!
416
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
417
+ end
418
+
419
+ def test_belongs_to_with_touch_option_on_touch
420
+ line_item = LineItem.create!
421
+ Invoice.create!(line_items: [line_item])
422
+
423
+ assert_queries(1) { line_item.touch }
424
+ end
425
+
426
+ def test_belongs_to_with_touch_option_on_touch_without_updated_at_attributes
427
+ assert_not LineItem.column_names.include?("updated_at")
428
+
429
+ line_item = LineItem.create!
430
+ invoice = Invoice.create!(line_items: [line_item])
431
+ initial = invoice.updated_at
432
+ line_item.touch
433
+
434
+ assert_not_equal initial, invoice.reload.updated_at
435
+ end
436
+
437
+ def test_belongs_to_with_touch_option_on_touch_and_removed_parent
438
+ line_item = LineItem.create!
439
+ Invoice.create!(line_items: [line_item])
440
+
441
+ line_item.invoice = nil
442
+
443
+ assert_queries(2) { line_item.touch }
444
+ end
445
+
446
+ def test_belongs_to_with_touch_option_on_update
447
+ line_item = LineItem.create!
448
+ Invoice.create!(line_items: [line_item])
449
+
450
+ assert_queries(2) { line_item.update amount: 10 }
451
+ end
452
+
453
+ def test_belongs_to_with_touch_option_on_empty_update
454
+ line_item = LineItem.create!
455
+ Invoice.create!(line_items: [line_item])
456
+
457
+ assert_queries(0) { line_item.save }
458
+ end
459
+
460
+ def test_belongs_to_with_touch_option_on_destroy
461
+ line_item = LineItem.create!
462
+ Invoice.create!(line_items: [line_item])
463
+
464
+ assert_queries(2) { line_item.destroy }
465
+ end
466
+
467
+ def test_belongs_to_with_touch_option_on_destroy_with_destroyed_parent
468
+ line_item = LineItem.create!
469
+ invoice = Invoice.create!(line_items: [line_item])
470
+ invoice.destroy
471
+
472
+ assert_queries(1) { line_item.destroy }
473
+ end
474
+
475
+ def test_belongs_to_with_touch_option_on_touch_and_reassigned_parent
476
+ line_item = LineItem.create!
477
+ Invoice.create!(line_items: [line_item])
478
+
479
+ line_item.invoice = Invoice.create!
480
+
481
+ assert_queries(3) { line_item.touch }
482
+ end
483
+
484
+ def test_belongs_to_counter_after_update
485
+ topic = Topic.create!(title: "37s")
486
+ topic.replies.create!(title: "re: 37s", content: "rails")
487
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
488
+
489
+ topic.update(title: "37signals")
490
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
491
+ end
492
+
493
+ def test_belongs_to_counter_when_update_columns
494
+ topic = Topic.create!(:title => "37s")
495
+ topic.replies.create!(:title => "re: 37s", :content => "rails")
496
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
497
+
498
+ topic.update_columns(content: "rails is wonderful")
499
+ assert_equal 1, Topic.find(topic.id)[:replies_count]
500
+ end
501
+
502
+ def test_assignment_before_child_saved
503
+ final_cut = Client.new("name" => "Final Cut")
504
+ firm = Firm.find(1)
505
+ final_cut.firm = firm
506
+ assert !final_cut.persisted?
507
+ assert final_cut.save
508
+ assert final_cut.persisted?
509
+ assert firm.persisted?
510
+ assert_equal firm, final_cut.firm
511
+ assert_equal firm, final_cut.firm(true)
512
+ end
513
+
514
+ def test_assignment_before_child_saved_with_primary_key
515
+ final_cut = Client.new("name" => "Final Cut")
516
+ firm = Firm.find(1)
517
+ final_cut.firm_with_primary_key = firm
518
+ assert !final_cut.persisted?
519
+ assert final_cut.save
520
+ assert final_cut.persisted?
521
+ assert firm.persisted?
522
+ assert_equal firm, final_cut.firm_with_primary_key
523
+ assert_equal firm, final_cut.firm_with_primary_key(true)
524
+ end
525
+
526
+ def test_new_record_with_foreign_key_but_no_object
527
+ client = Client.new("firm_id" => 1)
528
+ # sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
529
+ assert_equal Firm.all.merge!(:order => "id").first, client.firm_with_basic_id
530
+ end
531
+
532
+ def test_setting_foreign_key_after_nil_target_loaded
533
+ client = Client.new
534
+ client.firm_with_basic_id
535
+ client.firm_id = 1
536
+
537
+ assert_equal companies(:first_firm), client.firm_with_basic_id
538
+ end
539
+
540
+ def test_polymorphic_setting_foreign_key_after_nil_target_loaded
541
+ sponsor = Sponsor.new
542
+ sponsor.sponsorable
543
+ sponsor.sponsorable_id = 1
544
+ sponsor.sponsorable_type = "Member"
545
+
546
+ assert_equal members(:groucho), sponsor.sponsorable
547
+ end
548
+
549
+ def test_dont_find_target_when_foreign_key_is_null
550
+ tagging = taggings(:thinking_general)
551
+ assert_queries(0) { tagging.super_tag }
552
+ end
553
+
554
+ def test_field_name_same_as_foreign_key
555
+ computer = Computer.find(1)
556
+ assert_not_nil computer.developer, ":foreign key == attribute didn't lock up" # '
557
+ end
558
+
559
+ def test_counter_cache
560
+ topic = Topic.create :title => "Zoom-zoom-zoom"
561
+ assert_equal 0, topic[:replies_count]
562
+
563
+ reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
564
+ reply.topic = topic
565
+
566
+ assert_equal 1, topic.reload[:replies_count]
567
+ assert_equal 1, topic.replies.size
568
+
569
+ topic[:replies_count] = 15
570
+ assert_equal 15, topic.replies.size
571
+ end
572
+
573
+ def test_counter_cache_double_destroy
574
+ topic = Topic.create :title => "Zoom-zoom-zoom"
575
+
576
+ 5.times do
577
+ topic.replies.create(:title => "re: zoom", :content => "speedy quick!")
578
+ end
579
+
580
+ assert_equal 5, topic.reload[:replies_count]
581
+ assert_equal 5, topic.replies.size
582
+
583
+ reply = topic.replies.first
584
+
585
+ reply.destroy
586
+ assert_equal 4, topic.reload[:replies_count]
587
+
588
+ reply.destroy
589
+ assert_equal 4, topic.reload[:replies_count]
590
+ assert_equal 4, topic.replies.size
591
+ end
592
+
593
+ def test_concurrent_counter_cache_double_destroy
594
+ topic = Topic.create :title => "Zoom-zoom-zoom"
595
+
596
+ 5.times do
597
+ topic.replies.create(:title => "re: zoom", :content => "speedy quick!")
598
+ end
599
+
600
+ assert_equal 5, topic.reload[:replies_count]
601
+ assert_equal 5, topic.replies.size
602
+
603
+ reply = topic.replies.first
604
+ reply_clone = Reply.find(reply.id)
605
+
606
+ reply.destroy
607
+ assert_equal 4, topic.reload[:replies_count]
608
+
609
+ reply_clone.destroy
610
+ assert_equal 4, topic.reload[:replies_count]
611
+ assert_equal 4, topic.replies.size
612
+ end
613
+
614
+ def test_custom_counter_cache
615
+ reply = Reply.create(:title => "re: zoom", :content => "speedy quick!")
616
+ assert_equal 0, reply[:replies_count]
617
+
618
+ silly = SillyReply.create(:title => "gaga", :content => "boo-boo")
619
+ silly.reply = reply
620
+
621
+ assert_equal 1, reply.reload[:replies_count]
622
+ assert_equal 1, reply.replies.size
623
+
624
+ reply[:replies_count] = 17
625
+ assert_equal 17, reply.replies.size
626
+ end
627
+
628
+ def test_association_assignment_sticks
629
+ post = Post.first
630
+
631
+ author1, author2 = Author.all.merge!(:limit => 2).to_a
632
+ assert_not_nil author1
633
+ assert_not_nil author2
634
+
635
+ # make sure the association is loaded
636
+ post.author
637
+
638
+ # set the association by id, directly
639
+ post.author_id = author2.id
640
+
641
+ # save and reload
642
+ post.save!
643
+ post.reload
644
+
645
+ # the author id of the post should be the id we set
646
+ assert_equal post.author_id, author2.id
647
+ end
648
+
649
+ def test_cant_save_readonly_association
650
+ assert_raise(ActiveRecord::ReadOnlyRecord) { companies(:first_client).readonly_firm.save! }
651
+ assert companies(:first_client).readonly_firm.readonly?
652
+ end
653
+
654
+ def test_test_polymorphic_assignment_foreign_key_type_string
655
+ comment = Comment.first
656
+ comment.author = Author.first
657
+ comment.resource = Member.first
658
+ comment.save
659
+
660
+ assert_equal Comment.all.to_a,
661
+ Comment.includes(:author).to_a
662
+
663
+ assert_equal Comment.all.to_a,
664
+ Comment.includes(:resource).to_a
665
+ end
666
+
667
+ def test_polymorphic_assignment_foreign_type_field_updating
668
+ # should update when assigning a saved record
669
+ sponsor = Sponsor.new
670
+ member = Member.create
671
+ sponsor.sponsorable = member
672
+ assert_equal "Member", sponsor.sponsorable_type
673
+
674
+ # should update when assigning a new record
675
+ sponsor = Sponsor.new
676
+ member = Member.new
677
+ sponsor.sponsorable = member
678
+ assert_equal "Member", sponsor.sponsorable_type
679
+ end
680
+
681
+ def test_polymorphic_assignment_with_primary_key_foreign_type_field_updating
682
+ # should update when assigning a saved record
683
+ essay = Essay.new
684
+ writer = Author.create(:name => "David")
685
+ essay.writer = writer
686
+ assert_equal "Author", essay.writer_type
687
+
688
+ # should update when assigning a new record
689
+ essay = Essay.new
690
+ writer = Author.new
691
+ essay.writer = writer
692
+ assert_equal "Author", essay.writer_type
693
+ end
694
+
695
+ def test_polymorphic_assignment_updates_foreign_id_field_for_new_and_saved_records
696
+ sponsor = Sponsor.new
697
+ saved_member = Member.create
698
+ new_member = Member.new
699
+
700
+ sponsor.sponsorable = saved_member
701
+ assert_equal saved_member.id, sponsor.sponsorable_id
702
+
703
+ sponsor.sponsorable = new_member
704
+ assert_nil sponsor.sponsorable_id
705
+ end
706
+
707
+ def test_assignment_updates_foreign_id_field_for_new_and_saved_records
708
+ client = Client.new
709
+ saved_firm = Firm.create :name => "Saved"
710
+ new_firm = Firm.new
711
+
712
+ client.firm = saved_firm
713
+ assert_equal saved_firm.id, client.client_of
714
+
715
+ client.firm = new_firm
716
+ assert_nil client.client_of
717
+ end
718
+
719
+ def test_polymorphic_assignment_with_primary_key_updates_foreign_id_field_for_new_and_saved_records
720
+ essay = Essay.new
721
+ saved_writer = Author.create(:name => "David")
722
+ new_writer = Author.new
723
+
724
+ essay.writer = saved_writer
725
+ assert_equal saved_writer.name, essay.writer_id
726
+
727
+ essay.writer = new_writer
728
+ assert_nil essay.writer_id
729
+ end
730
+
731
+ def test_polymorphic_assignment_with_nil
732
+ essay = Essay.new
733
+ assert_nil essay.writer_id
734
+ assert_nil essay.writer_type
735
+
736
+ essay.writer_id = 1
737
+ essay.writer_type = 'Author'
738
+
739
+ essay.writer = nil
740
+ assert_nil essay.writer_id
741
+ assert_nil essay.writer_type
742
+ end
743
+
744
+ def test_belongs_to_proxy_should_not_respond_to_private_methods
745
+ assert_raise(NoMethodError) { companies(:first_firm).private_method }
746
+ assert_raise(NoMethodError) { companies(:second_client).firm.private_method }
747
+ end
748
+
749
+ def test_belongs_to_proxy_should_respond_to_private_methods_via_send
750
+ companies(:first_firm).send(:private_method)
751
+ companies(:second_client).firm.send(:private_method)
752
+ end
753
+
754
+ def test_save_of_record_with_loaded_belongs_to
755
+ @account = companies(:first_firm).account
756
+
757
+ assert_nothing_raised do
758
+ Account.find(@account.id).save!
759
+ Account.all.merge!(:includes => :firm).find(@account.id).save!
760
+ end
761
+
762
+ @account.firm.delete
763
+
764
+ assert_nothing_raised do
765
+ Account.find(@account.id).save!
766
+ Account.all.merge!(:includes => :firm).find(@account.id).save!
767
+ end
768
+ end
769
+
770
+ def test_dependent_delete_and_destroy_with_belongs_to
771
+ AuthorAddress.destroyed_author_address_ids.clear
772
+
773
+ author_address = author_addresses(:david_address)
774
+ author_address_extra = author_addresses(:david_address_extra)
775
+ assert_equal [], AuthorAddress.destroyed_author_address_ids
776
+
777
+ assert_difference "AuthorAddress.count", -2 do
778
+ authors(:david).destroy
779
+ end
780
+
781
+ assert_equal [], AuthorAddress.where(id: [author_address.id, author_address_extra.id])
782
+ assert_equal [author_address.id], AuthorAddress.destroyed_author_address_ids
783
+ end
784
+
785
+ def test_belongs_to_invalid_dependent_option_raises_exception
786
+ error = assert_raise ArgumentError do
787
+ Class.new(Author).belongs_to :special_author_address, :dependent => :nullify
788
+ end
789
+ assert_equal error.message, 'The :dependent option must be one of [:destroy, :delete], but is :nullify'
790
+ end
791
+
792
+ def test_attributes_are_being_set_when_initialized_from_belongs_to_association_with_where_clause
793
+ new_firm = accounts(:signals37).build_firm(:name => 'Apple')
794
+ assert_equal new_firm.name, "Apple"
795
+ end
796
+
797
+ def test_attributes_are_set_without_error_when_initialized_from_belongs_to_association_with_array_in_where_clause
798
+ new_account = Account.where(:credit_limit => [ 50, 60 ]).new
799
+ assert_nil new_account.credit_limit
800
+ end
801
+
802
+ def test_reassigning_the_parent_id_updates_the_object
803
+ client = companies(:second_client)
804
+
805
+ client.firm
806
+ client.firm_with_condition
807
+ firm_proxy = client.send(:association_instance_get, :firm)
808
+ firm_with_condition_proxy = client.send(:association_instance_get, :firm_with_condition)
809
+
810
+ assert !firm_proxy.stale_target?
811
+ assert !firm_with_condition_proxy.stale_target?
812
+ assert_equal companies(:first_firm), client.firm
813
+ assert_equal companies(:first_firm), client.firm_with_condition
814
+
815
+ client.client_of = companies(:another_firm).id
816
+
817
+ assert firm_proxy.stale_target?
818
+ assert firm_with_condition_proxy.stale_target?
819
+ assert_equal companies(:another_firm), client.firm
820
+ assert_equal companies(:another_firm), client.firm_with_condition
821
+ end
822
+
823
+ def test_polymorphic_reassignment_of_associated_id_updates_the_object
824
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
825
+
826
+ sponsor.sponsorable
827
+ proxy = sponsor.send(:association_instance_get, :sponsorable)
828
+
829
+ assert !proxy.stale_target?
830
+ assert_equal members(:groucho), sponsor.sponsorable
831
+
832
+ sponsor.sponsorable_id = members(:some_other_guy).id
833
+
834
+ assert proxy.stale_target?
835
+ assert_equal members(:some_other_guy), sponsor.sponsorable
836
+ end
837
+
838
+ def test_polymorphic_reassignment_of_associated_type_updates_the_object
839
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
840
+
841
+ sponsor.sponsorable
842
+ proxy = sponsor.send(:association_instance_get, :sponsorable)
843
+
844
+ assert !proxy.stale_target?
845
+ assert_equal members(:groucho), sponsor.sponsorable
846
+
847
+ sponsor.sponsorable_type = 'Firm'
848
+
849
+ assert proxy.stale_target?
850
+ assert_equal companies(:first_firm), sponsor.sponsorable
851
+ end
852
+
853
+ def test_reloading_association_with_key_change
854
+ client = companies(:second_client)
855
+ firm = client.association(:firm)
856
+
857
+ client.firm = companies(:another_firm)
858
+ firm.reload
859
+ assert_equal companies(:another_firm), firm.target
860
+
861
+ client.client_of = companies(:first_firm).id
862
+ firm.reload
863
+ assert_equal companies(:first_firm), firm.target
864
+ end
865
+
866
+ def test_polymorphic_counter_cache
867
+ tagging = taggings(:welcome_general)
868
+ post = posts(:welcome)
869
+ comment = comments(:greetings)
870
+
871
+ assert_difference lambda { post.reload.tags_count }, -1 do
872
+ assert_difference 'comment.reload.tags_count', +1 do
873
+ tagging.taggable = comment
874
+ end
875
+ end
876
+ end
877
+
878
+ def test_polymorphic_with_custom_foreign_type
879
+ sponsor = sponsors(:moustache_club_sponsor_for_groucho)
880
+ groucho = members(:groucho)
881
+ other = members(:some_other_guy)
882
+
883
+ assert_equal groucho, sponsor.sponsorable
884
+ assert_equal groucho, sponsor.thing
885
+
886
+ sponsor.thing = other
887
+
888
+ assert_equal other, sponsor.sponsorable
889
+ assert_equal other, sponsor.thing
890
+
891
+ sponsor.sponsorable = groucho
892
+
893
+ assert_equal groucho, sponsor.sponsorable
894
+ assert_equal groucho, sponsor.thing
895
+ end
896
+
897
+ def test_build_with_conditions
898
+ client = companies(:second_client)
899
+ firm = client.build_bob_firm
900
+
901
+ assert_equal "Bob", firm.name
902
+ end
903
+
904
+ def test_create_with_conditions
905
+ client = companies(:second_client)
906
+ firm = client.create_bob_firm
907
+
908
+ assert_equal "Bob", firm.name
909
+ end
910
+
911
+ def test_create_bang_with_conditions
912
+ client = companies(:second_client)
913
+ firm = client.create_bob_firm!
914
+
915
+ assert_equal "Bob", firm.name
916
+ end
917
+
918
+ def test_build_with_block
919
+ client = Client.create(:name => 'Client Company')
920
+
921
+ firm = client.build_firm{ |f| f.name = 'Agency Company' }
922
+ assert_equal 'Agency Company', firm.name
923
+ end
924
+
925
+ def test_create_with_block
926
+ client = Client.create(:name => 'Client Company')
927
+
928
+ firm = client.create_firm{ |f| f.name = 'Agency Company' }
929
+ assert_equal 'Agency Company', firm.name
930
+ end
931
+
932
+ def test_create_bang_with_block
933
+ client = Client.create(:name => 'Client Company')
934
+
935
+ firm = client.create_firm!{ |f| f.name = 'Agency Company' }
936
+ assert_equal 'Agency Company', firm.name
937
+ end
938
+
939
+ def test_should_set_foreign_key_on_create_association
940
+ client = Client.create! :name => "fuu"
941
+
942
+ firm = client.create_firm :name => "baa"
943
+ assert_equal firm.id, client.client_of
944
+ end
945
+
946
+ def test_should_set_foreign_key_on_create_association!
947
+ client = Client.create! :name => "fuu"
948
+
949
+ firm = client.create_firm! :name => "baa"
950
+ assert_equal firm.id, client.client_of
951
+ end
952
+
953
+ def test_self_referential_belongs_to_with_counter_cache_assigning_nil
954
+ comment = Comment.create! :post => posts(:thinking), :body => "fuu"
955
+ comment.parent = nil
956
+ comment.save!
957
+
958
+ assert_equal nil, comment.reload.parent
959
+ assert_equal 0, comments(:greetings).reload.children_count
960
+ end
961
+
962
+ def test_belongs_to_with_id_assigning
963
+ post = posts(:welcome)
964
+ comment = Comment.create! body: "foo", post: post
965
+ parent = comments(:greetings)
966
+ assert_equal 0, parent.reload.children_count
967
+ comment.parent_id = parent.id
968
+
969
+ comment.save!
970
+ assert_equal 1, parent.reload.children_count
971
+ end
972
+
973
+ def test_polymorphic_with_custom_primary_key
974
+ toy = Toy.create!
975
+ sponsor = Sponsor.create!(:sponsorable => toy)
976
+
977
+ assert_equal toy, sponsor.reload.sponsorable
978
+ end
979
+
980
+ test "stale tracking doesn't care about the type" do
981
+ apple = Firm.create("name" => "Apple")
982
+ citibank = Account.create("credit_limit" => 10)
983
+
984
+ citibank.firm_id = apple.id
985
+ citibank.firm # load it
986
+
987
+ citibank.firm_id = apple.id.to_s
988
+
989
+ assert !citibank.association(:firm).stale_target?
990
+ end
991
+
992
+ def test_reflect_the_most_recent_change
993
+ author1, author2 = Author.limit(2)
994
+ post = Post.new(:title => "foo", :body=> "bar")
995
+
996
+ post.author = author1
997
+ post.author_id = author2.id
998
+
999
+ assert post.save
1000
+ assert_equal post.author_id, author2.id
1001
+ end
1002
+
1003
+ test 'dangerous association name raises ArgumentError' do
1004
+ [:errors, 'errors', :save, 'save'].each do |name|
1005
+ assert_raises(ArgumentError, "Association #{name} should not be allowed") do
1006
+ Class.new(ActiveRecord::Base) do
1007
+ belongs_to name
1008
+ end
1009
+ end
1010
+ end
1011
+ end
1012
+
1013
+ test 'belongs_to works with model called Record' do
1014
+ record = Record.create!
1015
+ Column.create! record: record
1016
+ assert_equal 1, Column.count
1017
+ end
1018
+ end
1019
+
1020
+ class BelongsToWithForeignKeyTest < ActiveRecord::TestCase
1021
+ fixtures :authors, :author_addresses
1022
+
1023
+ def test_destroy_linked_models
1024
+ address = AuthorAddress.create!
1025
+ author = Author.create! name: "Author", author_address_id: address.id
1026
+
1027
+ author.destroy!
1028
+ end
1029
+ end