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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/OLD/extconf.rb +264 -0
  8. data/ext/{extconf_MacOS.rb → OLD/extconf_MacOS.rb} +269 -269
  9. data/ext/extconf.rb +291 -264
  10. data/ext/ibm_db.c +2 -2
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4 -4
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +115 -115
  19. data/test/active_record/connection_adapters/fake_adapter.rb +46 -0
  20. data/test/assets/example.log +1 -0
  21. data/test/assets/flowers.jpg +0 -0
  22. data/test/assets/test.txt +1 -0
  23. data/test/cases/adapter_test.rb +261 -207
  24. data/test/cases/aggregations_test.rb +158 -0
  25. data/test/cases/ar_schema_test.rb +161 -0
  26. data/test/cases/associations/association_scope_test.rb +21 -0
  27. data/test/cases/associations/belongs_to_associations_test.rb +1029 -711
  28. data/test/cases/associations/callbacks_test.rb +192 -0
  29. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -181
  30. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -0
  31. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  32. data/test/cases/associations/eager_load_nested_include_test.rb +128 -0
  33. data/test/cases/associations/eager_singularization_test.rb +148 -0
  34. data/test/cases/associations/eager_test.rb +1411 -0
  35. data/test/cases/associations/extension_test.rb +82 -0
  36. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +932 -851
  37. data/test/cases/associations/has_many_associations_test.rb +2162 -0
  38. data/test/cases/associations/has_many_through_associations_test.rb +1204 -0
  39. data/test/cases/associations/has_one_associations_test.rb +610 -0
  40. data/test/cases/associations/has_one_through_associations_test.rb +380 -0
  41. data/test/cases/associations/inner_join_association_test.rb +139 -0
  42. data/test/cases/associations/inverse_associations_test.rb +693 -0
  43. data/test/cases/associations/join_model_test.rb +754 -743
  44. data/test/cases/associations/nested_through_associations_test.rb +579 -0
  45. data/test/cases/associations/required_test.rb +82 -0
  46. data/test/cases/associations_test.rb +380 -0
  47. data/test/cases/attribute_decorators_test.rb +125 -0
  48. data/test/cases/attribute_methods/read_test.rb +60 -0
  49. data/test/cases/attribute_methods/serialization_test.rb +29 -0
  50. data/test/cases/attribute_methods_test.rb +952 -822
  51. data/test/cases/attribute_set_test.rb +200 -0
  52. data/test/cases/attribute_test.rb +180 -0
  53. data/test/cases/attributes_test.rb +136 -0
  54. data/test/cases/autosave_association_test.rb +1595 -0
  55. data/test/cases/base_test.rb +1638 -2133
  56. data/test/cases/batches_test.rb +212 -0
  57. data/test/cases/binary_test.rb +52 -0
  58. data/test/cases/bind_parameter_test.rb +100 -0
  59. data/test/cases/calculations_test.rb +646 -482
  60. data/test/cases/callbacks_test.rb +543 -0
  61. data/test/cases/clone_test.rb +40 -0
  62. data/test/cases/coders/yaml_column_test.rb +63 -0
  63. data/test/cases/column_alias_test.rb +17 -0
  64. data/test/cases/column_definition_test.rb +123 -0
  65. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -0
  66. data/test/cases/connection_adapters/connection_handler_test.rb +53 -0
  67. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  68. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -0
  69. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -0
  70. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  71. data/test/cases/connection_adapters/schema_cache_test.rb +56 -0
  72. data/test/cases/connection_adapters/type_lookup_test.rb +110 -0
  73. data/test/cases/connection_management_test.rb +122 -0
  74. data/test/cases/connection_pool_test.rb +346 -0
  75. data/test/cases/connection_specification/resolver_test.rb +116 -0
  76. data/test/cases/core_test.rb +112 -0
  77. data/test/cases/counter_cache_test.rb +209 -0
  78. data/test/cases/custom_locking_test.rb +17 -0
  79. data/test/cases/database_statements_test.rb +19 -0
  80. data/test/cases/date_time_test.rb +61 -0
  81. data/test/cases/defaults_test.rb +223 -0
  82. data/test/cases/dirty_test.rb +775 -0
  83. data/test/cases/disconnected_test.rb +28 -0
  84. data/test/cases/dup_test.rb +157 -0
  85. data/test/cases/enum_test.rb +290 -0
  86. data/test/cases/explain_subscriber_test.rb +64 -0
  87. data/test/cases/explain_test.rb +76 -0
  88. data/test/cases/finder_respond_to_test.rb +60 -0
  89. data/test/cases/finder_test.rb +1166 -0
  90. data/test/cases/fixture_set/file_test.rb +138 -0
  91. data/test/cases/fixtures_test.rb +897 -0
  92. data/test/cases/forbidden_attributes_protection_test.rb +99 -0
  93. data/test/cases/habtm_destroy_order_test.rb +61 -0
  94. data/test/cases/helper.rb +210 -0
  95. data/test/cases/hot_compatibility_test.rb +54 -0
  96. data/test/cases/i18n_test.rb +45 -0
  97. data/test/cases/inheritance_test.rb +375 -0
  98. data/test/cases/integration_test.rb +139 -0
  99. data/test/cases/invalid_connection_test.rb +22 -0
  100. data/test/cases/invalid_date_test.rb +32 -0
  101. data/test/cases/invertible_migration_test.rb +295 -0
  102. data/test/cases/json_serialization_test.rb +302 -0
  103. data/test/cases/locking_test.rb +477 -0
  104. data/test/cases/log_subscriber_test.rb +136 -0
  105. data/test/cases/migration/change_schema_test - Copy.rb +448 -0
  106. data/test/cases/migration/change_schema_test.rb +472 -0
  107. data/test/cases/migration/change_table_test.rb +224 -0
  108. data/test/cases/migration/column_attributes_test.rb +192 -0
  109. data/test/cases/migration/column_positioning_test.rb +56 -0
  110. data/test/cases/migration/columns_test.rb +304 -0
  111. data/test/cases/migration/command_recorder_test.rb +305 -0
  112. data/test/cases/migration/create_join_table_test.rb +148 -0
  113. data/test/cases/migration/foreign_key_test - Changed.rb +325 -0
  114. data/test/cases/migration/foreign_key_test.rb +360 -0
  115. data/test/cases/migration/helper.rb +39 -0
  116. data/test/cases/migration/index_test.rb +216 -0
  117. data/test/cases/migration/logger_test.rb +36 -0
  118. data/test/cases/migration/pending_migrations_test.rb +53 -0
  119. data/test/cases/migration/references_foreign_key_test.rb +214 -0
  120. data/test/cases/migration/references_index_test.rb +101 -0
  121. data/test/cases/migration/references_statements_test.rb +116 -0
  122. data/test/cases/migration/rename_table_test.rb +93 -0
  123. data/test/cases/migration/table_and_index_test.rb +24 -0
  124. data/test/cases/migration_test.rb +959 -2408
  125. data/test/cases/migrator_test.rb +388 -0
  126. data/test/cases/mixin_test.rb +70 -0
  127. data/test/cases/modules_test.rb +173 -0
  128. data/test/cases/multiparameter_attributes_test.rb +350 -0
  129. data/test/cases/multiple_db_test.rb +115 -0
  130. data/test/cases/nested_attributes_test.rb +1057 -0
  131. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -0
  132. data/test/cases/persistence_test.rb +909 -642
  133. data/test/cases/pooled_connections_test.rb +81 -0
  134. data/test/cases/primary_keys_test.rb +237 -0
  135. data/test/cases/query_cache_test.rb +326 -257
  136. data/test/cases/quoting_test.rb +156 -0
  137. data/test/cases/readonly_test.rb +118 -0
  138. data/test/cases/reaper_test.rb +85 -0
  139. data/test/cases/reflection_test.rb +454 -0
  140. data/test/cases/relation/delegation_test.rb +68 -0
  141. data/test/cases/relation/merging_test.rb +161 -0
  142. data/test/cases/relation/mutation_test.rb +165 -0
  143. data/test/cases/relation/predicate_builder_test.rb +14 -0
  144. data/test/cases/relation/where_chain_test.rb +181 -0
  145. data/test/cases/relation/where_test.rb +300 -0
  146. data/test/cases/relation/where_test2.rb +36 -0
  147. data/test/cases/relation_test.rb +297 -0
  148. data/test/cases/relations_test.rb +1815 -1182
  149. data/test/cases/reload_models_test.rb +22 -0
  150. data/test/cases/result_test.rb +80 -0
  151. data/test/cases/sanitize_test.rb +83 -0
  152. data/test/cases/schema_dumper_test.rb +463 -256
  153. data/test/cases/scoping/default_scoping_test.rb +454 -0
  154. data/test/cases/scoping/named_scoping_test.rb +524 -0
  155. data/test/cases/scoping/relation_scoping_test.rb +357 -0
  156. data/test/cases/serialization_test.rb +104 -0
  157. data/test/cases/serialized_attribute_test.rb +277 -0
  158. data/test/cases/statement_cache_test.rb +98 -0
  159. data/test/cases/store_test.rb +194 -0
  160. data/test/cases/tasks/database_tasks_test.rb +396 -0
  161. data/test/cases/tasks/mysql_rake_test.rb +311 -0
  162. data/test/cases/tasks/postgresql_rake_test.rb +245 -0
  163. data/test/cases/tasks/sqlite_rake_test.rb +193 -0
  164. data/test/cases/test_case.rb +123 -0
  165. data/test/cases/timestamp_test.rb +468 -0
  166. data/test/cases/transaction_callbacks_test.rb +452 -300
  167. data/test/cases/transaction_isolation_test.rb +106 -0
  168. data/test/cases/transactions_test.rb +817 -0
  169. data/test/cases/type/decimal_test.rb +51 -0
  170. data/test/cases/type/integer_test.rb +121 -0
  171. data/test/cases/type/string_test.rb +36 -0
  172. data/test/cases/type/type_map_test.rb +177 -0
  173. data/test/cases/type/unsigned_integer_test.rb +18 -0
  174. data/test/cases/types_test.rb +141 -0
  175. data/test/cases/unconnected_test.rb +33 -0
  176. data/test/cases/validations/association_validation_test.rb +86 -0
  177. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -0
  178. data/test/cases/validations/i18n_validation_test.rb +90 -0
  179. data/test/cases/validations/length_validation_test.rb +47 -0
  180. data/test/cases/validations/presence_validation_test.rb +68 -0
  181. data/test/cases/validations/uniqueness_validation_test.rb +434 -299
  182. data/test/cases/validations_repair_helper.rb +23 -0
  183. data/test/cases/validations_test.rb +165 -0
  184. data/test/cases/view_test.rb +113 -0
  185. data/test/cases/xml_serialization_test.rb +457 -408
  186. data/test/cases/yaml_serialization_test.rb +86 -0
  187. data/test/config.rb +5 -0
  188. data/test/config.yml +154 -154
  189. data/test/connections/native_ibm_db/connection.rb +43 -43
  190. data/test/fixtures/accounts.yml +29 -0
  191. data/test/fixtures/admin/accounts.yml +2 -0
  192. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  193. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  194. data/test/fixtures/admin/users.yml +10 -0
  195. data/test/fixtures/all/admin +1 -0
  196. data/test/fixtures/all/developers.yml +0 -0
  197. data/test/fixtures/all/people.yml +0 -0
  198. data/test/fixtures/all/tasks.yml +0 -0
  199. data/test/fixtures/author_addresses.yml +18 -0
  200. data/test/fixtures/author_favorites.yml +4 -0
  201. data/test/fixtures/authors.yml +23 -0
  202. data/test/fixtures/binaries.yml +133 -0
  203. data/test/fixtures/books.yml +11 -0
  204. data/test/fixtures/bulbs.yml +5 -0
  205. data/test/fixtures/cars.yml +9 -0
  206. data/test/fixtures/categories.yml +19 -0
  207. data/test/fixtures/categories/special_categories.yml +9 -0
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  209. data/test/fixtures/categories_ordered.yml +7 -0
  210. data/test/fixtures/categories_posts.yml +31 -0
  211. data/test/fixtures/categorizations.yml +23 -0
  212. data/test/fixtures/clubs.yml +8 -0
  213. data/test/fixtures/collections.yml +3 -0
  214. data/test/fixtures/colleges.yml +3 -0
  215. data/test/fixtures/comments.yml +65 -0
  216. data/test/fixtures/companies.yml +67 -0
  217. data/test/fixtures/computers.yml +10 -0
  218. data/test/fixtures/courses.yml +8 -0
  219. data/test/fixtures/customers.yml +26 -0
  220. data/test/fixtures/dashboards.yml +6 -0
  221. data/test/fixtures/developers.yml +22 -0
  222. data/test/fixtures/developers_projects.yml +17 -0
  223. data/test/fixtures/dog_lovers.yml +7 -0
  224. data/test/fixtures/dogs.yml +4 -0
  225. data/test/fixtures/doubloons.yml +3 -0
  226. data/test/fixtures/edges.yml +5 -0
  227. data/test/fixtures/entrants.yml +14 -0
  228. data/test/fixtures/essays.yml +6 -0
  229. data/test/fixtures/faces.yml +11 -0
  230. data/test/fixtures/fk_test_has_fk.yml +3 -0
  231. data/test/fixtures/fk_test_has_pk.yml +2 -0
  232. data/test/fixtures/friendships.yml +4 -0
  233. data/test/fixtures/funny_jokes.yml +10 -0
  234. data/test/fixtures/interests.yml +33 -0
  235. data/test/fixtures/items.yml +3 -0
  236. data/test/fixtures/jobs.yml +7 -0
  237. data/test/fixtures/legacy_things.yml +3 -0
  238. data/test/fixtures/mateys.yml +4 -0
  239. data/test/fixtures/member_details.yml +8 -0
  240. data/test/fixtures/member_types.yml +6 -0
  241. data/test/fixtures/members.yml +11 -0
  242. data/test/fixtures/memberships.yml +34 -0
  243. data/test/fixtures/men.yml +5 -0
  244. data/test/fixtures/minimalistics.yml +2 -0
  245. data/test/fixtures/minivans.yml +5 -0
  246. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  247. data/test/fixtures/mixins.yml +29 -0
  248. data/test/fixtures/movies.yml +7 -0
  249. data/test/fixtures/naked/csv/accounts.csv +1 -0
  250. data/test/fixtures/naked/yml/accounts.yml +1 -0
  251. data/test/fixtures/naked/yml/companies.yml +1 -0
  252. data/test/fixtures/naked/yml/courses.yml +1 -0
  253. data/test/fixtures/organizations.yml +5 -0
  254. data/test/fixtures/other_topics.yml +42 -0
  255. data/test/fixtures/owners.yml +9 -0
  256. data/test/fixtures/parrots.yml +27 -0
  257. data/test/fixtures/parrots_pirates.yml +7 -0
  258. data/test/fixtures/people.yml +24 -0
  259. data/test/fixtures/peoples_treasures.yml +3 -0
  260. data/test/fixtures/pets.yml +19 -0
  261. data/test/fixtures/pirates.yml +12 -0
  262. data/test/fixtures/posts.yml +80 -0
  263. data/test/fixtures/price_estimates.yml +7 -0
  264. data/test/fixtures/products.yml +4 -0
  265. data/test/fixtures/projects.yml +7 -0
  266. data/test/fixtures/randomly_named_a9.yml +7 -0
  267. data/test/fixtures/ratings.yml +14 -0
  268. data/test/fixtures/readers.yml +11 -0
  269. data/test/fixtures/references.yml +17 -0
  270. data/test/fixtures/reserved_words/distinct.yml +5 -0
  271. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  272. data/test/fixtures/reserved_words/group.yml +14 -0
  273. data/test/fixtures/reserved_words/select.yml +8 -0
  274. data/test/fixtures/reserved_words/values.yml +7 -0
  275. data/test/fixtures/ships.yml +6 -0
  276. data/test/fixtures/speedometers.yml +8 -0
  277. data/test/fixtures/sponsors.yml +12 -0
  278. data/test/fixtures/string_key_objects.yml +7 -0
  279. data/test/fixtures/subscribers.yml +11 -0
  280. data/test/fixtures/subscriptions.yml +12 -0
  281. data/test/fixtures/taggings.yml +78 -0
  282. data/test/fixtures/tags.yml +11 -0
  283. data/test/fixtures/tasks.yml +7 -0
  284. data/test/fixtures/teapots.yml +3 -0
  285. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  286. data/test/fixtures/to_be_linked/users.yml +10 -0
  287. data/test/fixtures/topics.yml +49 -0
  288. data/test/fixtures/toys.yml +14 -0
  289. data/test/fixtures/traffic_lights.yml +10 -0
  290. data/test/fixtures/treasures.yml +10 -0
  291. data/test/fixtures/uuid_children.yml +3 -0
  292. data/test/fixtures/uuid_parents.yml +2 -0
  293. data/test/fixtures/variants.yml +4 -0
  294. data/test/fixtures/vegetables.yml +20 -0
  295. data/test/fixtures/vertices.yml +4 -0
  296. data/test/fixtures/warehouse_things.yml +3 -0
  297. data/test/fixtures/zines.yml +5 -0
  298. data/test/ibm_db_test.rb +24 -24
  299. data/test/migrations/10_urban/9_add_expressions.rb +11 -0
  300. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  301. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -0
  302. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  303. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  304. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  305. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  306. data/test/migrations/rename/1_we_need_things.rb +11 -0
  307. data/test/migrations/rename/2_rename_things.rb +9 -0
  308. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -0
  309. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -0
  310. data/test/migrations/to_copy2/1_create_articles.rb +7 -0
  311. data/test/migrations/to_copy2/2_create_comments.rb +7 -0
  312. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -0
  313. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -0
  314. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -0
  315. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -0
  316. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -0
  317. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -0
  318. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  319. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  320. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -0
  321. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -0
  322. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -0
  323. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -0
  324. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -0
  325. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -0
  326. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -0
  327. data/test/models/admin.rb +5 -0
  328. data/test/models/admin/account.rb +3 -0
  329. data/test/models/admin/randomly_named_c1.rb +3 -0
  330. data/test/models/admin/user.rb +40 -0
  331. data/test/models/aircraft.rb +4 -0
  332. data/test/models/arunit2_model.rb +3 -0
  333. data/test/models/author.rb +212 -0
  334. data/test/models/auto_id.rb +4 -0
  335. data/test/models/autoloadable/extra_firm.rb +2 -0
  336. data/test/models/binary.rb +2 -0
  337. data/test/models/bird.rb +12 -0
  338. data/test/models/book.rb +18 -0
  339. data/test/models/boolean.rb +2 -0
  340. data/test/models/bulb.rb +51 -0
  341. data/test/models/cake_designer.rb +3 -0
  342. data/test/models/car.rb +26 -0
  343. data/test/models/carrier.rb +2 -0
  344. data/test/models/categorization.rb +19 -0
  345. data/test/models/category.rb +35 -0
  346. data/test/models/chef.rb +3 -0
  347. data/test/models/citation.rb +3 -0
  348. data/test/models/club.rb +23 -0
  349. data/test/models/college.rb +10 -0
  350. data/test/models/column.rb +3 -0
  351. data/test/models/column_name.rb +3 -0
  352. data/test/models/comment.rb +64 -0
  353. data/test/models/company.rb +225 -0
  354. data/test/models/company_in_module.rb +98 -0
  355. data/test/models/computer.rb +3 -0
  356. data/test/models/contact.rb +41 -0
  357. data/test/models/contract.rb +20 -0
  358. data/test/models/country.rb +7 -0
  359. data/test/models/course.rb +6 -0
  360. data/test/models/customer.rb +77 -0
  361. data/test/models/customer_carrier.rb +14 -0
  362. data/test/models/dashboard.rb +3 -0
  363. data/test/models/default.rb +2 -0
  364. data/test/models/department.rb +4 -0
  365. data/test/models/developer.rb +252 -0
  366. data/test/models/dog.rb +5 -0
  367. data/test/models/dog_lover.rb +5 -0
  368. data/test/models/doubloon.rb +12 -0
  369. data/test/models/drink_designer.rb +3 -0
  370. data/test/models/edge.rb +5 -0
  371. data/test/models/electron.rb +5 -0
  372. data/test/models/engine.rb +4 -0
  373. data/test/models/entrant.rb +3 -0
  374. data/test/models/essay.rb +5 -0
  375. data/test/models/event.rb +3 -0
  376. data/test/models/eye.rb +37 -0
  377. data/test/models/face.rb +9 -0
  378. data/test/models/friendship.rb +6 -0
  379. data/test/models/guid.rb +2 -0
  380. data/test/models/hotel.rb +6 -0
  381. data/test/models/image.rb +3 -0
  382. data/test/models/interest.rb +5 -0
  383. data/test/models/invoice.rb +4 -0
  384. data/test/models/item.rb +7 -0
  385. data/test/models/job.rb +7 -0
  386. data/test/models/joke.rb +7 -0
  387. data/test/models/keyboard.rb +3 -0
  388. data/test/models/legacy_thing.rb +3 -0
  389. data/test/models/lesson.rb +11 -0
  390. data/test/models/line_item.rb +3 -0
  391. data/test/models/liquid.rb +4 -0
  392. data/test/models/man.rb +11 -0
  393. data/test/models/matey.rb +4 -0
  394. data/test/models/member.rb +41 -0
  395. data/test/models/member_detail.rb +7 -0
  396. data/test/models/member_type.rb +3 -0
  397. data/test/models/membership.rb +35 -0
  398. data/test/models/minimalistic.rb +2 -0
  399. data/test/models/minivan.rb +9 -0
  400. data/test/models/mixed_case_monkey.rb +3 -0
  401. data/test/models/molecule.rb +6 -0
  402. data/test/models/movie.rb +5 -0
  403. data/test/models/order.rb +4 -0
  404. data/test/models/organization.rb +14 -0
  405. data/test/models/owner.rb +34 -0
  406. data/test/models/parrot.rb +29 -0
  407. data/test/models/person.rb +143 -0
  408. data/test/models/personal_legacy_thing.rb +4 -0
  409. data/test/models/pet.rb +15 -0
  410. data/test/models/pirate.rb +92 -0
  411. data/test/models/possession.rb +3 -0
  412. data/test/models/post.rb +264 -0
  413. data/test/models/price_estimate.rb +4 -0
  414. data/test/models/professor.rb +5 -0
  415. data/test/models/project.rb +29 -0
  416. data/test/models/publisher.rb +2 -0
  417. data/test/models/publisher/article.rb +4 -0
  418. data/test/models/publisher/magazine.rb +3 -0
  419. data/test/models/randomly_named_c1.rb +3 -0
  420. data/test/models/rating.rb +4 -0
  421. data/test/models/reader.rb +23 -0
  422. data/test/models/record.rb +2 -0
  423. data/test/models/reference.rb +22 -0
  424. data/test/models/reply.rb +61 -0
  425. data/test/models/ship.rb +33 -0
  426. data/test/models/ship_part.rb +8 -0
  427. data/test/models/shop.rb +17 -0
  428. data/test/models/shop_account.rb +6 -0
  429. data/test/models/speedometer.rb +6 -0
  430. data/test/models/sponsor.rb +7 -0
  431. data/test/models/string_key_object.rb +3 -0
  432. data/test/models/student.rb +4 -0
  433. data/test/models/subject.rb +16 -0
  434. data/test/models/subscriber.rb +8 -0
  435. data/test/models/subscription.rb +4 -0
  436. data/test/models/tag.rb +7 -0
  437. data/test/models/tagging.rb +13 -0
  438. data/test/models/task.rb +5 -0
  439. data/test/models/topic.rb +124 -0
  440. data/test/models/toy.rb +6 -0
  441. data/test/models/traffic_light.rb +4 -0
  442. data/test/models/treasure.rb +14 -0
  443. data/test/models/treaty.rb +7 -0
  444. data/test/models/tyre.rb +11 -0
  445. data/test/models/uuid_child.rb +3 -0
  446. data/test/models/uuid_parent.rb +3 -0
  447. data/test/models/vegetables.rb +24 -0
  448. data/test/models/vehicle.rb +7 -0
  449. data/test/models/vertex.rb +9 -0
  450. data/test/models/warehouse_thing.rb +5 -5
  451. data/test/models/wheel.rb +3 -0
  452. data/test/models/without_table.rb +3 -0
  453. data/test/models/zine.rb +3 -0
  454. data/test/schema/mysql2_specific_schema.rb +58 -0
  455. data/test/schema/mysql_specific_schema.rb +70 -0
  456. data/test/schema/oracle_specific_schema.rb +43 -0
  457. data/test/schema/postgresql_specific_schema.rb +202 -0
  458. data/test/schema/schema.rb +938 -751
  459. data/test/schema/sqlite_specific_schema.rb +22 -0
  460. data/test/support/config.rb +43 -0
  461. data/test/support/connection.rb +22 -0
  462. data/test/support/connection_helper.rb +14 -0
  463. data/test/support/ddl_helper.rb +8 -0
  464. data/test/support/schema_dumping_helper.rb +20 -0
  465. metadata +444 -18
@@ -0,0 +1,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,642 +1,909 @@
1
- require "cases/helper"
2
- require 'models/post'
3
- require 'models/comment'
4
- require 'models/author'
5
- require 'models/topic'
6
- require 'models/reply'
7
- require 'models/category'
8
- require 'models/company'
9
- require 'models/developer'
10
- require 'models/project'
11
- require 'models/minimalistic'
12
- require 'models/warehouse_thing'
13
- require 'models/parrot'
14
- require 'models/minivan'
15
- require 'models/person'
16
- require 'rexml/document'
17
- require 'active_support/core_ext/exception'
18
-
19
- class PersistencesTest < ActiveRecord::TestCase
20
- fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics,
21
- 'warehouse_things', :authors, :categorizations, :categories, :posts, :minivans
22
-
23
- # Skip databases that don't support UPDATE + ORDER BY
24
- unless current_adapter?(:OracleAdapter, :PostgreSQLAdapter)
25
- def test_update_all_ignores_order_without_limit_from_association
26
- author = authors(:david)
27
- assert_nothing_raised do
28
- assert_equal author.posts_with_comments_and_categories.length,
29
- author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
30
- end
31
- end
32
-
33
- def test_update_all_doesnt_ignore_order
34
- assert_equal authors(:david).id + 1, authors(:mary).id # make sure there is going to be a duplicate PK error
35
- test_update_with_order_succeeds = lambda do |order|
36
- begin
37
- Author.order(order).update_all('id = id + 1')
38
- rescue ActiveRecord::ActiveRecordError
39
- false
40
- end
41
- end
42
-
43
- if !current_adapter?(:IBM_DBAdapter) && test_update_with_order_succeeds.call('id DESC')
44
- # The update below goes on successfully in DB2.
45
- 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
46
- else
47
- # test that we're failing because the current Arel's engine doesn't support UPDATE ORDER BY queries is using subselects instead
48
- assert_sql(/\AUPDATE .+ \(SELECT .* ORDER BY id DESC\)\Z/i) do
49
- test_update_with_order_succeeds.call('id DESC')
50
- end
51
- end
52
- end
53
-
54
- def test_update_all_with_order_and_limit_updates_subset_only
55
- author = authors(:david)
56
- assert_nothing_raised do
57
- assert_equal 1, author.posts_sorted_by_id_limited.size
58
- assert_equal 2, author.posts_sorted_by_id_limited.find(:all, :limit => 2).size
59
- assert_equal 1, author.posts_sorted_by_id_limited.update_all([ "body = ?", "bulk update!" ])
60
- assert_equal "bulk update!", posts(:welcome).body
61
- assert_not_equal "bulk update!", posts(:thinking).body
62
- end
63
- end
64
- end
65
-
66
- def test_update_many
67
- topic_data = { 1 => { "content" => "1 updated" }, 2 => { "content" => "2 updated" } }
68
- updated = Topic.update(topic_data.keys, topic_data.values)
69
-
70
- assert_equal 2, updated.size
71
- assert_equal "1 updated", Topic.find(1).content
72
- assert_equal "2 updated", Topic.find(2).content
73
- end
74
-
75
- def test_delete_all
76
- assert Topic.count > 0
77
-
78
- assert_equal Topic.count, Topic.delete_all
79
- end
80
-
81
- def test_update_by_condition
82
- Topic.update_all "content = 'bulk updated!'", ["approved = ?", true]
83
- assert_equal "Have a nice day", Topic.find(1).content
84
- assert_equal "bulk updated!", Topic.find(2).content
85
- end
86
-
87
- def test_increment_attribute
88
- assert_equal 50, accounts(:signals37).credit_limit
89
- accounts(:signals37).increment! :credit_limit
90
- assert_equal 51, accounts(:signals37, :reload).credit_limit
91
-
92
- accounts(:signals37).increment(:credit_limit).increment!(:credit_limit)
93
- assert_equal 53, accounts(:signals37, :reload).credit_limit
94
- end
95
-
96
- def test_increment_nil_attribute
97
- assert_nil topics(:first).parent_id
98
- topics(:first).increment! :parent_id
99
- assert_equal 1, topics(:first).parent_id
100
- end
101
-
102
- def test_increment_attribute_by
103
- assert_equal 50, accounts(:signals37).credit_limit
104
- accounts(:signals37).increment! :credit_limit, 5
105
- assert_equal 55, accounts(:signals37, :reload).credit_limit
106
-
107
- accounts(:signals37).increment(:credit_limit, 1).increment!(:credit_limit, 3)
108
- assert_equal 59, accounts(:signals37, :reload).credit_limit
109
- end
110
-
111
- def test_destroy_all
112
- conditions = "author_name = 'Mary'"
113
- topics_by_mary = Topic.all(:conditions => conditions, :order => 'id')
114
- assert ! topics_by_mary.empty?
115
-
116
- assert_difference('Topic.count', -topics_by_mary.size) do
117
- destroyed = Topic.destroy_all(conditions).sort_by(&:id)
118
- assert_equal topics_by_mary, destroyed
119
- assert destroyed.all? { |topic| topic.frozen? }, "destroyed topics should be frozen"
120
- end
121
- end
122
-
123
- def test_destroy_many
124
- clients = Client.find([2, 3], :order => 'id')
125
-
126
- assert_difference('Client.count', -2) do
127
- destroyed = Client.destroy([2, 3]).sort_by(&:id)
128
- assert_equal clients, destroyed
129
- assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
130
- end
131
- end
132
-
133
- def test_delete_many
134
- original_count = Topic.count
135
- Topic.delete(deleting = [1, 2])
136
- assert_equal original_count - deleting.size, Topic.count
137
- end
138
-
139
- def test_decrement_attribute
140
- assert_equal 50, accounts(:signals37).credit_limit
141
-
142
- accounts(:signals37).decrement!(:credit_limit)
143
- assert_equal 49, accounts(:signals37, :reload).credit_limit
144
-
145
- accounts(:signals37).decrement(:credit_limit).decrement!(:credit_limit)
146
- assert_equal 47, accounts(:signals37, :reload).credit_limit
147
- end
148
-
149
- def test_decrement_attribute_by
150
- assert_equal 50, accounts(:signals37).credit_limit
151
- accounts(:signals37).decrement! :credit_limit, 5
152
- assert_equal 45, accounts(:signals37, :reload).credit_limit
153
-
154
- accounts(:signals37).decrement(:credit_limit, 1).decrement!(:credit_limit, 3)
155
- assert_equal 41, accounts(:signals37, :reload).credit_limit
156
- end
157
-
158
- def test_create
159
- topic = Topic.new
160
- topic.title = "New Topic"
161
- topic.save
162
- topic_reloaded = Topic.find(topic.id)
163
- assert_equal("New Topic", topic_reloaded.title)
164
- end
165
-
166
- def test_save!
167
- topic = Topic.new(:title => "New Topic")
168
- assert topic.save!
169
-
170
- reply = WrongReply.new
171
- assert_raise(ActiveRecord::RecordInvalid) { reply.save! }
172
- end
173
-
174
- def test_save_null_string_attributes
175
- topic = Topic.find(1)
176
- topic.attributes = { "title" => "null", "author_name" => "null" }
177
- topic.save!
178
- topic.reload
179
- assert_equal("null", topic.title)
180
- assert_equal("null", topic.author_name)
181
- end
182
-
183
- def test_save_nil_string_attributes
184
- topic = Topic.find(1)
185
- topic.title = nil
186
- topic.save!
187
- topic.reload
188
- assert_nil topic.title
189
- end
190
-
191
- def test_save_for_record_with_only_primary_key
192
- minimalistic = Minimalistic.new
193
- assert_nothing_raised { minimalistic.save }
194
- end
195
-
196
- def test_save_for_record_with_only_primary_key_that_is_provided
197
- assert_nothing_raised { Minimalistic.create!(:id => 2) }
198
- end
199
-
200
- def test_create_many
201
- topics = Topic.create([ { "title" => "first" }, { "title" => "second" }])
202
- assert_equal 2, topics.size
203
- assert_equal "first", topics.first.title
204
- end
205
-
206
- def test_create_columns_not_equal_attributes
207
- topic = Topic.allocate.init_with(
208
- 'attributes' => {
209
- 'title' => 'Another New Topic',
210
- 'does_not_exist' => 'test'
211
- }
212
- )
213
- assert_nothing_raised { topic.save }
214
- end
215
-
216
- def test_create_through_factory_with_block
217
- topic = Topic.create("title" => "New Topic") do |t|
218
- t.author_name = "David"
219
- end
220
- assert_equal("New Topic", topic.title)
221
- assert_equal("David", topic.author_name)
222
- end
223
-
224
- def test_create_many_through_factory_with_block
225
- topics = Topic.create([ { "title" => "first" }, { "title" => "second" }]) do |t|
226
- t.author_name = "David"
227
- end
228
- assert_equal 2, topics.size
229
- topic1, topic2 = Topic.find(topics[0].id), Topic.find(topics[1].id)
230
- assert_equal "first", topic1.title
231
- assert_equal "David", topic1.author_name
232
- assert_equal "second", topic2.title
233
- assert_equal "David", topic2.author_name
234
- end
235
-
236
- def test_update
237
- topic = Topic.new
238
- topic.title = "Another New Topic"
239
- topic.written_on = "2003-12-12 23:23:00"
240
- topic.save
241
- topicReloaded = Topic.find(topic.id)
242
- assert_equal("Another New Topic", topicReloaded.title)
243
-
244
- topicReloaded.title = "Updated topic"
245
- topicReloaded.save
246
-
247
- topicReloadedAgain = Topic.find(topic.id)
248
-
249
- assert_equal("Updated topic", topicReloadedAgain.title)
250
- end
251
-
252
- def test_update_columns_not_equal_attributes
253
- topic = Topic.new
254
- topic.title = "Still another topic"
255
- topic.save
256
-
257
- topicReloaded = Topic.allocate
258
- topicReloaded.init_with(
259
- 'attributes' => topic.attributes.merge('does_not_exist' => 'test')
260
- )
261
- topicReloaded.title = 'A New Topic'
262
- assert_nothing_raised { topicReloaded.save }
263
- end
264
-
265
- def test_update_for_record_with_only_primary_key
266
- minimalistic = minimalistics(:first)
267
- assert_nothing_raised { minimalistic.save }
268
- end
269
-
270
- def test_update_sti_type
271
- assert_instance_of Reply, topics(:second)
272
-
273
- topic = topics(:second).becomes(Topic)
274
- assert_instance_of Topic, topic
275
- topic.save!
276
- assert_instance_of Topic, Topic.find(topic.id)
277
- end
278
-
279
- def test_delete
280
- topic = Topic.find(1)
281
- assert_equal topic, topic.delete, 'topic.delete did not return self'
282
- assert topic.frozen?, 'topic not frozen after delete'
283
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
284
- end
285
-
286
- def test_delete_doesnt_run_callbacks
287
- Topic.find(1).delete
288
- assert_not_nil Topic.find(2)
289
- end
290
-
291
- def test_destroy
292
- topic = Topic.find(1)
293
- assert_equal topic, topic.destroy, 'topic.destroy did not return self'
294
- assert topic.frozen?, 'topic not frozen after destroy'
295
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
296
- end
297
-
298
- def test_record_not_found_exception
299
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(99999) }
300
- end
301
-
302
- def test_update_all
303
- assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'")
304
- assert_equal "bulk updated!", Topic.find(1).content
305
- assert_equal "bulk updated!", Topic.find(2).content
306
-
307
- assert_equal Topic.count, Topic.update_all(['content = ?', 'bulk updated again!'])
308
- assert_equal "bulk updated again!", Topic.find(1).content
309
- assert_equal "bulk updated again!", Topic.find(2).content
310
-
311
- assert_equal Topic.count, Topic.update_all(['content = ?', nil])
312
- assert_nil Topic.find(1).content
313
- end
314
-
315
- def test_update_all_with_hash
316
- assert_not_nil Topic.find(1).last_read
317
- assert_equal Topic.count, Topic.update_all(:content => 'bulk updated with hash!', :last_read => nil)
318
- assert_equal "bulk updated with hash!", Topic.find(1).content
319
- assert_equal "bulk updated with hash!", Topic.find(2).content
320
- assert_nil Topic.find(1).last_read
321
- assert_nil Topic.find(2).last_read
322
- end
323
-
324
- def test_update_all_with_non_standard_table_name
325
- assert_equal 1, WarehouseThing.update_all(['value = ?', 0], ['id = ?', 1])
326
- assert_equal 0, WarehouseThing.find(1).value
327
- end
328
-
329
- def test_delete_new_record
330
- client = Client.new
331
- client.delete
332
- assert client.frozen?
333
- end
334
-
335
- def test_delete_record_with_associations
336
- client = Client.find(3)
337
- client.delete
338
- assert client.frozen?
339
- assert_kind_of Firm, client.firm
340
- assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
341
- end
342
-
343
- def test_destroy_new_record
344
- client = Client.new
345
- client.destroy
346
- assert client.frozen?
347
- end
348
-
349
- def test_destroy_record_with_associations
350
- client = Client.find(3)
351
- client.destroy
352
- assert client.frozen?
353
- assert_kind_of Firm, client.firm
354
- assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" }
355
- end
356
-
357
- def test_update_attribute
358
- assert !Topic.find(1).approved?
359
- Topic.find(1).update_attribute("approved", true)
360
- assert Topic.find(1).approved?
361
-
362
- Topic.find(1).update_attribute(:approved, false)
363
- assert !Topic.find(1).approved?
364
- end
365
-
366
- def test_update_attribute_does_not_choke_on_nil
367
- assert Topic.find(1).update_attributes(nil)
368
- end
369
-
370
- def test_update_attribute_for_readonly_attribute
371
- minivan = Minivan.find('m1')
372
- assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_attribute(:color, 'black') }
373
- end
374
-
375
- # This test is correct, but it is hard to fix it since
376
- # update_attribute trigger simply call save! that triggers
377
- # all callbacks.
378
- # def test_update_attribute_with_one_changed_and_one_updated
379
- # t = Topic.order('id').limit(1).first
380
- # title, author_name = t.title, t.author_name
381
- # t.author_name = 'John'
382
- # t.update_attribute(:title, 'super_title')
383
- # assert_equal 'John', t.author_name
384
- # assert_equal 'super_title', t.title
385
- # assert t.changed?, "topic should have changed"
386
- # assert t.author_name_changed?, "author_name should have changed"
387
- # assert !t.title_changed?, "title should not have changed"
388
- # assert_nil t.title_change, 'title change should be nil'
389
- # assert_equal ['author_name'], t.changed
390
- #
391
- # t.reload
392
- # assert_equal 'David', t.author_name
393
- # assert_equal 'super_title', t.title
394
- # end
395
-
396
- def test_update_attribute_with_one_updated
397
- t = Topic.first
398
- title = t.title
399
- t.update_attribute(:title, 'super_title')
400
- assert_equal 'super_title', t.title
401
- assert !t.changed?, "topic should not have changed"
402
- assert !t.title_changed?, "title should not have changed"
403
- assert_nil t.title_change, 'title change should be nil'
404
-
405
- t.reload
406
- assert_equal 'super_title', t.title
407
- end
408
-
409
- def test_update_attribute_for_updated_at_on
410
- developer = Developer.find(1)
411
- prev_month = Time.now.prev_month
412
-
413
- developer.update_attribute(:updated_at, prev_month)
414
- assert_equal prev_month, developer.updated_at
415
-
416
- developer.update_attribute(:salary, 80001)
417
- assert_not_equal prev_month, developer.updated_at
418
-
419
- developer.reload
420
- assert_not_equal prev_month, developer.updated_at
421
- end
422
-
423
- def test_update_column
424
- topic = Topic.find(1)
425
- topic.update_column("approved", true)
426
- assert topic.approved?
427
- topic.reload
428
- assert topic.approved?
429
-
430
- topic.update_column(:approved, false)
431
- assert !topic.approved?
432
- topic.reload
433
- assert !topic.approved?
434
- end
435
-
436
- def test_update_column_should_not_use_setter_method
437
- dev = Developer.find(1)
438
- dev.instance_eval { def salary=(value); write_attribute(:salary, value * 2); end }
439
-
440
- dev.update_column(:salary, 80000)
441
- assert_equal 80000, dev.salary
442
-
443
- dev.reload
444
- assert_equal 80000, dev.salary
445
- end
446
-
447
- def test_update_column_should_raise_exception_if_new_record
448
- topic = Topic.new
449
- assert_raises(ActiveRecord::ActiveRecordError) { topic.update_column("approved", false) }
450
- end
451
-
452
- def test_update_column_should_not_leave_the_object_dirty
453
- topic = Topic.find(1)
454
- topic.update_attribute("content", "Have a nice day")
455
-
456
- topic.reload
457
- topic.update_column(:content, "You too")
458
- assert_equal [], topic.changed
459
-
460
- topic.reload
461
- topic.update_column("content", "Have a nice day")
462
- assert_equal [], topic.changed
463
- end
464
-
465
- def test_update_column_with_model_having_primary_key_other_than_id
466
- minivan = Minivan.find('m1')
467
- new_name = 'sebavan'
468
-
469
- minivan.update_column(:name, new_name)
470
- assert_equal new_name, minivan.name
471
- end
472
-
473
- def test_update_column_for_readonly_attribute
474
- minivan = Minivan.find('m1')
475
- prev_color = minivan.color
476
- assert_raises(ActiveRecord::ActiveRecordError) { minivan.update_column(:color, 'black') }
477
- assert_equal prev_color, minivan.color
478
- end
479
-
480
- def test_update_column_should_not_modify_updated_at
481
- developer = Developer.find(1)
482
- prev_month = Time.now.prev_month
483
-
484
- developer.update_column(:updated_at, prev_month)
485
- assert_equal prev_month, developer.updated_at
486
-
487
- developer.update_column(:salary, 80001)
488
- assert_equal prev_month, developer.updated_at
489
-
490
- developer.reload
491
- assert_equal prev_month.to_i, developer.updated_at.to_i
492
- end
493
-
494
- def test_update_column_with_one_changed_and_one_updated
495
- t = Topic.order('id').limit(1).first
496
- title, author_name = t.title, t.author_name
497
- t.author_name = 'John'
498
- t.update_column(:title, 'super_title')
499
- assert_equal 'John', t.author_name
500
- assert_equal 'super_title', t.title
501
- assert t.changed?, "topic should have changed"
502
- assert t.author_name_changed?, "author_name should have changed"
503
-
504
- t.reload
505
- assert_equal author_name, t.author_name
506
- assert_equal 'super_title', t.title
507
- end
508
-
509
- def test_update_attributes
510
- topic = Topic.find(1)
511
- assert !topic.approved?
512
- assert_equal "The First Topic", topic.title
513
-
514
- topic.update_attributes("approved" => true, "title" => "The First Topic Updated")
515
- topic.reload
516
- assert topic.approved?
517
- assert_equal "The First Topic Updated", topic.title
518
-
519
- topic.update_attributes(:approved => false, :title => "The First Topic")
520
- topic.reload
521
- assert !topic.approved?
522
- assert_equal "The First Topic", topic.title
523
- end
524
-
525
- def test_update_attributes_as_admin
526
- person = TightPerson.create({ "first_name" => 'Joshua' })
527
- person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
528
- person.reload
529
-
530
- assert_equal 'Josh', person.first_name
531
- assert_equal 'm', person.gender
532
- assert_equal 'from NZ', person.comments
533
- end
534
-
535
- def test_update_attributes_without_protection
536
- person = TightPerson.create({ "first_name" => 'Joshua' })
537
- person.update_attributes({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
538
- person.reload
539
-
540
- assert_equal 'Josh', person.first_name
541
- assert_equal 'm', person.gender
542
- assert_equal 'from NZ', person.comments
543
- end
544
-
545
- def test_update_attributes!
546
- Reply.validates_presence_of(:title)
547
- reply = Reply.find(2)
548
- assert_equal "The Second Topic of the day", reply.title
549
- assert_equal "Have a nice day", reply.content
550
-
551
- reply.update_attributes!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening")
552
- reply.reload
553
- assert_equal "The Second Topic of the day updated", reply.title
554
- assert_equal "Have a nice evening", reply.content
555
-
556
- reply.update_attributes!(:title => "The Second Topic of the day", :content => "Have a nice day")
557
- reply.reload
558
- assert_equal "The Second Topic of the day", reply.title
559
- assert_equal "Have a nice day", reply.content
560
-
561
- assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") }
562
- ensure
563
- Reply.reset_callbacks(:validate)
564
- end
565
-
566
- def test_update_attributes_with_bang_as_admin
567
- person = TightPerson.create({ "first_name" => 'Joshua' })
568
- person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :as => :admin)
569
- person.reload
570
-
571
- assert_equal 'Josh', person.first_name
572
- assert_equal 'm', person.gender
573
- assert_equal 'from NZ', person.comments
574
- end
575
-
576
- def test_update_attributestes_with_bang_without_protection
577
- person = TightPerson.create({ "first_name" => 'Joshua' })
578
- person.update_attributes!({ "first_name" => 'Josh', "gender" => 'm', "comments" => 'from NZ' }, :without_protection => true)
579
- person.reload
580
-
581
- assert_equal 'Josh', person.first_name
582
- assert_equal 'm', person.gender
583
- assert_equal 'from NZ', person.comments
584
- end
585
-
586
- def test_destroyed_returns_boolean
587
- developer = Developer.first
588
- assert_equal false, developer.destroyed?
589
- developer.destroy
590
- assert_equal true, developer.destroyed?
591
-
592
- developer = Developer.last
593
- assert_equal false, developer.destroyed?
594
- developer.delete
595
- assert_equal true, developer.destroyed?
596
- end
597
-
598
- def test_persisted_returns_boolean
599
- developer = Developer.new(:name => "Jose")
600
- assert_equal false, developer.persisted?
601
- developer.save!
602
- assert_equal true, developer.persisted?
603
-
604
- developer = Developer.first
605
- assert_equal true, developer.persisted?
606
- developer.destroy
607
- assert_equal false, developer.persisted?
608
-
609
- developer = Developer.last
610
- assert_equal true, developer.persisted?
611
- developer.delete
612
- assert_equal false, developer.persisted?
613
- end
614
-
615
- def test_class_level_destroy
616
- should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
617
- Topic.find(1).replies << should_be_destroyed_reply
618
-
619
- Topic.destroy(1)
620
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
621
- assert_raise(ActiveRecord::RecordNotFound) { Reply.find(should_be_destroyed_reply.id) }
622
- end
623
-
624
- def test_class_level_delete
625
- should_be_destroyed_reply = Reply.create("title" => "hello", "content" => "world")
626
- Topic.find(1).replies << should_be_destroyed_reply
627
-
628
- Topic.delete(1)
629
- assert_raise(ActiveRecord::RecordNotFound) { Topic.find(1) }
630
- assert_nothing_raised { Reply.find(should_be_destroyed_reply.id) }
631
- end
632
-
633
- def test_create_with_custom_timestamps
634
- custom_datetime = 1.hour.ago.beginning_of_day
635
-
636
- %w(created_at created_on updated_at updated_on).each do |attribute|
637
- parrot = LiveParrot.create(:name => "colombian", attribute => custom_datetime)
638
- assert_equal custom_datetime, parrot[attribute]
639
- end
640
- end
641
-
642
- 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