ibm_db 3.0.4-x86-mingw32 → 3.0.5-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 (463) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -1
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/README +225 -225
  6. data/ext/Makefile.nt32 +181 -181
  7. data/ext/Makefile.nt32.191 +212 -212
  8. data/ext/extconf.rb +291 -291
  9. data/ext/ibm_db.c +11887 -11884
  10. data/ext/ruby_ibm_db.h +241 -241
  11. data/ext/ruby_ibm_db_cli.c +866 -866
  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 +3177 -3177
  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 +122 -122
  19. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  20. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  21. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +46 -46
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +276 -261
  26. data/test/cases/aggregations_test.rb +158 -158
  27. data/test/cases/ar_schema_test.rb +161 -161
  28. data/test/cases/associations/association_scope_test.rb +21 -21
  29. data/test/cases/associations/belongs_to_associations_test.rb +1029 -1029
  30. data/test/cases/associations/callbacks_test.rb +192 -192
  31. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  32. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -26
  33. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  34. data/test/cases/associations/eager_load_nested_include_test.rb +128 -128
  35. data/test/cases/associations/eager_singularization_test.rb +148 -148
  36. data/test/cases/associations/eager_test.rb +1429 -1411
  37. data/test/cases/associations/extension_test.rb +82 -82
  38. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +972 -932
  39. data/test/cases/associations/has_many_associations_test.rb +2182 -2162
  40. data/test/cases/associations/has_many_through_associations_test.rb +1204 -1204
  41. data/test/cases/associations/has_one_associations_test.rb +610 -610
  42. data/test/cases/associations/has_one_through_associations_test.rb +380 -380
  43. data/test/cases/associations/inner_join_association_test.rb +139 -139
  44. data/test/cases/associations/inverse_associations_test.rb +706 -693
  45. data/test/cases/associations/join_model_test.rb +754 -754
  46. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  47. data/test/cases/associations/required_test.rb +82 -82
  48. data/test/cases/associations_test.rb +380 -380
  49. data/test/cases/attribute_decorators_test.rb +125 -125
  50. data/test/cases/attribute_methods/read_test.rb +60 -60
  51. data/test/cases/attribute_methods/serialization_test.rb +29 -29
  52. data/test/cases/attribute_methods_test.rb +952 -952
  53. data/test/cases/attribute_set_test.rb +210 -200
  54. data/test/cases/attribute_test.rb +180 -180
  55. data/test/cases/attributes_test.rb +136 -136
  56. data/test/cases/autosave_association_test.rb +1595 -1595
  57. data/test/cases/base_test.rb +1664 -1638
  58. data/test/cases/batches_test.rb +212 -212
  59. data/test/cases/binary_test.rb +52 -52
  60. data/test/cases/bind_parameter_test.rb +100 -100
  61. data/test/cases/calculations_test.rb +646 -646
  62. data/test/cases/callbacks_test.rb +543 -543
  63. data/test/cases/clone_test.rb +40 -40
  64. data/test/cases/coders/yaml_column_test.rb +63 -63
  65. data/test/cases/column_alias_test.rb +17 -17
  66. data/test/cases/column_definition_test.rb +123 -123
  67. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -54
  68. data/test/cases/connection_adapters/connection_handler_test.rb +53 -53
  69. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  70. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -293
  71. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -65
  72. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  73. data/test/cases/connection_adapters/schema_cache_test.rb +56 -56
  74. data/test/cases/connection_adapters/type_lookup_test.rb +110 -110
  75. data/test/cases/connection_management_test.rb +122 -122
  76. data/test/cases/connection_pool_test.rb +346 -346
  77. data/test/cases/connection_specification/resolver_test.rb +116 -116
  78. data/test/cases/core_test.rb +112 -112
  79. data/test/cases/counter_cache_test.rb +209 -209
  80. data/test/cases/custom_locking_test.rb +17 -17
  81. data/test/cases/database_statements_test.rb +19 -19
  82. data/test/cases/date_time_test.rb +61 -61
  83. data/test/cases/defaults_test.rb +223 -223
  84. data/test/cases/dirty_test.rb +785 -775
  85. data/test/cases/disconnected_test.rb +28 -28
  86. data/test/cases/dup_test.rb +157 -157
  87. data/test/cases/enum_test.rb +290 -290
  88. data/test/cases/explain_subscriber_test.rb +64 -64
  89. data/test/cases/explain_test.rb +76 -76
  90. data/test/cases/finder_respond_to_test.rb +60 -60
  91. data/test/cases/finder_test.rb +1169 -1166
  92. data/test/cases/fixture_set/file_test.rb +138 -138
  93. data/test/cases/fixtures_test.rb +908 -897
  94. data/test/cases/forbidden_attributes_protection_test.rb +99 -99
  95. data/test/cases/habtm_destroy_order_test.rb +61 -61
  96. data/test/cases/helper.rb +210 -210
  97. data/test/cases/hot_compatibility_test.rb +54 -54
  98. data/test/cases/i18n_test.rb +45 -45
  99. data/test/cases/inheritance_test.rb +375 -375
  100. data/test/cases/integration_test.rb +139 -139
  101. data/test/cases/invalid_connection_test.rb +22 -22
  102. data/test/cases/invalid_date_test.rb +32 -32
  103. data/test/cases/invertible_migration_test.rb +295 -295
  104. data/test/cases/json_serialization_test.rb +302 -302
  105. data/test/cases/locking_test.rb +477 -477
  106. data/test/cases/log_subscriber_test.rb +136 -136
  107. data/test/cases/migration/change_schema_test - Copy.rb +448 -448
  108. data/test/cases/migration/change_schema_test.rb +512 -472
  109. data/test/cases/migration/change_table_test.rb +224 -224
  110. data/test/cases/migration/column_attributes_test.rb +192 -192
  111. data/test/cases/migration/column_positioning_test.rb +56 -56
  112. data/test/cases/migration/columns_test.rb +304 -304
  113. data/test/cases/migration/command_recorder_test.rb +305 -305
  114. data/test/cases/migration/create_join_table_test.rb +148 -148
  115. data/test/cases/migration/foreign_key_test - Changed.rb +325 -325
  116. data/test/cases/migration/foreign_key_test.rb +328 -360
  117. data/test/cases/migration/helper.rb +39 -39
  118. data/test/cases/migration/index_test.rb +216 -216
  119. data/test/cases/migration/logger_test.rb +36 -36
  120. data/test/cases/migration/pending_migrations_test.rb +53 -53
  121. data/test/cases/migration/references_foreign_key_test.rb +169 -214
  122. data/test/cases/migration/references_index_test.rb +101 -101
  123. data/test/cases/migration/references_statements_test.rb +116 -116
  124. data/test/cases/migration/rename_table_test.rb +93 -93
  125. data/test/cases/migration/table_and_index_test.rb +24 -24
  126. data/test/cases/migration_test.rb +959 -959
  127. data/test/cases/migrator_test.rb +388 -388
  128. data/test/cases/mixin_test.rb +70 -70
  129. data/test/cases/modules_test.rb +173 -173
  130. data/test/cases/multiparameter_attributes_test.rb +350 -350
  131. data/test/cases/multiple_db_test.rb +115 -115
  132. data/test/cases/nested_attributes_test.rb +1070 -1057
  133. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  134. data/test/cases/persistence_test.rb +909 -909
  135. data/test/cases/pooled_connections_test.rb +81 -81
  136. data/test/cases/primary_keys_test.rb +237 -237
  137. data/test/cases/query_cache_test.rb +326 -326
  138. data/test/cases/quoting_test.rb +156 -156
  139. data/test/cases/readonly_test.rb +118 -118
  140. data/test/cases/reaper_test.rb +85 -85
  141. data/test/cases/reflection_test.rb +463 -454
  142. data/test/cases/relation/delegation_test.rb +68 -68
  143. data/test/cases/relation/merging_test.rb +161 -161
  144. data/test/cases/relation/mutation_test.rb +165 -165
  145. data/test/cases/relation/predicate_builder_test.rb +14 -14
  146. data/test/cases/relation/where_chain_test.rb +181 -181
  147. data/test/cases/relation/where_test.rb +300 -300
  148. data/test/cases/relation/where_test2.rb +36 -36
  149. data/test/cases/relation_test.rb +319 -297
  150. data/test/cases/relations_test.rb +1815 -1815
  151. data/test/cases/reload_models_test.rb +22 -22
  152. data/test/cases/result_test.rb +80 -80
  153. data/test/cases/sanitize_test.rb +83 -83
  154. data/test/cases/schema_dumper_test.rb +463 -463
  155. data/test/cases/scoping/default_scoping_test.rb +454 -454
  156. data/test/cases/scoping/named_scoping_test.rb +524 -524
  157. data/test/cases/scoping/relation_scoping_test.rb +357 -357
  158. data/test/cases/serialization_test.rb +104 -104
  159. data/test/cases/serialized_attribute_test.rb +277 -277
  160. data/test/cases/statement_cache_test.rb +98 -98
  161. data/test/cases/store_test.rb +194 -194
  162. data/test/cases/tasks/database_tasks_test.rb +398 -396
  163. data/test/cases/tasks/mysql_rake_test.rb +324 -311
  164. data/test/cases/tasks/postgresql_rake_test.rb +250 -245
  165. data/test/cases/tasks/sqlite_rake_test.rb +193 -193
  166. data/test/cases/test_case.rb +123 -123
  167. data/test/cases/timestamp_test.rb +467 -468
  168. data/test/cases/transaction_callbacks_test.rb +452 -452
  169. data/test/cases/transaction_isolation_test.rb +106 -106
  170. data/test/cases/transactions_test.rb +817 -817
  171. data/test/cases/type/decimal_test.rb +56 -51
  172. data/test/cases/type/integer_test.rb +121 -121
  173. data/test/cases/type/string_test.rb +36 -36
  174. data/test/cases/type/type_map_test.rb +177 -177
  175. data/test/cases/type/unsigned_integer_test.rb +18 -18
  176. data/test/cases/types_test.rb +141 -141
  177. data/test/cases/unconnected_test.rb +33 -33
  178. data/test/cases/validations/association_validation_test.rb +86 -86
  179. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  180. data/test/cases/validations/i18n_validation_test.rb +90 -90
  181. data/test/cases/validations/length_validation_test.rb +47 -47
  182. data/test/cases/validations/presence_validation_test.rb +68 -68
  183. data/test/cases/validations/uniqueness_validation_test.rb +457 -434
  184. data/test/cases/validations_repair_helper.rb +23 -23
  185. data/test/cases/validations_test.rb +165 -165
  186. data/test/cases/view_test.rb +119 -113
  187. data/test/cases/xml_serialization_test.rb +457 -457
  188. data/test/cases/yaml_serialization_test.rb +126 -86
  189. data/test/config.rb +5 -5
  190. data/test/config.yml +154 -154
  191. data/test/connections/native_ibm_db/connection.rb +43 -43
  192. data/test/fixtures/accounts.yml +29 -29
  193. data/test/fixtures/admin/accounts.yml +2 -2
  194. data/test/fixtures/admin/randomly_named_a9.yml +7 -7
  195. data/test/fixtures/admin/randomly_named_b0.yml +7 -7
  196. data/test/fixtures/admin/users.yml +10 -10
  197. data/test/fixtures/author_addresses.yml +17 -17
  198. data/test/fixtures/author_favorites.yml +3 -3
  199. data/test/fixtures/authors.yml +23 -23
  200. data/test/fixtures/binaries.yml +133 -133
  201. data/test/fixtures/books.yml +11 -11
  202. data/test/fixtures/bulbs.yml +5 -5
  203. data/test/fixtures/cars.yml +9 -9
  204. data/test/fixtures/categories.yml +19 -19
  205. data/test/fixtures/categories/special_categories.yml +9 -9
  206. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  207. data/test/fixtures/categories_ordered.yml +7 -7
  208. data/test/fixtures/categories_posts.yml +31 -31
  209. data/test/fixtures/categorizations.yml +23 -23
  210. data/test/fixtures/clubs.yml +8 -8
  211. data/test/fixtures/collections.yml +3 -3
  212. data/test/fixtures/colleges.yml +3 -3
  213. data/test/fixtures/comments.yml +65 -65
  214. data/test/fixtures/companies.yml +67 -67
  215. data/test/fixtures/computers.yml +10 -10
  216. data/test/fixtures/courses.yml +8 -8
  217. data/test/fixtures/customers.yml +25 -25
  218. data/test/fixtures/dashboards.yml +6 -6
  219. data/test/fixtures/developers.yml +21 -21
  220. data/test/fixtures/developers_projects.yml +16 -16
  221. data/test/fixtures/dog_lovers.yml +7 -7
  222. data/test/fixtures/dogs.yml +4 -4
  223. data/test/fixtures/doubloons.yml +3 -3
  224. data/test/fixtures/edges.yml +5 -5
  225. data/test/fixtures/entrants.yml +14 -14
  226. data/test/fixtures/essays.yml +6 -6
  227. data/test/fixtures/faces.yml +11 -11
  228. data/test/fixtures/fk_test_has_fk.yml +3 -3
  229. data/test/fixtures/fk_test_has_pk.yml +1 -1
  230. data/test/fixtures/friendships.yml +4 -4
  231. data/test/fixtures/funny_jokes.yml +10 -10
  232. data/test/fixtures/interests.yml +33 -33
  233. data/test/fixtures/items.yml +3 -3
  234. data/test/fixtures/jobs.yml +7 -7
  235. data/test/fixtures/legacy_things.yml +3 -3
  236. data/test/fixtures/mateys.yml +4 -4
  237. data/test/fixtures/member_details.yml +8 -8
  238. data/test/fixtures/member_types.yml +6 -6
  239. data/test/fixtures/members.yml +11 -11
  240. data/test/fixtures/memberships.yml +34 -34
  241. data/test/fixtures/men.yml +5 -5
  242. data/test/fixtures/minimalistics.yml +2 -2
  243. data/test/fixtures/minivans.yml +5 -5
  244. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  245. data/test/fixtures/mixins.yml +29 -29
  246. data/test/fixtures/movies.yml +7 -7
  247. data/test/fixtures/naked/csv/accounts.csv +1 -1
  248. data/test/fixtures/naked/yml/accounts.yml +1 -1
  249. data/test/fixtures/naked/yml/companies.yml +1 -1
  250. data/test/fixtures/naked/yml/courses.yml +1 -1
  251. data/test/fixtures/organizations.yml +5 -5
  252. data/test/fixtures/other_topics.yml +42 -42
  253. data/test/fixtures/owners.yml +9 -9
  254. data/test/fixtures/parrots.yml +27 -27
  255. data/test/fixtures/parrots_pirates.yml +7 -7
  256. data/test/fixtures/people.yml +24 -24
  257. data/test/fixtures/peoples_treasures.yml +3 -3
  258. data/test/fixtures/pets.yml +19 -19
  259. data/test/fixtures/pirates.yml +12 -12
  260. data/test/fixtures/posts.yml +80 -80
  261. data/test/fixtures/price_estimates.yml +7 -7
  262. data/test/fixtures/products.yml +4 -4
  263. data/test/fixtures/projects.yml +7 -7
  264. data/test/fixtures/randomly_named_a9.yml +7 -7
  265. data/test/fixtures/ratings.yml +14 -14
  266. data/test/fixtures/readers.yml +11 -11
  267. data/test/fixtures/references.yml +17 -17
  268. data/test/fixtures/reserved_words/distinct.yml +5 -5
  269. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  270. data/test/fixtures/reserved_words/group.yml +14 -14
  271. data/test/fixtures/reserved_words/select.yml +8 -8
  272. data/test/fixtures/reserved_words/values.yml +7 -7
  273. data/test/fixtures/ships.yml +6 -6
  274. data/test/fixtures/speedometers.yml +8 -8
  275. data/test/fixtures/sponsors.yml +12 -12
  276. data/test/fixtures/string_key_objects.yml +7 -7
  277. data/test/fixtures/subscribers.yml +10 -10
  278. data/test/fixtures/subscriptions.yml +12 -12
  279. data/test/fixtures/taggings.yml +78 -78
  280. data/test/fixtures/tags.yml +11 -11
  281. data/test/fixtures/tasks.yml +7 -7
  282. data/test/fixtures/teapots.yml +3 -3
  283. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  284. data/test/fixtures/to_be_linked/users.yml +10 -10
  285. data/test/fixtures/topics.yml +49 -49
  286. data/test/fixtures/toys.yml +14 -14
  287. data/test/fixtures/traffic_lights.yml +9 -9
  288. data/test/fixtures/treasures.yml +10 -10
  289. data/test/fixtures/uuid_children.yml +3 -3
  290. data/test/fixtures/uuid_parents.yml +2 -2
  291. data/test/fixtures/variants.yml +4 -4
  292. data/test/fixtures/vegetables.yml +19 -19
  293. data/test/fixtures/vertices.yml +3 -3
  294. data/test/fixtures/warehouse_things.yml +2 -2
  295. data/test/fixtures/zines.yml +5 -5
  296. data/test/ibm_db_test.rb +24 -24
  297. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  298. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  299. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  300. data/test/migrations/missing/1000_people_have_middle_names.rb +8 -8
  301. data/test/migrations/missing/1_people_have_last_names.rb +8 -8
  302. data/test/migrations/missing/3_we_need_reminders.rb +11 -11
  303. data/test/migrations/missing/4_innocent_jointable.rb +11 -11
  304. data/test/migrations/rename/1_we_need_things.rb +10 -10
  305. data/test/migrations/rename/2_rename_things.rb +8 -8
  306. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  307. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  308. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  309. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  310. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  311. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  312. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  313. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  314. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  315. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  316. data/test/migrations/valid/2_we_need_reminders.rb +11 -11
  317. data/test/migrations/valid/3_innocent_jointable.rb +11 -11
  318. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  319. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +11 -11
  320. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +11 -11
  321. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  322. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  323. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  324. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  325. data/test/models/admin.rb +4 -4
  326. data/test/models/admin/account.rb +2 -2
  327. data/test/models/admin/randomly_named_c1.rb +3 -3
  328. data/test/models/admin/user.rb +40 -40
  329. data/test/models/aircraft.rb +4 -4
  330. data/test/models/arunit2_model.rb +3 -3
  331. data/test/models/author.rb +212 -212
  332. data/test/models/auto_id.rb +4 -4
  333. data/test/models/autoloadable/extra_firm.rb +2 -2
  334. data/test/models/binary.rb +1 -1
  335. data/test/models/bird.rb +12 -12
  336. data/test/models/book.rb +18 -18
  337. data/test/models/boolean.rb +2 -2
  338. data/test/models/bulb.rb +51 -51
  339. data/test/models/cake_designer.rb +3 -3
  340. data/test/models/car.rb +26 -26
  341. data/test/models/carrier.rb +2 -2
  342. data/test/models/categorization.rb +19 -19
  343. data/test/models/category.rb +35 -35
  344. data/test/models/chef.rb +7 -3
  345. data/test/models/citation.rb +3 -3
  346. data/test/models/club.rb +23 -23
  347. data/test/models/college.rb +10 -10
  348. data/test/models/column.rb +3 -3
  349. data/test/models/column_name.rb +3 -3
  350. data/test/models/comment.rb +64 -64
  351. data/test/models/company.rb +228 -225
  352. data/test/models/company_in_module.rb +98 -98
  353. data/test/models/computer.rb +3 -3
  354. data/test/models/contact.rb +41 -41
  355. data/test/models/contract.rb +20 -20
  356. data/test/models/country.rb +7 -7
  357. data/test/models/course.rb +6 -6
  358. data/test/models/customer.rb +77 -77
  359. data/test/models/customer_carrier.rb +14 -14
  360. data/test/models/dashboard.rb +3 -3
  361. data/test/models/default.rb +2 -2
  362. data/test/models/department.rb +4 -4
  363. data/test/models/developer.rb +255 -252
  364. data/test/models/dog.rb +5 -5
  365. data/test/models/dog_lover.rb +5 -5
  366. data/test/models/doubloon.rb +12 -12
  367. data/test/models/drink_designer.rb +3 -3
  368. data/test/models/edge.rb +5 -5
  369. data/test/models/electron.rb +5 -5
  370. data/test/models/engine.rb +4 -4
  371. data/test/models/entrant.rb +3 -3
  372. data/test/models/essay.rb +5 -5
  373. data/test/models/event.rb +2 -2
  374. data/test/models/eye.rb +37 -37
  375. data/test/models/face.rb +9 -9
  376. data/test/models/friendship.rb +6 -6
  377. data/test/models/guid.rb +1 -1
  378. data/test/models/hotel.rb +9 -6
  379. data/test/models/image.rb +3 -3
  380. data/test/models/interest.rb +5 -5
  381. data/test/models/invoice.rb +4 -4
  382. data/test/models/item.rb +7 -7
  383. data/test/models/job.rb +7 -7
  384. data/test/models/joke.rb +7 -7
  385. data/test/models/keyboard.rb +3 -3
  386. data/test/models/legacy_thing.rb +3 -3
  387. data/test/models/lesson.rb +11 -11
  388. data/test/models/line_item.rb +3 -3
  389. data/test/models/liquid.rb +4 -4
  390. data/test/models/man.rb +11 -11
  391. data/test/models/matey.rb +4 -4
  392. data/test/models/member.rb +41 -41
  393. data/test/models/member_detail.rb +7 -7
  394. data/test/models/member_type.rb +3 -3
  395. data/test/models/membership.rb +35 -35
  396. data/test/models/minimalistic.rb +2 -2
  397. data/test/models/minivan.rb +9 -9
  398. data/test/models/mixed_case_monkey.rb +3 -3
  399. data/test/models/molecule.rb +6 -6
  400. data/test/models/movie.rb +5 -5
  401. data/test/models/order.rb +4 -4
  402. data/test/models/organization.rb +14 -14
  403. data/test/models/owner.rb +34 -34
  404. data/test/models/parrot.rb +29 -29
  405. data/test/models/person.rb +143 -143
  406. data/test/models/personal_legacy_thing.rb +4 -4
  407. data/test/models/pet.rb +15 -15
  408. data/test/models/pirate.rb +92 -92
  409. data/test/models/possession.rb +3 -3
  410. data/test/models/post.rb +264 -264
  411. data/test/models/price_estimate.rb +4 -4
  412. data/test/models/professor.rb +5 -5
  413. data/test/models/project.rb +31 -29
  414. data/test/models/publisher.rb +2 -2
  415. data/test/models/publisher/article.rb +4 -4
  416. data/test/models/publisher/magazine.rb +3 -3
  417. data/test/models/randomly_named_c1.rb +3 -3
  418. data/test/models/rating.rb +4 -4
  419. data/test/models/reader.rb +23 -23
  420. data/test/models/record.rb +2 -2
  421. data/test/models/reference.rb +22 -22
  422. data/test/models/reply.rb +61 -61
  423. data/test/models/ship.rb +33 -33
  424. data/test/models/ship_part.rb +7 -7
  425. data/test/models/shop.rb +17 -17
  426. data/test/models/shop_account.rb +6 -6
  427. data/test/models/speedometer.rb +6 -6
  428. data/test/models/sponsor.rb +7 -7
  429. data/test/models/string_key_object.rb +3 -3
  430. data/test/models/student.rb +4 -4
  431. data/test/models/subject.rb +16 -16
  432. data/test/models/subscriber.rb +8 -8
  433. data/test/models/subscription.rb +4 -4
  434. data/test/models/tag.rb +7 -7
  435. data/test/models/tagging.rb +13 -13
  436. data/test/models/task.rb +5 -5
  437. data/test/models/topic.rb +124 -124
  438. data/test/models/toy.rb +6 -6
  439. data/test/models/traffic_light.rb +4 -4
  440. data/test/models/treasure.rb +14 -14
  441. data/test/models/treaty.rb +7 -7
  442. data/test/models/tyre.rb +11 -11
  443. data/test/models/uuid_child.rb +3 -3
  444. data/test/models/uuid_parent.rb +3 -3
  445. data/test/models/vegetables.rb +24 -24
  446. data/test/models/vehicle.rb +6 -6
  447. data/test/models/vertex.rb +9 -9
  448. data/test/models/warehouse_thing.rb +5 -5
  449. data/test/models/wheel.rb +3 -3
  450. data/test/models/without_table.rb +3 -3
  451. data/test/models/zine.rb +3 -3
  452. data/test/schema/mysql2_specific_schema.rb +58 -58
  453. data/test/schema/mysql_specific_schema.rb +70 -70
  454. data/test/schema/oracle_specific_schema.rb +43 -43
  455. data/test/schema/postgresql_specific_schema.rb +202 -202
  456. data/test/schema/schema.rb +952 -938
  457. data/test/schema/sqlite_specific_schema.rb +21 -21
  458. data/test/support/config.rb +43 -43
  459. data/test/support/connection.rb +22 -22
  460. data/test/support/connection_helper.rb +14 -14
  461. data/test/support/ddl_helper.rb +8 -8
  462. data/test/support/schema_dumping_helper.rb +20 -20
  463. metadata +2 -2
@@ -1,144 +1,144 @@
1
- require "cases/helper"
2
- require "models/pirate"
3
- require "models/bird"
4
-
5
- class NestedAttributesWithCallbacksTest < ActiveRecord::TestCase
6
- Pirate.has_many(:birds_with_add_load,
7
- :class_name => "Bird",
8
- :before_add => proc { |p,b|
9
- @@add_callback_called << b
10
- p.birds_with_add_load.to_a
11
- })
12
- Pirate.has_many(:birds_with_add,
13
- :class_name => "Bird",
14
- :before_add => proc { |p,b| @@add_callback_called << b })
15
-
16
- Pirate.accepts_nested_attributes_for(:birds_with_add_load,
17
- :birds_with_add,
18
- :allow_destroy => true)
19
-
20
- def setup
21
- @@add_callback_called = []
22
- @pirate = Pirate.new.tap do |pirate|
23
- pirate.catchphrase = "Don't call me!"
24
- pirate.birds_attributes = [{:name => 'Bird1'},{:name => 'Bird2'}]
25
- pirate.save!
26
- end
27
- @birds = @pirate.birds.to_a
28
- end
29
-
30
- def bird_to_update
31
- @birds[0]
32
- end
33
-
34
- def bird_to_destroy
35
- @birds[1]
36
- end
37
-
38
- def existing_birds_attributes
39
- @birds.map do |bird|
40
- bird.attributes.slice("id","name")
41
- end
42
- end
43
-
44
- def new_birds
45
- @pirate.birds_with_add.to_a - @birds
46
- end
47
-
48
- def new_bird_attributes
49
- [{'name' => "New Bird"}]
50
- end
51
-
52
- def destroy_bird_attributes
53
- [{'id' => bird_to_destroy.id.to_s, "_destroy" => true}]
54
- end
55
-
56
- def update_new_and_destroy_bird_attributes
57
- [{'id' => @birds[0].id.to_s, 'name' => 'New Name'},
58
- {'name' => "New Bird"},
59
- {'id' => bird_to_destroy.id.to_s, "_destroy" => true}]
60
- end
61
-
62
- # Characterizing when :before_add callback is called
63
- test ":before_add called for new bird when not loaded" do
64
- assert_not @pirate.birds_with_add.loaded?
65
- @pirate.birds_with_add_attributes = new_bird_attributes
66
- assert_new_bird_with_callback_called
67
- end
68
-
69
- test ":before_add called for new bird when loaded" do
70
- @pirate.birds_with_add.load_target
71
- @pirate.birds_with_add_attributes = new_bird_attributes
72
- assert_new_bird_with_callback_called
73
- end
74
-
75
- def assert_new_bird_with_callback_called
76
- assert_equal(1, new_birds.size)
77
- assert_equal(new_birds, @@add_callback_called)
78
- end
79
-
80
- test ":before_add not called for identical assignment when not loaded" do
81
- assert_not @pirate.birds_with_add.loaded?
82
- @pirate.birds_with_add_attributes = existing_birds_attributes
83
- assert_callbacks_not_called
84
- end
85
-
86
- test ":before_add not called for identical assignment when loaded" do
87
- @pirate.birds_with_add.load_target
88
- @pirate.birds_with_add_attributes = existing_birds_attributes
89
- assert_callbacks_not_called
90
- end
91
-
92
- test ":before_add not called for destroy assignment when not loaded" do
93
- assert_not @pirate.birds_with_add.loaded?
94
- @pirate.birds_with_add_attributes = destroy_bird_attributes
95
- assert_callbacks_not_called
96
- end
97
-
98
- test ":before_add not called for deletion assignment when loaded" do
99
- @pirate.birds_with_add.load_target
100
- @pirate.birds_with_add_attributes = destroy_bird_attributes
101
- assert_callbacks_not_called
102
- end
103
-
104
- def assert_callbacks_not_called
105
- assert_empty new_birds
106
- assert_empty @@add_callback_called
107
- end
108
-
109
- # Ensuring that the records in the association target are updated,
110
- # whether the association is loaded before or not
111
- test "Assignment updates records in target when not loaded" do
112
- assert_not @pirate.birds_with_add.loaded?
113
- @pirate.birds_with_add_attributes = update_new_and_destroy_bird_attributes
114
- assert_assignment_affects_records_in_target(:birds_with_add)
115
- end
116
-
117
- test "Assignment updates records in target when loaded" do
118
- @pirate.birds_with_add.load_target
119
- @pirate.birds_with_add_attributes = update_new_and_destroy_bird_attributes
120
- assert_assignment_affects_records_in_target(:birds_with_add)
121
- end
122
-
123
- test("Assignment updates records in target when not loaded" +
124
- " and callback loads target") do
125
- assert_not @pirate.birds_with_add_load.loaded?
126
- @pirate.birds_with_add_load_attributes = update_new_and_destroy_bird_attributes
127
- assert_assignment_affects_records_in_target(:birds_with_add_load)
128
- end
129
-
130
- test("Assignment updates records in target when loaded" +
131
- " and callback loads target") do
132
- @pirate.birds_with_add_load.load_target
133
- @pirate.birds_with_add_load_attributes = update_new_and_destroy_bird_attributes
134
- assert_assignment_affects_records_in_target(:birds_with_add_load)
135
- end
136
-
137
- def assert_assignment_affects_records_in_target(association_name)
138
- association = @pirate.send(association_name)
139
- assert association.detect {|b| b == bird_to_update }.name_changed?,
140
- 'Update record not updated'
141
- assert association.detect {|b| b == bird_to_destroy }.marked_for_destruction?,
142
- 'Destroy record not marked for destruction'
143
- end
144
- end
1
+ require "cases/helper"
2
+ require "models/pirate"
3
+ require "models/bird"
4
+
5
+ class NestedAttributesWithCallbacksTest < ActiveRecord::TestCase
6
+ Pirate.has_many(:birds_with_add_load,
7
+ :class_name => "Bird",
8
+ :before_add => proc { |p,b|
9
+ @@add_callback_called << b
10
+ p.birds_with_add_load.to_a
11
+ })
12
+ Pirate.has_many(:birds_with_add,
13
+ :class_name => "Bird",
14
+ :before_add => proc { |p,b| @@add_callback_called << b })
15
+
16
+ Pirate.accepts_nested_attributes_for(:birds_with_add_load,
17
+ :birds_with_add,
18
+ :allow_destroy => true)
19
+
20
+ def setup
21
+ @@add_callback_called = []
22
+ @pirate = Pirate.new.tap do |pirate|
23
+ pirate.catchphrase = "Don't call me!"
24
+ pirate.birds_attributes = [{:name => 'Bird1'},{:name => 'Bird2'}]
25
+ pirate.save!
26
+ end
27
+ @birds = @pirate.birds.to_a
28
+ end
29
+
30
+ def bird_to_update
31
+ @birds[0]
32
+ end
33
+
34
+ def bird_to_destroy
35
+ @birds[1]
36
+ end
37
+
38
+ def existing_birds_attributes
39
+ @birds.map do |bird|
40
+ bird.attributes.slice("id","name")
41
+ end
42
+ end
43
+
44
+ def new_birds
45
+ @pirate.birds_with_add.to_a - @birds
46
+ end
47
+
48
+ def new_bird_attributes
49
+ [{'name' => "New Bird"}]
50
+ end
51
+
52
+ def destroy_bird_attributes
53
+ [{'id' => bird_to_destroy.id.to_s, "_destroy" => true}]
54
+ end
55
+
56
+ def update_new_and_destroy_bird_attributes
57
+ [{'id' => @birds[0].id.to_s, 'name' => 'New Name'},
58
+ {'name' => "New Bird"},
59
+ {'id' => bird_to_destroy.id.to_s, "_destroy" => true}]
60
+ end
61
+
62
+ # Characterizing when :before_add callback is called
63
+ test ":before_add called for new bird when not loaded" do
64
+ assert_not @pirate.birds_with_add.loaded?
65
+ @pirate.birds_with_add_attributes = new_bird_attributes
66
+ assert_new_bird_with_callback_called
67
+ end
68
+
69
+ test ":before_add called for new bird when loaded" do
70
+ @pirate.birds_with_add.load_target
71
+ @pirate.birds_with_add_attributes = new_bird_attributes
72
+ assert_new_bird_with_callback_called
73
+ end
74
+
75
+ def assert_new_bird_with_callback_called
76
+ assert_equal(1, new_birds.size)
77
+ assert_equal(new_birds, @@add_callback_called)
78
+ end
79
+
80
+ test ":before_add not called for identical assignment when not loaded" do
81
+ assert_not @pirate.birds_with_add.loaded?
82
+ @pirate.birds_with_add_attributes = existing_birds_attributes
83
+ assert_callbacks_not_called
84
+ end
85
+
86
+ test ":before_add not called for identical assignment when loaded" do
87
+ @pirate.birds_with_add.load_target
88
+ @pirate.birds_with_add_attributes = existing_birds_attributes
89
+ assert_callbacks_not_called
90
+ end
91
+
92
+ test ":before_add not called for destroy assignment when not loaded" do
93
+ assert_not @pirate.birds_with_add.loaded?
94
+ @pirate.birds_with_add_attributes = destroy_bird_attributes
95
+ assert_callbacks_not_called
96
+ end
97
+
98
+ test ":before_add not called for deletion assignment when loaded" do
99
+ @pirate.birds_with_add.load_target
100
+ @pirate.birds_with_add_attributes = destroy_bird_attributes
101
+ assert_callbacks_not_called
102
+ end
103
+
104
+ def assert_callbacks_not_called
105
+ assert_empty new_birds
106
+ assert_empty @@add_callback_called
107
+ end
108
+
109
+ # Ensuring that the records in the association target are updated,
110
+ # whether the association is loaded before or not
111
+ test "Assignment updates records in target when not loaded" do
112
+ assert_not @pirate.birds_with_add.loaded?
113
+ @pirate.birds_with_add_attributes = update_new_and_destroy_bird_attributes
114
+ assert_assignment_affects_records_in_target(:birds_with_add)
115
+ end
116
+
117
+ test "Assignment updates records in target when loaded" do
118
+ @pirate.birds_with_add.load_target
119
+ @pirate.birds_with_add_attributes = update_new_and_destroy_bird_attributes
120
+ assert_assignment_affects_records_in_target(:birds_with_add)
121
+ end
122
+
123
+ test("Assignment updates records in target when not loaded" +
124
+ " and callback loads target") do
125
+ assert_not @pirate.birds_with_add_load.loaded?
126
+ @pirate.birds_with_add_load_attributes = update_new_and_destroy_bird_attributes
127
+ assert_assignment_affects_records_in_target(:birds_with_add_load)
128
+ end
129
+
130
+ test("Assignment updates records in target when loaded" +
131
+ " and callback loads target") do
132
+ @pirate.birds_with_add_load.load_target
133
+ @pirate.birds_with_add_load_attributes = update_new_and_destroy_bird_attributes
134
+ assert_assignment_affects_records_in_target(:birds_with_add_load)
135
+ end
136
+
137
+ def assert_assignment_affects_records_in_target(association_name)
138
+ association = @pirate.send(association_name)
139
+ assert association.detect {|b| b == bird_to_update }.name_changed?,
140
+ 'Update record not updated'
141
+ assert association.detect {|b| b == bird_to_destroy }.marked_for_destruction?,
142
+ 'Destroy record not marked for destruction'
143
+ end
144
+ end
@@ -1,909 +1,909 @@
1
- require "cases/helper"
2
- require 'models/aircraft'
3
- require 'models/post'
4
- require 'models/comment'
5
- require 'models/author'
6
- require 'models/topic'
7
- require 'models/reply'
8
- require 'models/category'
9
- require 'models/company'
10
- require 'models/developer'
11
- require 'models/computer'
12
- require 'models/project'
13
- require 'models/minimalistic'
14
- require 'models/warehouse_thing'
15
- require 'models/parrot'
16
- require 'models/minivan'
17
- require 'models/owner'
18
- require 'models/person'
19
- require 'models/pet'
20
- require 'models/toy'
21
- require 'rexml/document'
22
-
23
- class PersistenceTest < ActiveRecord::TestCase
24
- fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse_things', :authors, :author_addresses, :categorizations, :categories, :posts, :minivans, :pets, :toys
25
-
26
- # Oracle UPDATE does not support ORDER BY
27
- unless current_adapter?(:OracleAdapter)
28
- def test_update_all_ignores_order_without_limit_from_association
29
- author = authors(:david)
30
- assert_nothing_raised do
31
- assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
32
- end
33
- end
34
-
35
- def test_update_all_doesnt_ignore_order
36
- assert_equal authors(:david).id + 1, authors(:mary).id # make sure there is going to be a duplicate PK error
37
- test_update_with_order_succeeds = lambda do |order|
38
- begin
39
- Author.order(order).update_all('id = id + 1')
40
- rescue ActiveRecord::ActiveRecordError
41
- false
42
- end
43
- end
44
-
45
- if !current_adapter?(:IBM_DBAdapter) && test_update_with_order_succeeds.call('id DESC')
46
- # The update below goes on successfully in DB2.
47
- assert !test_update_with_order_succeeds.call('id ASC') # test that this wasn't a fluke and using an incorrect order results in an exception
48
- else
49
- # test that we're failing because the current Arel's engine doesn't support UPDATE ORDER BY queries is using subselects instead
50
- assert_sql(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\Z/i) do
51
- test_update_with_order_succeeds.call('id DESC')
52
- end
53
- end
54
- end
55
-
56
- def test_update_all_with_order_and_limit_updates_subset_only
57
- author = authors(:david)
58
- assert_nothing_raised do
59
- assert_equal 1, author.posts_sorted_by_id_limited.size
60
- assert_equal 2, author.posts_sorted_by_id_limited.limit(2).to_a.size
61
- assert_equal 1, author.posts_sorted_by_id_limited.update_all([ "body = ?", "bulk update!" ])
62
- assert_equal "bulk update!", posts(:welcome).body
63
- assert_not_equal "bulk update!", posts(:thinking).body
64
- end
65
- end
66
- end
67
-
68
- def test_update_many
69
- topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
70
- updated = Topic.update(topic_data.keys, topic_data.values)
71
-
72
- assert_equal 2, updated.size
73
- assert_equal "1 updated", Topic.find(1).content
74
- assert_equal "2 updated", Topic.find(2).content
75
- end
76
-
77
- def test_delete_all
78
- assert Topic.count > 0
79
-
80
- assert_equal Topic.count, Topic.delete_all
81
- end
82
-
83
- def test_delete_all_with_joins_and_where_part_is_hash
84
- where_args = {:toys => {:name => 'Bone'}}
85
- count = Pet.joins(:toys).where(where_args).count
86
-
87
- assert_equal count, 1
88
- assert_equal count, Pet.joins(:toys).where(where_args).delete_all
89
- end
90
-
91
- def test_delete_all_with_joins_and_where_part_is_not_hash
92
- where_args = ['toys.name = ?', 'Bone']
93
- count = Pet.joins(:toys).where(where_args).count
94
-
95
- assert_equal count, 1
96
- assert_equal count, Pet.joins(:toys).where(where_args).delete_all
97
- end
98
-
99
- def test_increment_attribute
100
- assert_equal 50, accounts(:signals37).credit_limit
101
- accounts(:signals37).increment! :credit_limit
102
- assert_equal 51, accounts(:signals37, :reload).credit_limit
103
-
104
- accounts(:signals37).increment(:credit_limit).increment!(:credit_limit)
105
- assert_equal 53, accounts(:signals37, :reload).credit_limit
106
- end
107
-
108
- def test_increment_nil_attribute
109
- assert_nil topics(:first).parent_id
110
- topics(:first).increment! :parent_id
111
- assert_equal 1, topics(:first).parent_id
112
- end
113
-
114
- def test_increment_attribute_by
115
- assert_equal 50, accounts(:signals37).credit_limit
116
- accounts(:signals37).increment! :credit_limit, 5
117
- assert_equal 55, accounts(:signals37, :reload).credit_limit
118
-
119
- accounts(:signals37).increment(:credit_limit, 1).increment!(:credit_limit, 3)
120
- assert_equal 59, accounts(:signals37, :reload).credit_limit
121
- end
122
-
123
- def test_destroy_all
124
- conditions = "author_name = 'Mary'"
125
- topics_by_mary = Topic.all.merge!(:where => conditions, :order => 'id').to_a
126
- assert ! topics_by_mary.empty?
127
-
128
- assert_difference('Topic.count', -topics_by_mary.size) do
129
- destroyed = Topic.destroy_all(conditions).sort_by(&:id)
130
- assert_equal topics_by_mary, destroyed
131
- assert destroyed.all? { |topic| topic.frozen? }, "destroyed topics should be frozen"
132
- end
133
- end
134
-
135
- def test_destroy_many
136
- clients = Client.all.merge!(:order => 'id').find([2, 3])
137
-
138
- assert_difference('Client.count', -2) do
139
- destroyed = Client.destroy([2, 3]).sort_by(&:id)
140
- assert_equal clients, destroyed
141
- assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
142
- end
143
- end
144
-
145
- def test_becomes
146
- assert_kind_of Reply, topics(:first).becomes(Reply)
147
- assert_equal "The First Topic", topics(:first).becomes(Reply).title
148
- end
149
-
150
- def test_becomes_includes_errors
151
- company = Company.new(:name => nil)
152
- assert !company.valid?
153
- original_errors = company.errors
154
- client = company.becomes(Client)
155
- assert_equal original_errors, client.errors
156
- end
157
-
158
- def test_dupd_becomes_persists_changes_from_the_original
159
- original = topics(:first)
160
- copy = original.dup.becomes(Reply)
161
- copy.save!
162
- assert_equal "The First Topic", Topic.find(copy.id).title
163
- end
164
-
165
- def test_becomes_includes_changed_attributes
166
- company = Company.new(name: "37signals")
167
- client = company.becomes(Client)
168
- assert_equal "37signals", client.name
169
- assert_equal %w{name}, client.changed
170
- end
171
-
172
- def test_delete_many
173
- original_count = Topic.count
174
- Topic.delete(deleting = [1, 2])
175
- assert_equal original_count - deleting.size, Topic.count
176
- end
177
-
178
- def test_decrement_attribute
179
- assert_equal 50, accounts(:signals37).credit_limit
180
-
181
- accounts(:signals37).decrement!(:credit_limit)
182
- assert_equal 49, accounts(:signals37, :reload).credit_limit
183
-
184
- accounts(:signals37).decrement(:credit_limit).decrement!(:credit_limit)
185
- assert_equal 47, accounts(:signals37, :reload).credit_limit
186
- end
187
-
188
- def test_decrement_attribute_by
189
- assert_equal 50, accounts(:signals37).credit_limit
190
- accounts(:signals37).decrement! :credit_limit, 5
191
- assert_equal 45, accounts(:signals37, :reload).credit_limit
192
-
193
- accounts(:signals37).decrement(:credit_limit, 1).decrement!(:credit_limit, 3)
194
- assert_equal 41, accounts(:signals37, :reload).credit_limit
195
- end
196
-
197
- def test_create
198
- topic = Topic.new
199
- topic.title = "New Topic"
200
- topic.save
201
- topic_reloaded = Topic.find(topic.id)
202
- assert_equal("New Topic", topic_reloaded.title)
203
- end
204
-
205
- def test_save!
206
- topic = Topic.new(:title => "New Topic")
207
- assert topic.save!
208
-
209
- reply = WrongReply.new
210
- assert_raise(ActiveRecord::RecordInvalid) { reply.save! }
211
- end
212
-
213
- def test_save_null_string_attributes
214
- topic = Topic.find(1)
215
- topic.attributes = { "title" => "null", "author_name" => "null" }
216
- topic.save!
217
- topic.reload
218
- assert_equal("null", topic.title)
219
- assert_equal("null", topic.author_name)
220
- end
221
-
222
- def test_save_nil_string_attributes
223
- topic = Topic.find(1)
224
- topic.title = nil
225
- topic.save!
226
- topic.reload
227
- assert_nil topic.title
228
- end
229
-
230
- def test_save_for_record_with_only_primary_key
231
- minimalistic = Minimalistic.new
232
- assert_nothing_raised { minimalistic.save }
233
- end
234
-
235
- def test_save_for_record_with_only_primary_key_that_is_provided
236
- assert_nothing_raised { Minimalistic.create!(:id => 2) }
237
- end
238
-
239
- def test_save_with_duping_of_destroyed_object
240
- developer = Developer.first
241
- developer.destroy
242
- new_developer = developer.dup
243
- new_developer.save
244
- assert new_developer.persisted?
245
- assert_not new_developer.destroyed?
246
- end
247
-
248
- def test_create_many
249
- topics = Topic.create([ { "title" => "first" }, { "title" => "second" }])
250
- assert_equal 2, topics.size
251
- assert_equal "first", topics.first.title
252
- end
253
-
254
- def test_create_columns_not_equal_attributes
255
- topic = Topic.instantiate(
256
- 'title' => 'Another New Topic',
257
- 'does_not_exist' => 'test'
258
- )
259
- assert_nothing_raised { topic.save }
260
- end
261
-
262
- def test_create_through_factory_with_block
263
- topic = Topic.create("title" => "New Topic") do |t|
264
- t.author_name = "David"
265
- end
266
- assert_equal("New Topic", topic.title)
267
- assert_equal("David", topic.author_name)
268
- end
269
-
270
- def test_create_many_through_factory_with_block
271
- topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) do |t|
272
- t.author_name = "David"
273
- end
274
- assert_equal 2, topics.size
275
- topic1, topic2 = Topic.find(topics[0].id), Topic.find(topics[1].id)
276
- assert_equal "first", topic1.title
277
- assert_equal "David", topic1.author_name
278
- assert_equal "second", topic2.title
279
- assert_equal "David", topic2.author_name
280
- end
281
-
282
- def test_update_object
283
- topic = Topic.new
284
- topic.title = "Another New Topic"
285
- topic.written_on = "2003-12-12 23:23:00"
286
- topic.save
287
- topic_reloaded = Topic.find(topic.id)
288
- assert_equal("Another New Topic", topic_reloaded.title)
289
-
290
- topic_reloaded.title = "Updated topic"
291
- topic_reloaded.save
292
-
293
- topic_reloaded_again = Topic.find(topic.id)
294
-
295
- assert_equal("Updated topic", topic_reloaded_again.title)
296
- end
297
-
298
- def test_update_columns_not_equal_attributes
299
- topic = Topic.new
300
- topic.title = "Still another topic"
301
- topic.save
302
-
303
- topic_reloaded = Topic.instantiate(topic.attributes.merge('does_not_exist' => 'test'))
304
- topic_reloaded.title = 'A New Topic'
305
- assert_nothing_raised { topic_reloaded.save }
306
- end
307
-
308
- def test_update_for_record_with_only_primary_key
309
- minimalistic = minimalistics(:first)
310
- assert_nothing_raised { minimalistic.save }
311
- end
312
-
313
- def test_update_sti_type
314
- assert_instance_of Reply, topics(:second)
315
-
316
- topic = topics(:second).becomes!(Topic)
317
- assert_instance_of Topic, topic
318
- topic.save!
319
- assert_instance_of Topic, Topic.find(topic.id)
320
- end
321
-
322
- def test_preserve_original_sti_type
323
- reply = topics(:second)
324
- assert_equal "Reply", reply.type
325
-
326
- topic = reply.becomes(Topic)
327
- assert_equal "Reply", reply.type
328
-
329
- assert_instance_of Topic, topic
330
- assert_equal "Reply", topic.type
331
- end
332
-
333
- def test_update_sti_subclass_type
334
- assert_instance_of Topic, topics(:first)
335
-
336
- reply = topics(:first).becomes!(Reply)
337
- assert_instance_of Reply, reply
338
- reply.save!
339
- assert_instance_of Reply, Reply.find(reply.id)
340
- end
341
-
342
- def test_update_after_create
343
- klass = Class.new(Topic) do
344
- def self.name; 'Topic'; end
345
- after_create do
346
- update_attribute("author_name", "David")
347
- end
348
- end
349
- topic = klass.new
350
- topic.title = "Another New Topic"
351
- topic.save
352
-
353
- topic_reloaded = Topic.find(topic.id)
354
- assert_equal("Another New Topic", topic_reloaded.title)
355
- assert_equal("David", topic_reloaded.author_name)
356
- end
357
-
358
- def test_delete
359
- topic = Topic.find(1)
360
- assert_equal topic, topic.delete, 'topic.delete did not return self'
361
- assert topic.frozen?, 'topic not frozen after delete'
362
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
363
- end
364
-
365
- def test_delete_doesnt_run_callbacks
366
- Topic.find(1).delete
367
- assert_not_nil Topic.find(2)
368
- end
369
-
370
- def test_destroy
371
- topic = Topic.find(1)
372
- assert_equal topic, topic.destroy, 'topic.destroy did not return self'
373
- assert topic.frozen?, 'topic not frozen after destroy'
374
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
375
- end
376
-
377
- def test_destroy!
378
- topic = Topic.find(1)
379
- assert_equal topic, topic.destroy!, 'topic.destroy! did not return self'
380
- assert topic.frozen?, 'topic not frozen after destroy!'
381
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
382
- end
383
-
384
- def test_record_not_found_exception
385
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(99999) }
386
- end
387
-
388
- def test_update_all
389
- assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'")
390
- assert_equal "bulk updated!", Topic.find(1).content
391
- assert_equal "bulk updated!", Topic.find(2).content
392
-
393
- assert_equal Topic.count, Topic.update_all(['content = ?', 'bulk updated again!'])
394
- assert_equal "bulk updated again!", Topic.find(1).content
395
- assert_equal "bulk updated again!", Topic.find(2).content
396
-
397
- assert_equal Topic.count, Topic.update_all(['content = ?', nil])
398
- assert_nil Topic.find(1).content
399
- end
400
-
401
- def test_update_all_with_hash
402
- assert_not_nil Topic.find(1).last_read
403
- assert_equal Topic.count, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
404
- assert_equal "bulk updated with hash!", Topic.find(1).content
405
- assert_equal "bulk updated with hash!", Topic.find(2).content
406
- assert_nil Topic.find(1).last_read
407
- assert_nil Topic.find(2).last_read
408
- end
409
-
410
- def test_update_all_with_non_standard_table_name
411
- assert_equal 1, WarehouseThing.where(id: 1).update_all(['value = ?', 0])
412
- assert_equal 0, WarehouseThing.find(1).value
413
- end
414
-
415
- def test_delete_new_record
416
- client = Client.new
417
- client.delete
418
- assert client.frozen?
419
- end
420
-
421
- def test_delete_record_with_associations
422
- client = Client.find(3)
423
- client.delete
424
- assert client.frozen?
425
- assert_kind_of Firm, client.firm
426
- assert_raise(RuntimeError) { client.name = "something else" }
427
- end
428
-
429
- def test_destroy_new_record
430
- client = Client.new
431
- client.destroy
432
- assert client.frozen?
433
- end
434
-
435
- def test_destroy_record_with_associations
436
- client = Client.find(3)
437
- client.destroy
438
- assert client.frozen?
439
- assert_kind_of Firm, client.firm
440
- assert_raise(RuntimeError) { client.name = "something else" }
441
- end
442
-
443
- def test_update_attribute
444
- assert !Topic.find(1).approved?
445
- Topic.find(1).update_attribute("approved", true)
446
- assert Topic.find(1).approved?
447
-
448
- Topic.find(1).update_attribute(:approved, false)
449
- assert !Topic.find(1).approved?
450
- end
451
-
452
- def test_update_attribute_for_readonly_attribute
453
- minivan = Minivan.find('m1')
454
- assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_attribute(:color, 'black') }
455
- end
456
-
457
- def test_update_attribute_with_one_updated
458
- t = Topic.first
459
- t.update_attribute(:title, 'super_title')
460
- assert_equal 'super_title', t.title
461
- assert !t.changed?, "topic should not have changed"
462
- assert !t.title_changed?, "title should not have changed"
463
- assert_nil t.title_change, 'title change should be nil'
464
-
465
- t.reload
466
- assert_equal 'super_title', t.title
467
- end
468
-
469
- def test_update_attribute_for_updated_at_on
470
- developer = Developer.find(1)
471
- prev_month = Time.now.prev_month.change(usec: 0)
472
-
473
- developer.update_attribute(:updated_at, prev_month)
474
- assert_equal prev_month, developer.updated_at
475
-
476
- developer.update_attribute(:salary, 80001)
477
- assert_not_equal prev_month, developer.updated_at
478
-
479
- developer.reload
480
- assert_not_equal prev_month, developer.updated_at
481
- end
482
-
483
- def test_update_column
484
- topic = Topic.find(1)
485
- topic.update_column("approved", true)
486
- assert topic.approved?
487
- topic.reload
488
- assert topic.approved?
489
-
490
- topic.update_column(:approved, false)
491
- assert !topic.approved?
492
- topic.reload
493
- assert !topic.approved?
494
- end
495
-
496
- def test_update_column_should_not_use_setter_method
497
- dev = Developer.find(1)
498
- dev.instance_eval { def salary=(value); write_attribute(:salary, value * 2); end }
499
-
500
- dev.update_column(:salary, 80000)
501
- assert_equal 80000, dev.salary
502
-
503
- dev.reload
504
- assert_equal 80000, dev.salary
505
- end
506
-
507
- def test_update_column_should_raise_exception_if_new_record
508
- topic = Topic.new
509
- assert_raises(ActiveRecord::ActiveRecordError) { topic.update_column("approved", false) }
510
- end
511
-
512
- def test_update_column_should_not_leave_the_object_dirty
513
- topic = Topic.find(1)
514
- topic.update_column("content", "--- Have a nice day\n...\n")
515
-
516
- topic.reload
517
- topic.update_column(:content, "--- You too\n...\n")
518
- assert_equal [], topic.changed
519
-
520
- topic.reload
521
- topic.update_column("content", "--- Have a nice day\n...\n")
522
- assert_equal [], topic.changed
523
- end
524
-
525
- def test_update_column_with_model_having_primary_key_other_than_id
526
- minivan = Minivan.find('m1')
527
- new_name = 'sebavan'
528
-
529
- minivan.update_column(:name, new_name)
530
- assert_equal new_name, minivan.name
531
- end
532
-
533
- def test_update_column_for_readonly_attribute
534
- minivan = Minivan.find('m1')
535
- prev_color = minivan.color
536
- assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_column(:color, 'black') }
537
- assert_equal prev_color, minivan.color
538
- end
539
-
540
- def test_update_column_should_not_modify_updated_at
541
- developer = Developer.find(1)
542
- prev_month = Time.now.prev_month.change(usec: 0)
543
-
544
- developer.update_column(:updated_at, prev_month)
545
- assert_equal prev_month, developer.updated_at
546
-
547
- developer.update_column(:salary, 80001)
548
- assert_equal prev_month, developer.updated_at
549
-
550
- developer.reload
551
- assert_equal prev_month.to_i, developer.updated_at.to_i
552
- end
553
-
554
- def test_update_column_with_one_changed_and_one_updated
555
- t = Topic.order('id').limit(1).first
556
- author_name = t.author_name
557
- t.author_name = 'John'
558
- t.update_column(:title, 'super_title')
559
- assert_equal 'John', t.author_name
560
- assert_equal 'super_title', t.title
561
- assert t.changed?, "topic should have changed"
562
- assert t.author_name_changed?, "author_name should have changed"
563
-
564
- t.reload
565
- assert_equal author_name, t.author_name
566
- assert_equal 'super_title', t.title
567
- end
568
-
569
- def test_update_column_with_default_scope
570
- developer = DeveloperCalledDavid.first
571
- developer.name = 'John'
572
- developer.save!
573
-
574
- assert developer.update_column(:name, 'Will'), 'did not update record due to default scope'
575
- end
576
-
577
- def test_update_columns
578
- topic = Topic.find(1)
579
- topic.update_columns({ "approved" => true, title: "Sebastian Topic" })
580
- assert topic.approved?
581
- assert_equal "Sebastian Topic", topic.title
582
- topic.reload
583
- assert topic.approved?
584
- assert_equal "Sebastian Topic", topic.title
585
- end
586
-
587
- def test_update_columns_should_not_use_setter_method
588
- dev = Developer.find(1)
589
- dev.instance_eval { def salary=(value); write_attribute(:salary, value * 2); end }
590
-
591
- dev.update_columns(salary: 80000)
592
- assert_equal 80000, dev.salary
593
-
594
- dev.reload
595
- assert_equal 80000, dev.salary
596
- end
597
-
598
- def test_update_columns_should_raise_exception_if_new_record
599
- topic = Topic.new
600
- assert_raises(ActiveRecord::ActiveRecordError) { topic.update_columns({ approved: false }) }
601
- end
602
-
603
- def test_update_columns_should_not_leave_the_object_dirty
604
- topic = Topic.find(1)
605
- topic.update({ "content" => "--- Have a nice day\n...\n", :author_name => "Jose" })
606
-
607
- topic.reload
608
- topic.update_columns({ content: "--- You too\n...\n", "author_name" => "Sebastian" })
609
- assert_equal [], topic.changed
610
-
611
- topic.reload
612
- topic.update_columns({ content: "--- Have a nice day\n...\n", author_name: "Jose" })
613
- assert_equal [], topic.changed
614
- end
615
-
616
- def test_update_columns_with_model_having_primary_key_other_than_id
617
- minivan = Minivan.find('m1')
618
- new_name = 'sebavan'
619
-
620
- minivan.update_columns(name: new_name)
621
- assert_equal new_name, minivan.name
622
- end
623
-
624
- def test_update_columns_with_one_readonly_attribute
625
- minivan = Minivan.find('m1')
626
- prev_color = minivan.color
627
- prev_name = minivan.name
628
- assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_columns({ name: "My old minivan", color: 'black' }) }
629
- assert_equal prev_color, minivan.color
630
- assert_equal prev_name, minivan.name
631
-
632
- minivan.reload
633
- assert_equal prev_color, minivan.color
634
- assert_equal prev_name, minivan.name
635
- end
636
-
637
- def test_update_columns_should_not_modify_updated_at
638
- developer = Developer.find(1)
639
- prev_month = Time.now.prev_month.change(usec: 0)
640
-
641
- developer.update_columns(updated_at: prev_month)
642
- assert_equal prev_month, developer.updated_at
643
-
644
- developer.update_columns(salary: 80000)
645
- assert_equal prev_month, developer.updated_at
646
- assert_equal 80000, developer.salary
647
-
648
- developer.reload
649
- assert_equal prev_month.to_i, developer.updated_at.to_i
650
- assert_equal 80000, developer.salary
651
- end
652
-
653
- def test_update_columns_with_one_changed_and_one_updated
654
- t = Topic.order('id').limit(1).first
655
- author_name = t.author_name
656
- t.author_name = 'John'
657
- t.update_columns(title: 'super_title')
658
- assert_equal 'John', t.author_name
659
- assert_equal 'super_title', t.title
660
- assert t.changed?, "topic should have changed"
661
- assert t.author_name_changed?, "author_name should have changed"
662
-
663
- t.reload
664
- assert_equal author_name, t.author_name
665
- assert_equal 'super_title', t.title
666
- end
667
-
668
- def test_update_columns_changing_id
669
- topic = Topic.find(1)
670
- topic.update_columns(id: 123)
671
- assert_equal 123, topic.id
672
- topic.reload
673
- assert_equal 123, topic.id
674
- end
675
-
676
- def test_update_columns_returns_boolean
677
- topic = Topic.find(1)
678
- assert_equal true, topic.update_columns(title: "New title")
679
- end
680
-
681
- def test_update_columns_with_default_scope
682
- developer = DeveloperCalledDavid.first
683
- developer.name = 'John'
684
- developer.save!
685
-
686
- assert developer.update_columns(name: 'Will'), 'did not update record due to default scope'
687
- end
688
-
689
- def test_update
690
- topic = Topic.find(1)
691
- assert !topic.approved?
692
- assert_equal "The First Topic", topic.title
693
-
694
- topic.update("approved" => true, "title" => "The First Topic Updated")
695
- topic.reload
696
- assert topic.approved?
697
- assert_equal "The First Topic Updated", topic.title
698
-
699
- topic.update(approved: false, title: "The First Topic")
700
- topic.reload
701
- assert !topic.approved?
702
- assert_equal "The First Topic", topic.title
703
- end
704
-
705
- def test_update_attributes
706
- topic = Topic.find(1)
707
- assert !topic.approved?
708
- assert_equal "The First Topic", topic.title
709
-
710
- topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
711
- topic.reload
712
- assert topic.approved?
713
- assert_equal "The First Topic Updated", topic.title
714
-
715
- topic.update_attributes(approved: false, title: "The First Topic")
716
- topic.reload
717
- assert !topic.approved?
718
- assert_equal "The First Topic", topic.title
719
-
720
- assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
721
- topic.update_attributes(id: 3, title: "Hm is it possible?")
722
- end
723
- assert_not_equal "Hm is it possible?", Topic.find(3).title
724
-
725
- topic.update_attributes(id: 1234)
726
- assert_nothing_raised { topic.reload }
727
- assert_equal topic.title, Topic.find(1234).title
728
- end
729
-
730
- def test_update_attributes_parameters
731
- topic = Topic.find(1)
732
- assert_nothing_raised do
733
- topic.update_attributes({})
734
- end
735
-
736
- assert_raises(ArgumentError) do
737
- topic.update_attributes(nil)
738
- end
739
- end
740
-
741
- def test_update!
742
- Reply.validates_presence_of(:title)
743
- reply = Reply.find(2)
744
- assert_equal "The Second Topic of the day", reply.title
745
- assert_equal "Have a nice day", reply.content
746
-
747
- reply.update!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
748
- reply.reload
749
- assert_equal "The Second Topic of the day updated", reply.title
750
- assert_equal "Have a nice evening", reply.content
751
-
752
- reply.update!(title: "The Second Topic of the day", content: "Have a nice day")
753
- reply.reload
754
- assert_equal "The Second Topic of the day", reply.title
755
- assert_equal "Have a nice day", reply.content
756
-
757
- assert_raise(ActiveRecord::RecordInvalid) { reply.update!(title: nil, content: "Have a nice evening") }
758
- ensure
759
- Reply.clear_validators!
760
- end
761
-
762
- def test_update_attributes!
763
- Reply.validates_presence_of(:title)
764
- reply = Reply.find(2)
765
- assert_equal "The Second Topic of the day", reply.title
766
- assert_equal "Have a nice day", reply.content
767
-
768
- reply.update_attributes!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
769
- reply.reload
770
- assert_equal "The Second Topic of the day updated", reply.title
771
- assert_equal "Have a nice evening", reply.content
772
-
773
- reply.update_attributes!(title: "The Second Topic of the day", content: "Have a nice day")
774
- reply.reload
775
- assert_equal "The Second Topic of the day", reply.title
776
- assert_equal "Have a nice day", reply.content
777
-
778
- assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(title: nil, content: "Have a nice evening") }
779
- ensure
780
- Reply.clear_validators!
781
- end
782
-
783
- def test_destroyed_returns_boolean
784
- developer = Developer.first
785
- assert_equal false, developer.destroyed?
786
- developer.destroy
787
- assert_equal true, developer.destroyed?
788
-
789
- developer = Developer.last
790
- assert_equal false, developer.destroyed?
791
- developer.delete
792
- assert_equal true, developer.destroyed?
793
- end
794
-
795
- def test_persisted_returns_boolean
796
- developer = Developer.new(:name => "Jose")
797
- assert_equal false, developer.persisted?
798
- developer.save!
799
- assert_equal true, developer.persisted?
800
-
801
- developer = Developer.first
802
- assert_equal true, developer.persisted?
803
- developer.destroy
804
- assert_equal false, developer.persisted?
805
-
806
- developer = Developer.last
807
- assert_equal true, developer.persisted?
808
- developer.delete
809
- assert_equal false, developer.persisted?
810
- end
811
-
812
- def test_class_level_destroy
813
- should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
814
- Topic.find(1).replies << should_be_destroyed_reply
815
-
816
- Topic.destroy(1)
817
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
818
- assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) }
819
- end
820
-
821
- def test_class_level_delete
822
- should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
823
- Topic.find(1).replies << should_be_destroyed_reply
824
-
825
- Topic.delete(1)
826
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
827
- assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) }
828
- end
829
-
830
- def test_create_with_custom_timestamps
831
- custom_datetime = 1.hour.ago.beginning_of_day
832
-
833
- %w(created_at created_on updated_at updated_on).each do |attribute|
834
- parrot = LiveParrot.create(:name => "colombian", attribute => custom_datetime)
835
- assert_equal custom_datetime, parrot[attribute]
836
- end
837
- end
838
-
839
- def test_persist_inherited_class_with_different_table_name
840
- minimalistic_aircrafts = Class.new(Minimalistic) do
841
- self.table_name = "aircraft"
842
- end
843
-
844
- assert_difference "Aircraft.count", 1 do
845
- aircraft = minimalistic_aircrafts.create(name: "Wright Flyer")
846
- aircraft.name = "Wright Glider"
847
- aircraft.save
848
- end
849
-
850
- assert_equal "Wright Glider", Aircraft.last.name
851
- end
852
-
853
- def test_instantiate_creates_a_new_instance
854
- post = Post.instantiate("title" => "appropriate documentation", "type" => "SpecialPost")
855
- assert_equal "appropriate documentation", post.title
856
- assert_instance_of SpecialPost, post
857
-
858
- # body was not initialized
859
- assert_raises ActiveModel::MissingAttributeError do
860
- post.body
861
- end
862
- end
863
-
864
- def test_reload_removes_custom_selects
865
- post = Post.select('posts.*, 1 as wibble').last!
866
-
867
- assert_equal 1, post[:wibble]
868
- assert_nil post.reload[:wibble]
869
- end
870
-
871
- def test_find_via_reload
872
- post = Post.new
873
-
874
- assert post.new_record?
875
-
876
- post.id = 1
877
- post.reload
878
-
879
- assert_equal "Welcome to the weblog", post.title
880
- assert_not post.new_record?
881
- end
882
-
883
- def test_reload_via_querycache
884
- ActiveRecord::Base.connection.enable_query_cache!
885
- ActiveRecord::Base.connection.clear_query_cache
886
- assert ActiveRecord::Base.connection.query_cache_enabled, 'cache should be on'
887
- parrot = Parrot.create(:name => 'Shane')
888
-
889
- # populate the cache with the SELECT result
890
- found_parrot = Parrot.find(parrot.id)
891
- assert_equal parrot.id, found_parrot.id
892
-
893
- # Manually update the 'name' attribute in the DB directly
894
- assert_equal 1, ActiveRecord::Base.connection.query_cache.length
895
- ActiveRecord::Base.uncached do
896
- found_parrot.name = 'Mary'
897
- found_parrot.save
898
- end
899
-
900
- # Now reload, and verify that it gets the DB version, and not the querycache version
901
- found_parrot.reload
902
- assert_equal 'Mary', found_parrot.name
903
-
904
- found_parrot = Parrot.find(parrot.id)
905
- assert_equal 'Mary', found_parrot.name
906
- ensure
907
- ActiveRecord::Base.connection.disable_query_cache!
908
- end
909
- end
1
+ require "cases/helper"
2
+ require 'models/aircraft'
3
+ require 'models/post'
4
+ require 'models/comment'
5
+ require 'models/author'
6
+ require 'models/topic'
7
+ require 'models/reply'
8
+ require 'models/category'
9
+ require 'models/company'
10
+ require 'models/developer'
11
+ require 'models/computer'
12
+ require 'models/project'
13
+ require 'models/minimalistic'
14
+ require 'models/warehouse_thing'
15
+ require 'models/parrot'
16
+ require 'models/minivan'
17
+ require 'models/owner'
18
+ require 'models/person'
19
+ require 'models/pet'
20
+ require 'models/toy'
21
+ require 'rexml/document'
22
+
23
+ class PersistenceTest < ActiveRecord::TestCase
24
+ fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse_things', :authors, :author_addresses, :categorizations, :categories, :posts, :minivans, :pets, :toys
25
+
26
+ # Oracle UPDATE does not support ORDER BY
27
+ unless current_adapter?(:OracleAdapter)
28
+ def test_update_all_ignores_order_without_limit_from_association
29
+ author = authors(:david)
30
+ assert_nothing_raised do
31
+ assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
32
+ end
33
+ end
34
+
35
+ def test_update_all_doesnt_ignore_order
36
+ assert_equal authors(:david).id + 1, authors(:mary).id # make sure there is going to be a duplicate PK error
37
+ test_update_with_order_succeeds = lambda do |order|
38
+ begin
39
+ Author.order(order).update_all('id = id + 1')
40
+ rescue ActiveRecord::ActiveRecordError
41
+ false
42
+ end
43
+ end
44
+
45
+ if !current_adapter?(:IBM_DBAdapter) && test_update_with_order_succeeds.call('id DESC')
46
+ # The update below goes on successfully in DB2.
47
+ assert !test_update_with_order_succeeds.call('id ASC') # test that this wasn't a fluke and using an incorrect order results in an exception
48
+ else
49
+ # test that we're failing because the current Arel's engine doesn't support UPDATE ORDER BY queries is using subselects instead
50
+ assert_sql(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\Z/i) do
51
+ test_update_with_order_succeeds.call('id DESC')
52
+ end
53
+ end
54
+ end
55
+
56
+ def test_update_all_with_order_and_limit_updates_subset_only
57
+ author = authors(:david)
58
+ assert_nothing_raised do
59
+ assert_equal 1, author.posts_sorted_by_id_limited.size
60
+ assert_equal 2, author.posts_sorted_by_id_limited.limit(2).to_a.size
61
+ assert_equal 1, author.posts_sorted_by_id_limited.update_all([ "body = ?", "bulk update!" ])
62
+ assert_equal "bulk update!", posts(:welcome).body
63
+ assert_not_equal "bulk update!", posts(:thinking).body
64
+ end
65
+ end
66
+ end
67
+
68
+ def test_update_many
69
+ topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
70
+ updated = Topic.update(topic_data.keys, topic_data.values)
71
+
72
+ assert_equal 2, updated.size
73
+ assert_equal "1 updated", Topic.find(1).content
74
+ assert_equal "2 updated", Topic.find(2).content
75
+ end
76
+
77
+ def test_delete_all
78
+ assert Topic.count > 0
79
+
80
+ assert_equal Topic.count, Topic.delete_all
81
+ end
82
+
83
+ def test_delete_all_with_joins_and_where_part_is_hash
84
+ where_args = {:toys => {:name => 'Bone'}}
85
+ count = Pet.joins(:toys).where(where_args).count
86
+
87
+ assert_equal count, 1
88
+ assert_equal count, Pet.joins(:toys).where(where_args).delete_all
89
+ end
90
+
91
+ def test_delete_all_with_joins_and_where_part_is_not_hash
92
+ where_args = ['toys.name = ?', 'Bone']
93
+ count = Pet.joins(:toys).where(where_args).count
94
+
95
+ assert_equal count, 1
96
+ assert_equal count, Pet.joins(:toys).where(where_args).delete_all
97
+ end
98
+
99
+ def test_increment_attribute
100
+ assert_equal 50, accounts(:signals37).credit_limit
101
+ accounts(:signals37).increment! :credit_limit
102
+ assert_equal 51, accounts(:signals37, :reload).credit_limit
103
+
104
+ accounts(:signals37).increment(:credit_limit).increment!(:credit_limit)
105
+ assert_equal 53, accounts(:signals37, :reload).credit_limit
106
+ end
107
+
108
+ def test_increment_nil_attribute
109
+ assert_nil topics(:first).parent_id
110
+ topics(:first).increment! :parent_id
111
+ assert_equal 1, topics(:first).parent_id
112
+ end
113
+
114
+ def test_increment_attribute_by
115
+ assert_equal 50, accounts(:signals37).credit_limit
116
+ accounts(:signals37).increment! :credit_limit, 5
117
+ assert_equal 55, accounts(:signals37, :reload).credit_limit
118
+
119
+ accounts(:signals37).increment(:credit_limit, 1).increment!(:credit_limit, 3)
120
+ assert_equal 59, accounts(:signals37, :reload).credit_limit
121
+ end
122
+
123
+ def test_destroy_all
124
+ conditions = "author_name = 'Mary'"
125
+ topics_by_mary = Topic.all.merge!(:where => conditions, :order => 'id').to_a
126
+ assert ! topics_by_mary.empty?
127
+
128
+ assert_difference('Topic.count', -topics_by_mary.size) do
129
+ destroyed = Topic.destroy_all(conditions).sort_by(&:id)
130
+ assert_equal topics_by_mary, destroyed
131
+ assert destroyed.all? { |topic| topic.frozen? }, "destroyed topics should be frozen"
132
+ end
133
+ end
134
+
135
+ def test_destroy_many
136
+ clients = Client.all.merge!(:order => 'id').find([2, 3])
137
+
138
+ assert_difference('Client.count', -2) do
139
+ destroyed = Client.destroy([2, 3]).sort_by(&:id)
140
+ assert_equal clients, destroyed
141
+ assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
142
+ end
143
+ end
144
+
145
+ def test_becomes
146
+ assert_kind_of Reply, topics(:first).becomes(Reply)
147
+ assert_equal "The First Topic", topics(:first).becomes(Reply).title
148
+ end
149
+
150
+ def test_becomes_includes_errors
151
+ company = Company.new(:name => nil)
152
+ assert !company.valid?
153
+ original_errors = company.errors
154
+ client = company.becomes(Client)
155
+ assert_equal original_errors, client.errors
156
+ end
157
+
158
+ def test_dupd_becomes_persists_changes_from_the_original
159
+ original = topics(:first)
160
+ copy = original.dup.becomes(Reply)
161
+ copy.save!
162
+ assert_equal "The First Topic", Topic.find(copy.id).title
163
+ end
164
+
165
+ def test_becomes_includes_changed_attributes
166
+ company = Company.new(name: "37signals")
167
+ client = company.becomes(Client)
168
+ assert_equal "37signals", client.name
169
+ assert_equal %w{name}, client.changed
170
+ end
171
+
172
+ def test_delete_many
173
+ original_count = Topic.count
174
+ Topic.delete(deleting = [1, 2])
175
+ assert_equal original_count - deleting.size, Topic.count
176
+ end
177
+
178
+ def test_decrement_attribute
179
+ assert_equal 50, accounts(:signals37).credit_limit
180
+
181
+ accounts(:signals37).decrement!(:credit_limit)
182
+ assert_equal 49, accounts(:signals37, :reload).credit_limit
183
+
184
+ accounts(:signals37).decrement(:credit_limit).decrement!(:credit_limit)
185
+ assert_equal 47, accounts(:signals37, :reload).credit_limit
186
+ end
187
+
188
+ def test_decrement_attribute_by
189
+ assert_equal 50, accounts(:signals37).credit_limit
190
+ accounts(:signals37).decrement! :credit_limit, 5
191
+ assert_equal 45, accounts(:signals37, :reload).credit_limit
192
+
193
+ accounts(:signals37).decrement(:credit_limit, 1).decrement!(:credit_limit, 3)
194
+ assert_equal 41, accounts(:signals37, :reload).credit_limit
195
+ end
196
+
197
+ def test_create
198
+ topic = Topic.new
199
+ topic.title = "New Topic"
200
+ topic.save
201
+ topic_reloaded = Topic.find(topic.id)
202
+ assert_equal("New Topic", topic_reloaded.title)
203
+ end
204
+
205
+ def test_save!
206
+ topic = Topic.new(:title => "New Topic")
207
+ assert topic.save!
208
+
209
+ reply = WrongReply.new
210
+ assert_raise(ActiveRecord::RecordInvalid) { reply.save! }
211
+ end
212
+
213
+ def test_save_null_string_attributes
214
+ topic = Topic.find(1)
215
+ topic.attributes = { "title" => "null", "author_name" => "null" }
216
+ topic.save!
217
+ topic.reload
218
+ assert_equal("null", topic.title)
219
+ assert_equal("null", topic.author_name)
220
+ end
221
+
222
+ def test_save_nil_string_attributes
223
+ topic = Topic.find(1)
224
+ topic.title = nil
225
+ topic.save!
226
+ topic.reload
227
+ assert_nil topic.title
228
+ end
229
+
230
+ def test_save_for_record_with_only_primary_key
231
+ minimalistic = Minimalistic.new
232
+ assert_nothing_raised { minimalistic.save }
233
+ end
234
+
235
+ def test_save_for_record_with_only_primary_key_that_is_provided
236
+ assert_nothing_raised { Minimalistic.create!(:id => 2) }
237
+ end
238
+
239
+ def test_save_with_duping_of_destroyed_object
240
+ developer = Developer.first
241
+ developer.destroy
242
+ new_developer = developer.dup
243
+ new_developer.save
244
+ assert new_developer.persisted?
245
+ assert_not new_developer.destroyed?
246
+ end
247
+
248
+ def test_create_many
249
+ topics = Topic.create([ { "title" => "first" }, { "title" => "second" }])
250
+ assert_equal 2, topics.size
251
+ assert_equal "first", topics.first.title
252
+ end
253
+
254
+ def test_create_columns_not_equal_attributes
255
+ topic = Topic.instantiate(
256
+ 'title' => 'Another New Topic',
257
+ 'does_not_exist' => 'test'
258
+ )
259
+ assert_nothing_raised { topic.save }
260
+ end
261
+
262
+ def test_create_through_factory_with_block
263
+ topic = Topic.create("title" => "New Topic") do |t|
264
+ t.author_name = "David"
265
+ end
266
+ assert_equal("New Topic", topic.title)
267
+ assert_equal("David", topic.author_name)
268
+ end
269
+
270
+ def test_create_many_through_factory_with_block
271
+ topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) do |t|
272
+ t.author_name = "David"
273
+ end
274
+ assert_equal 2, topics.size
275
+ topic1, topic2 = Topic.find(topics[0].id), Topic.find(topics[1].id)
276
+ assert_equal "first", topic1.title
277
+ assert_equal "David", topic1.author_name
278
+ assert_equal "second", topic2.title
279
+ assert_equal "David", topic2.author_name
280
+ end
281
+
282
+ def test_update_object
283
+ topic = Topic.new
284
+ topic.title = "Another New Topic"
285
+ topic.written_on = "2003-12-12 23:23:00"
286
+ topic.save
287
+ topic_reloaded = Topic.find(topic.id)
288
+ assert_equal("Another New Topic", topic_reloaded.title)
289
+
290
+ topic_reloaded.title = "Updated topic"
291
+ topic_reloaded.save
292
+
293
+ topic_reloaded_again = Topic.find(topic.id)
294
+
295
+ assert_equal("Updated topic", topic_reloaded_again.title)
296
+ end
297
+
298
+ def test_update_columns_not_equal_attributes
299
+ topic = Topic.new
300
+ topic.title = "Still another topic"
301
+ topic.save
302
+
303
+ topic_reloaded = Topic.instantiate(topic.attributes.merge('does_not_exist' => 'test'))
304
+ topic_reloaded.title = 'A New Topic'
305
+ assert_nothing_raised { topic_reloaded.save }
306
+ end
307
+
308
+ def test_update_for_record_with_only_primary_key
309
+ minimalistic = minimalistics(:first)
310
+ assert_nothing_raised { minimalistic.save }
311
+ end
312
+
313
+ def test_update_sti_type
314
+ assert_instance_of Reply, topics(:second)
315
+
316
+ topic = topics(:second).becomes!(Topic)
317
+ assert_instance_of Topic, topic
318
+ topic.save!
319
+ assert_instance_of Topic, Topic.find(topic.id)
320
+ end
321
+
322
+ def test_preserve_original_sti_type
323
+ reply = topics(:second)
324
+ assert_equal "Reply", reply.type
325
+
326
+ topic = reply.becomes(Topic)
327
+ assert_equal "Reply", reply.type
328
+
329
+ assert_instance_of Topic, topic
330
+ assert_equal "Reply", topic.type
331
+ end
332
+
333
+ def test_update_sti_subclass_type
334
+ assert_instance_of Topic, topics(:first)
335
+
336
+ reply = topics(:first).becomes!(Reply)
337
+ assert_instance_of Reply, reply
338
+ reply.save!
339
+ assert_instance_of Reply, Reply.find(reply.id)
340
+ end
341
+
342
+ def test_update_after_create
343
+ klass = Class.new(Topic) do
344
+ def self.name; 'Topic'; end
345
+ after_create do
346
+ update_attribute("author_name", "David")
347
+ end
348
+ end
349
+ topic = klass.new
350
+ topic.title = "Another New Topic"
351
+ topic.save
352
+
353
+ topic_reloaded = Topic.find(topic.id)
354
+ assert_equal("Another New Topic", topic_reloaded.title)
355
+ assert_equal("David", topic_reloaded.author_name)
356
+ end
357
+
358
+ def test_delete
359
+ topic = Topic.find(1)
360
+ assert_equal topic, topic.delete, 'topic.delete did not return self'
361
+ assert topic.frozen?, 'topic not frozen after delete'
362
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
363
+ end
364
+
365
+ def test_delete_doesnt_run_callbacks
366
+ Topic.find(1).delete
367
+ assert_not_nil Topic.find(2)
368
+ end
369
+
370
+ def test_destroy
371
+ topic = Topic.find(1)
372
+ assert_equal topic, topic.destroy, 'topic.destroy did not return self'
373
+ assert topic.frozen?, 'topic not frozen after destroy'
374
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
375
+ end
376
+
377
+ def test_destroy!
378
+ topic = Topic.find(1)
379
+ assert_equal topic, topic.destroy!, 'topic.destroy! did not return self'
380
+ assert topic.frozen?, 'topic not frozen after destroy!'
381
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
382
+ end
383
+
384
+ def test_record_not_found_exception
385
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(99999) }
386
+ end
387
+
388
+ def test_update_all
389
+ assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'")
390
+ assert_equal "bulk updated!", Topic.find(1).content
391
+ assert_equal "bulk updated!", Topic.find(2).content
392
+
393
+ assert_equal Topic.count, Topic.update_all(['content = ?', 'bulk updated again!'])
394
+ assert_equal "bulk updated again!", Topic.find(1).content
395
+ assert_equal "bulk updated again!", Topic.find(2).content
396
+
397
+ assert_equal Topic.count, Topic.update_all(['content = ?', nil])
398
+ assert_nil Topic.find(1).content
399
+ end
400
+
401
+ def test_update_all_with_hash
402
+ assert_not_nil Topic.find(1).last_read
403
+ assert_equal Topic.count, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
404
+ assert_equal "bulk updated with hash!", Topic.find(1).content
405
+ assert_equal "bulk updated with hash!", Topic.find(2).content
406
+ assert_nil Topic.find(1).last_read
407
+ assert_nil Topic.find(2).last_read
408
+ end
409
+
410
+ def test_update_all_with_non_standard_table_name
411
+ assert_equal 1, WarehouseThing.where(id: 1).update_all(['value = ?', 0])
412
+ assert_equal 0, WarehouseThing.find(1).value
413
+ end
414
+
415
+ def test_delete_new_record
416
+ client = Client.new
417
+ client.delete
418
+ assert client.frozen?
419
+ end
420
+
421
+ def test_delete_record_with_associations
422
+ client = Client.find(3)
423
+ client.delete
424
+ assert client.frozen?
425
+ assert_kind_of Firm, client.firm
426
+ assert_raise(RuntimeError) { client.name = "something else" }
427
+ end
428
+
429
+ def test_destroy_new_record
430
+ client = Client.new
431
+ client.destroy
432
+ assert client.frozen?
433
+ end
434
+
435
+ def test_destroy_record_with_associations
436
+ client = Client.find(3)
437
+ client.destroy
438
+ assert client.frozen?
439
+ assert_kind_of Firm, client.firm
440
+ assert_raise(RuntimeError) { client.name = "something else" }
441
+ end
442
+
443
+ def test_update_attribute
444
+ assert !Topic.find(1).approved?
445
+ Topic.find(1).update_attribute("approved", true)
446
+ assert Topic.find(1).approved?
447
+
448
+ Topic.find(1).update_attribute(:approved, false)
449
+ assert !Topic.find(1).approved?
450
+ end
451
+
452
+ def test_update_attribute_for_readonly_attribute
453
+ minivan = Minivan.find('m1')
454
+ assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_attribute(:color, 'black') }
455
+ end
456
+
457
+ def test_update_attribute_with_one_updated
458
+ t = Topic.first
459
+ t.update_attribute(:title, 'super_title')
460
+ assert_equal 'super_title', t.title
461
+ assert !t.changed?, "topic should not have changed"
462
+ assert !t.title_changed?, "title should not have changed"
463
+ assert_nil t.title_change, 'title change should be nil'
464
+
465
+ t.reload
466
+ assert_equal 'super_title', t.title
467
+ end
468
+
469
+ def test_update_attribute_for_updated_at_on
470
+ developer = Developer.find(1)
471
+ prev_month = Time.now.prev_month.change(usec: 0)
472
+
473
+ developer.update_attribute(:updated_at, prev_month)
474
+ assert_equal prev_month, developer.updated_at
475
+
476
+ developer.update_attribute(:salary, 80001)
477
+ assert_not_equal prev_month, developer.updated_at
478
+
479
+ developer.reload
480
+ assert_not_equal prev_month, developer.updated_at
481
+ end
482
+
483
+ def test_update_column
484
+ topic = Topic.find(1)
485
+ topic.update_column("approved", true)
486
+ assert topic.approved?
487
+ topic.reload
488
+ assert topic.approved?
489
+
490
+ topic.update_column(:approved, false)
491
+ assert !topic.approved?
492
+ topic.reload
493
+ assert !topic.approved?
494
+ end
495
+
496
+ def test_update_column_should_not_use_setter_method
497
+ dev = Developer.find(1)
498
+ dev.instance_eval { def salary=(value); write_attribute(:salary, value * 2); end }
499
+
500
+ dev.update_column(:salary, 80000)
501
+ assert_equal 80000, dev.salary
502
+
503
+ dev.reload
504
+ assert_equal 80000, dev.salary
505
+ end
506
+
507
+ def test_update_column_should_raise_exception_if_new_record
508
+ topic = Topic.new
509
+ assert_raises(ActiveRecord::ActiveRecordError) { topic.update_column("approved", false) }
510
+ end
511
+
512
+ def test_update_column_should_not_leave_the_object_dirty
513
+ topic = Topic.find(1)
514
+ topic.update_column("content", "--- Have a nice day\n...\n")
515
+
516
+ topic.reload
517
+ topic.update_column(:content, "--- You too\n...\n")
518
+ assert_equal [], topic.changed
519
+
520
+ topic.reload
521
+ topic.update_column("content", "--- Have a nice day\n...\n")
522
+ assert_equal [], topic.changed
523
+ end
524
+
525
+ def test_update_column_with_model_having_primary_key_other_than_id
526
+ minivan = Minivan.find('m1')
527
+ new_name = 'sebavan'
528
+
529
+ minivan.update_column(:name, new_name)
530
+ assert_equal new_name, minivan.name
531
+ end
532
+
533
+ def test_update_column_for_readonly_attribute
534
+ minivan = Minivan.find('m1')
535
+ prev_color = minivan.color
536
+ assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_column(:color, 'black') }
537
+ assert_equal prev_color, minivan.color
538
+ end
539
+
540
+ def test_update_column_should_not_modify_updated_at
541
+ developer = Developer.find(1)
542
+ prev_month = Time.now.prev_month.change(usec: 0)
543
+
544
+ developer.update_column(:updated_at, prev_month)
545
+ assert_equal prev_month, developer.updated_at
546
+
547
+ developer.update_column(:salary, 80001)
548
+ assert_equal prev_month, developer.updated_at
549
+
550
+ developer.reload
551
+ assert_equal prev_month.to_i, developer.updated_at.to_i
552
+ end
553
+
554
+ def test_update_column_with_one_changed_and_one_updated
555
+ t = Topic.order('id').limit(1).first
556
+ author_name = t.author_name
557
+ t.author_name = 'John'
558
+ t.update_column(:title, 'super_title')
559
+ assert_equal 'John', t.author_name
560
+ assert_equal 'super_title', t.title
561
+ assert t.changed?, "topic should have changed"
562
+ assert t.author_name_changed?, "author_name should have changed"
563
+
564
+ t.reload
565
+ assert_equal author_name, t.author_name
566
+ assert_equal 'super_title', t.title
567
+ end
568
+
569
+ def test_update_column_with_default_scope
570
+ developer = DeveloperCalledDavid.first
571
+ developer.name = 'John'
572
+ developer.save!
573
+
574
+ assert developer.update_column(:name, 'Will'), 'did not update record due to default scope'
575
+ end
576
+
577
+ def test_update_columns
578
+ topic = Topic.find(1)
579
+ topic.update_columns({ "approved" => true, title: "Sebastian Topic" })
580
+ assert topic.approved?
581
+ assert_equal "Sebastian Topic", topic.title
582
+ topic.reload
583
+ assert topic.approved?
584
+ assert_equal "Sebastian Topic", topic.title
585
+ end
586
+
587
+ def test_update_columns_should_not_use_setter_method
588
+ dev = Developer.find(1)
589
+ dev.instance_eval { def salary=(value); write_attribute(:salary, value * 2); end }
590
+
591
+ dev.update_columns(salary: 80000)
592
+ assert_equal 80000, dev.salary
593
+
594
+ dev.reload
595
+ assert_equal 80000, dev.salary
596
+ end
597
+
598
+ def test_update_columns_should_raise_exception_if_new_record
599
+ topic = Topic.new
600
+ assert_raises(ActiveRecord::ActiveRecordError) { topic.update_columns({ approved: false }) }
601
+ end
602
+
603
+ def test_update_columns_should_not_leave_the_object_dirty
604
+ topic = Topic.find(1)
605
+ topic.update({ "content" => "--- Have a nice day\n...\n", :author_name => "Jose" })
606
+
607
+ topic.reload
608
+ topic.update_columns({ content: "--- You too\n...\n", "author_name" => "Sebastian" })
609
+ assert_equal [], topic.changed
610
+
611
+ topic.reload
612
+ topic.update_columns({ content: "--- Have a nice day\n...\n", author_name: "Jose" })
613
+ assert_equal [], topic.changed
614
+ end
615
+
616
+ def test_update_columns_with_model_having_primary_key_other_than_id
617
+ minivan = Minivan.find('m1')
618
+ new_name = 'sebavan'
619
+
620
+ minivan.update_columns(name: new_name)
621
+ assert_equal new_name, minivan.name
622
+ end
623
+
624
+ def test_update_columns_with_one_readonly_attribute
625
+ minivan = Minivan.find('m1')
626
+ prev_color = minivan.color
627
+ prev_name = minivan.name
628
+ assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_columns({ name: "My old minivan", color: 'black' }) }
629
+ assert_equal prev_color, minivan.color
630
+ assert_equal prev_name, minivan.name
631
+
632
+ minivan.reload
633
+ assert_equal prev_color, minivan.color
634
+ assert_equal prev_name, minivan.name
635
+ end
636
+
637
+ def test_update_columns_should_not_modify_updated_at
638
+ developer = Developer.find(1)
639
+ prev_month = Time.now.prev_month.change(usec: 0)
640
+
641
+ developer.update_columns(updated_at: prev_month)
642
+ assert_equal prev_month, developer.updated_at
643
+
644
+ developer.update_columns(salary: 80000)
645
+ assert_equal prev_month, developer.updated_at
646
+ assert_equal 80000, developer.salary
647
+
648
+ developer.reload
649
+ assert_equal prev_month.to_i, developer.updated_at.to_i
650
+ assert_equal 80000, developer.salary
651
+ end
652
+
653
+ def test_update_columns_with_one_changed_and_one_updated
654
+ t = Topic.order('id').limit(1).first
655
+ author_name = t.author_name
656
+ t.author_name = 'John'
657
+ t.update_columns(title: 'super_title')
658
+ assert_equal 'John', t.author_name
659
+ assert_equal 'super_title', t.title
660
+ assert t.changed?, "topic should have changed"
661
+ assert t.author_name_changed?, "author_name should have changed"
662
+
663
+ t.reload
664
+ assert_equal author_name, t.author_name
665
+ assert_equal 'super_title', t.title
666
+ end
667
+
668
+ def test_update_columns_changing_id
669
+ topic = Topic.find(1)
670
+ topic.update_columns(id: 123)
671
+ assert_equal 123, topic.id
672
+ topic.reload
673
+ assert_equal 123, topic.id
674
+ end
675
+
676
+ def test_update_columns_returns_boolean
677
+ topic = Topic.find(1)
678
+ assert_equal true, topic.update_columns(title: "New title")
679
+ end
680
+
681
+ def test_update_columns_with_default_scope
682
+ developer = DeveloperCalledDavid.first
683
+ developer.name = 'John'
684
+ developer.save!
685
+
686
+ assert developer.update_columns(name: 'Will'), 'did not update record due to default scope'
687
+ end
688
+
689
+ def test_update
690
+ topic = Topic.find(1)
691
+ assert !topic.approved?
692
+ assert_equal "The First Topic", topic.title
693
+
694
+ topic.update("approved" => true, "title" => "The First Topic Updated")
695
+ topic.reload
696
+ assert topic.approved?
697
+ assert_equal "The First Topic Updated", topic.title
698
+
699
+ topic.update(approved: false, title: "The First Topic")
700
+ topic.reload
701
+ assert !topic.approved?
702
+ assert_equal "The First Topic", topic.title
703
+ end
704
+
705
+ def test_update_attributes
706
+ topic = Topic.find(1)
707
+ assert !topic.approved?
708
+ assert_equal "The First Topic", topic.title
709
+
710
+ topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
711
+ topic.reload
712
+ assert topic.approved?
713
+ assert_equal "The First Topic Updated", topic.title
714
+
715
+ topic.update_attributes(approved: false, title: "The First Topic")
716
+ topic.reload
717
+ assert !topic.approved?
718
+ assert_equal "The First Topic", topic.title
719
+
720
+ assert_raise(ActiveRecord::RecordNotUnique, ActiveRecord::StatementInvalid) do
721
+ topic.update_attributes(id: 3, title: "Hm is it possible?")
722
+ end
723
+ assert_not_equal "Hm is it possible?", Topic.find(3).title
724
+
725
+ topic.update_attributes(id: 1234)
726
+ assert_nothing_raised { topic.reload }
727
+ assert_equal topic.title, Topic.find(1234).title
728
+ end
729
+
730
+ def test_update_attributes_parameters
731
+ topic = Topic.find(1)
732
+ assert_nothing_raised do
733
+ topic.update_attributes({})
734
+ end
735
+
736
+ assert_raises(ArgumentError) do
737
+ topic.update_attributes(nil)
738
+ end
739
+ end
740
+
741
+ def test_update!
742
+ Reply.validates_presence_of(:title)
743
+ reply = Reply.find(2)
744
+ assert_equal "The Second Topic of the day", reply.title
745
+ assert_equal "Have a nice day", reply.content
746
+
747
+ reply.update!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
748
+ reply.reload
749
+ assert_equal "The Second Topic of the day updated", reply.title
750
+ assert_equal "Have a nice evening", reply.content
751
+
752
+ reply.update!(title: "The Second Topic of the day", content: "Have a nice day")
753
+ reply.reload
754
+ assert_equal "The Second Topic of the day", reply.title
755
+ assert_equal "Have a nice day", reply.content
756
+
757
+ assert_raise(ActiveRecord::RecordInvalid) { reply.update!(title: nil, content: "Have a nice evening") }
758
+ ensure
759
+ Reply.clear_validators!
760
+ end
761
+
762
+ def test_update_attributes!
763
+ Reply.validates_presence_of(:title)
764
+ reply = Reply.find(2)
765
+ assert_equal "The Second Topic of the day", reply.title
766
+ assert_equal "Have a nice day", reply.content
767
+
768
+ reply.update_attributes!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
769
+ reply.reload
770
+ assert_equal "The Second Topic of the day updated", reply.title
771
+ assert_equal "Have a nice evening", reply.content
772
+
773
+ reply.update_attributes!(title: "The Second Topic of the day", content: "Have a nice day")
774
+ reply.reload
775
+ assert_equal "The Second Topic of the day", reply.title
776
+ assert_equal "Have a nice day", reply.content
777
+
778
+ assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(title: nil, content: "Have a nice evening") }
779
+ ensure
780
+ Reply.clear_validators!
781
+ end
782
+
783
+ def test_destroyed_returns_boolean
784
+ developer = Developer.first
785
+ assert_equal false, developer.destroyed?
786
+ developer.destroy
787
+ assert_equal true, developer.destroyed?
788
+
789
+ developer = Developer.last
790
+ assert_equal false, developer.destroyed?
791
+ developer.delete
792
+ assert_equal true, developer.destroyed?
793
+ end
794
+
795
+ def test_persisted_returns_boolean
796
+ developer = Developer.new(:name => "Jose")
797
+ assert_equal false, developer.persisted?
798
+ developer.save!
799
+ assert_equal true, developer.persisted?
800
+
801
+ developer = Developer.first
802
+ assert_equal true, developer.persisted?
803
+ developer.destroy
804
+ assert_equal false, developer.persisted?
805
+
806
+ developer = Developer.last
807
+ assert_equal true, developer.persisted?
808
+ developer.delete
809
+ assert_equal false, developer.persisted?
810
+ end
811
+
812
+ def test_class_level_destroy
813
+ should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
814
+ Topic.find(1).replies << should_be_destroyed_reply
815
+
816
+ Topic.destroy(1)
817
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
818
+ assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) }
819
+ end
820
+
821
+ def test_class_level_delete
822
+ should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
823
+ Topic.find(1).replies << should_be_destroyed_reply
824
+
825
+ Topic.delete(1)
826
+ assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
827
+ assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) }
828
+ end
829
+
830
+ def test_create_with_custom_timestamps
831
+ custom_datetime = 1.hour.ago.beginning_of_day
832
+
833
+ %w(created_at created_on updated_at updated_on).each do |attribute|
834
+ parrot = LiveParrot.create(:name => "colombian", attribute => custom_datetime)
835
+ assert_equal custom_datetime, parrot[attribute]
836
+ end
837
+ end
838
+
839
+ def test_persist_inherited_class_with_different_table_name
840
+ minimalistic_aircrafts = Class.new(Minimalistic) do
841
+ self.table_name = "aircraft"
842
+ end
843
+
844
+ assert_difference "Aircraft.count", 1 do
845
+ aircraft = minimalistic_aircrafts.create(name: "Wright Flyer")
846
+ aircraft.name = "Wright Glider"
847
+ aircraft.save
848
+ end
849
+
850
+ assert_equal "Wright Glider", Aircraft.last.name
851
+ end
852
+
853
+ def test_instantiate_creates_a_new_instance
854
+ post = Post.instantiate("title" => "appropriate documentation", "type" => "SpecialPost")
855
+ assert_equal "appropriate documentation", post.title
856
+ assert_instance_of SpecialPost, post
857
+
858
+ # body was not initialized
859
+ assert_raises ActiveModel::MissingAttributeError do
860
+ post.body
861
+ end
862
+ end
863
+
864
+ def test_reload_removes_custom_selects
865
+ post = Post.select('posts.*, 1 as wibble').last!
866
+
867
+ assert_equal 1, post[:wibble]
868
+ assert_nil post.reload[:wibble]
869
+ end
870
+
871
+ def test_find_via_reload
872
+ post = Post.new
873
+
874
+ assert post.new_record?
875
+
876
+ post.id = 1
877
+ post.reload
878
+
879
+ assert_equal "Welcome to the weblog", post.title
880
+ assert_not post.new_record?
881
+ end
882
+
883
+ def test_reload_via_querycache
884
+ ActiveRecord::Base.connection.enable_query_cache!
885
+ ActiveRecord::Base.connection.clear_query_cache
886
+ assert ActiveRecord::Base.connection.query_cache_enabled, 'cache should be on'
887
+ parrot = Parrot.create(:name => 'Shane')
888
+
889
+ # populate the cache with the SELECT result
890
+ found_parrot = Parrot.find(parrot.id)
891
+ assert_equal parrot.id, found_parrot.id
892
+
893
+ # Manually update the 'name' attribute in the DB directly
894
+ assert_equal 1, ActiveRecord::Base.connection.query_cache.length
895
+ ActiveRecord::Base.uncached do
896
+ found_parrot.name = 'Mary'
897
+ found_parrot.save
898
+ end
899
+
900
+ # Now reload, and verify that it gets the DB version, and not the querycache version
901
+ found_parrot.reload
902
+ assert_equal 'Mary', found_parrot.name
903
+
904
+ found_parrot = Parrot.find(parrot.id)
905
+ assert_equal 'Mary', found_parrot.name
906
+ ensure
907
+ ActiveRecord::Base.connection.disable_query_cache!
908
+ end
909
+ end