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,125 +1,125 @@
1
- require 'cases/helper'
2
-
3
- module ActiveRecord
4
- class AttributeDecoratorsTest < ActiveRecord::TestCase
5
- class Model < ActiveRecord::Base
6
- self.table_name = 'attribute_decorators_model'
7
- end
8
-
9
- class StringDecorator < SimpleDelegator
10
- def initialize(delegate, decoration = "decorated!")
11
- @decoration = decoration
12
- super(delegate)
13
- end
14
-
15
- def type_cast_from_user(value)
16
- "#{super} #{@decoration}"
17
- end
18
-
19
- alias type_cast_from_database type_cast_from_user
20
- end
21
-
22
- setup do
23
- @connection = ActiveRecord::Base.connection
24
- @connection.create_table :attribute_decorators_model, force: true do |t|
25
- t.string :a_string
26
- end
27
- end
28
-
29
- teardown do
30
- return unless @connection
31
- @connection.drop_table 'attribute_decorators_model' if @connection.table_exists? 'attribute_decorators_model'
32
- Model.attribute_type_decorations.clear
33
- Model.reset_column_information
34
- end
35
-
36
- test "attributes can be decorated" do
37
- model = Model.new(a_string: 'Hello')
38
- assert_equal 'Hello', model.a_string
39
-
40
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
41
-
42
- model = Model.new(a_string: 'Hello')
43
- assert_equal 'Hello decorated!', model.a_string
44
- end
45
-
46
- test "decoration does not eagerly load existing columns" do
47
- Model.reset_column_information
48
- assert_no_queries do
49
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
50
- end
51
- end
52
-
53
- test "undecorated columns are not touched" do
54
- Model.attribute :another_string, Type::String.new, default: 'something or other'
55
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
56
-
57
- assert_equal 'something or other', Model.new.another_string
58
- end
59
-
60
- test "decorators can be chained" do
61
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
62
- Model.decorate_attribute_type(:a_string, :other) { |t| StringDecorator.new(t) }
63
-
64
- model = Model.new(a_string: 'Hello!')
65
-
66
- assert_equal 'Hello! decorated! decorated!', model.a_string
67
- end
68
-
69
- test "decoration of the same type multiple times is idempotent" do
70
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
71
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
72
-
73
- model = Model.new(a_string: 'Hello')
74
- assert_equal 'Hello decorated!', model.a_string
75
- end
76
-
77
- test "decorations occur in order of declaration" do
78
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
79
- Model.decorate_attribute_type(:a_string, :other) do |type|
80
- StringDecorator.new(type, 'decorated again!')
81
- end
82
-
83
- model = Model.new(a_string: 'Hello!')
84
-
85
- assert_equal 'Hello! decorated! decorated again!', model.a_string
86
- end
87
-
88
- test "decorating attributes does not modify parent classes" do
89
- Model.attribute :another_string, Type::String.new, default: 'whatever'
90
- Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
91
- child_class = Class.new(Model)
92
- child_class.decorate_attribute_type(:another_string, :test) { |t| StringDecorator.new(t) }
93
- child_class.decorate_attribute_type(:a_string, :other) { |t| StringDecorator.new(t) }
94
-
95
- model = Model.new(a_string: 'Hello!')
96
- child = child_class.new(a_string: 'Hello!')
97
-
98
- assert_equal 'Hello! decorated!', model.a_string
99
- assert_equal 'whatever', model.another_string
100
- assert_equal 'Hello! decorated! decorated!', child.a_string
101
- assert_equal 'whatever decorated!', child.another_string
102
- end
103
-
104
- class Multiplier < SimpleDelegator
105
- def type_cast_from_user(value)
106
- return if value.nil?
107
- value * 2
108
- end
109
- alias type_cast_from_database type_cast_from_user
110
- end
111
-
112
- test "decorating with a proc" do
113
- Model.attribute :an_int, Type::Integer.new
114
- type_is_integer = proc { |_, type| type.type == :integer }
115
- Model.decorate_matching_attribute_types type_is_integer, :multiplier do |type|
116
- Multiplier.new(type)
117
- end
118
-
119
- model = Model.new(a_string: 'whatever', an_int: 1)
120
-
121
- assert_equal 'whatever', model.a_string
122
- assert_equal 2, model.an_int
123
- end
124
- end
125
- end
1
+ require 'cases/helper'
2
+
3
+ module ActiveRecord
4
+ class AttributeDecoratorsTest < ActiveRecord::TestCase
5
+ class Model < ActiveRecord::Base
6
+ self.table_name = 'attribute_decorators_model'
7
+ end
8
+
9
+ class StringDecorator < SimpleDelegator
10
+ def initialize(delegate, decoration = "decorated!")
11
+ @decoration = decoration
12
+ super(delegate)
13
+ end
14
+
15
+ def type_cast_from_user(value)
16
+ "#{super} #{@decoration}"
17
+ end
18
+
19
+ alias type_cast_from_database type_cast_from_user
20
+ end
21
+
22
+ setup do
23
+ @connection = ActiveRecord::Base.connection
24
+ @connection.create_table :attribute_decorators_model, force: true do |t|
25
+ t.string :a_string
26
+ end
27
+ end
28
+
29
+ teardown do
30
+ return unless @connection
31
+ @connection.drop_table 'attribute_decorators_model' if @connection.table_exists? 'attribute_decorators_model'
32
+ Model.attribute_type_decorations.clear
33
+ Model.reset_column_information
34
+ end
35
+
36
+ test "attributes can be decorated" do
37
+ model = Model.new(a_string: 'Hello')
38
+ assert_equal 'Hello', model.a_string
39
+
40
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
41
+
42
+ model = Model.new(a_string: 'Hello')
43
+ assert_equal 'Hello decorated!', model.a_string
44
+ end
45
+
46
+ test "decoration does not eagerly load existing columns" do
47
+ Model.reset_column_information
48
+ assert_no_queries do
49
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
50
+ end
51
+ end
52
+
53
+ test "undecorated columns are not touched" do
54
+ Model.attribute :another_string, Type::String.new, default: 'something or other'
55
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
56
+
57
+ assert_equal 'something or other', Model.new.another_string
58
+ end
59
+
60
+ test "decorators can be chained" do
61
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
62
+ Model.decorate_attribute_type(:a_string, :other) { |t| StringDecorator.new(t) }
63
+
64
+ model = Model.new(a_string: 'Hello!')
65
+
66
+ assert_equal 'Hello! decorated! decorated!', model.a_string
67
+ end
68
+
69
+ test "decoration of the same type multiple times is idempotent" do
70
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
71
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
72
+
73
+ model = Model.new(a_string: 'Hello')
74
+ assert_equal 'Hello decorated!', model.a_string
75
+ end
76
+
77
+ test "decorations occur in order of declaration" do
78
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
79
+ Model.decorate_attribute_type(:a_string, :other) do |type|
80
+ StringDecorator.new(type, 'decorated again!')
81
+ end
82
+
83
+ model = Model.new(a_string: 'Hello!')
84
+
85
+ assert_equal 'Hello! decorated! decorated again!', model.a_string
86
+ end
87
+
88
+ test "decorating attributes does not modify parent classes" do
89
+ Model.attribute :another_string, Type::String.new, default: 'whatever'
90
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
91
+ child_class = Class.new(Model)
92
+ child_class.decorate_attribute_type(:another_string, :test) { |t| StringDecorator.new(t) }
93
+ child_class.decorate_attribute_type(:a_string, :other) { |t| StringDecorator.new(t) }
94
+
95
+ model = Model.new(a_string: 'Hello!')
96
+ child = child_class.new(a_string: 'Hello!')
97
+
98
+ assert_equal 'Hello! decorated!', model.a_string
99
+ assert_equal 'whatever', model.another_string
100
+ assert_equal 'Hello! decorated! decorated!', child.a_string
101
+ assert_equal 'whatever decorated!', child.another_string
102
+ end
103
+
104
+ class Multiplier < SimpleDelegator
105
+ def type_cast_from_user(value)
106
+ return if value.nil?
107
+ value * 2
108
+ end
109
+ alias type_cast_from_database type_cast_from_user
110
+ end
111
+
112
+ test "decorating with a proc" do
113
+ Model.attribute :an_int, Type::Integer.new
114
+ type_is_integer = proc { |_, type| type.type == :integer }
115
+ Model.decorate_matching_attribute_types type_is_integer, :multiplier do |type|
116
+ Multiplier.new(type)
117
+ end
118
+
119
+ model = Model.new(a_string: 'whatever', an_int: 1)
120
+
121
+ assert_equal 'whatever', model.a_string
122
+ assert_equal 2, model.an_int
123
+ end
124
+ end
125
+ end
@@ -1,60 +1,60 @@
1
- require "cases/helper"
2
- require 'thread'
3
-
4
- module ActiveRecord
5
- module AttributeMethods
6
- class ReadTest < ActiveRecord::TestCase
7
- class FakeColumn < Struct.new(:name)
8
- def type; :integer; end
9
- end
10
-
11
- def setup
12
- @klass = Class.new do
13
- def self.superclass; Base; end
14
- def self.base_class; self; end
15
- def self.decorate_matching_attribute_types(*); end
16
- def self.initialize_generated_modules; end
17
-
18
- include ActiveRecord::AttributeMethods
19
-
20
- def self.column_names
21
- %w{ one two three }
22
- end
23
-
24
- def self.primary_key
25
- end
26
-
27
- def self.columns
28
- column_names.map { FakeColumn.new(name) }
29
- end
30
-
31
- def self.columns_hash
32
- Hash[column_names.map { |name|
33
- [name, FakeColumn.new(name)]
34
- }]
35
- end
36
- end
37
- end
38
-
39
- def test_define_attribute_methods
40
- instance = @klass.new
41
-
42
- @klass.column_names.each do |name|
43
- assert !instance.methods.map(&:to_s).include?(name)
44
- end
45
-
46
- @klass.define_attribute_methods
47
-
48
- @klass.column_names.each do |name|
49
- assert instance.methods.map(&:to_s).include?(name), "#{name} is not defined"
50
- end
51
- end
52
-
53
- def test_attribute_methods_generated?
54
- assert_not @klass.method_defined?(:one)
55
- @klass.define_attribute_methods
56
- assert @klass.method_defined?(:one)
57
- end
58
- end
59
- end
60
- end
1
+ require "cases/helper"
2
+ require 'thread'
3
+
4
+ module ActiveRecord
5
+ module AttributeMethods
6
+ class ReadTest < ActiveRecord::TestCase
7
+ class FakeColumn < Struct.new(:name)
8
+ def type; :integer; end
9
+ end
10
+
11
+ def setup
12
+ @klass = Class.new do
13
+ def self.superclass; Base; end
14
+ def self.base_class; self; end
15
+ def self.decorate_matching_attribute_types(*); end
16
+ def self.initialize_generated_modules; end
17
+
18
+ include ActiveRecord::AttributeMethods
19
+
20
+ def self.column_names
21
+ %w{ one two three }
22
+ end
23
+
24
+ def self.primary_key
25
+ end
26
+
27
+ def self.columns
28
+ column_names.map { FakeColumn.new(name) }
29
+ end
30
+
31
+ def self.columns_hash
32
+ Hash[column_names.map { |name|
33
+ [name, FakeColumn.new(name)]
34
+ }]
35
+ end
36
+ end
37
+ end
38
+
39
+ def test_define_attribute_methods
40
+ instance = @klass.new
41
+
42
+ @klass.column_names.each do |name|
43
+ assert !instance.methods.map(&:to_s).include?(name)
44
+ end
45
+
46
+ @klass.define_attribute_methods
47
+
48
+ @klass.column_names.each do |name|
49
+ assert instance.methods.map(&:to_s).include?(name), "#{name} is not defined"
50
+ end
51
+ end
52
+
53
+ def test_attribute_methods_generated?
54
+ assert_not @klass.method_defined?(:one)
55
+ @klass.define_attribute_methods
56
+ assert @klass.method_defined?(:one)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -1,29 +1,29 @@
1
- require "cases/helper"
2
-
3
- module ActiveRecord
4
- module AttributeMethods
5
- class SerializationTest < ActiveSupport::TestCase
6
- class FakeColumn < Struct.new(:name)
7
- def type; :integer; end
8
- def type_cast(s); "#{s}!"; end
9
- end
10
-
11
- class NullCoder
12
- def load(v); v; end
13
- end
14
-
15
- def test_type_cast_serialized_value
16
- value = Serialization::Attribute.new(NullCoder.new, "Hello world", :serialized)
17
- type = Serialization::Type.new(FakeColumn.new)
18
- assert_equal "Hello world!", type.type_cast(value)
19
- end
20
-
21
- def test_type_cast_unserialized_value
22
- value = Serialization::Attribute.new(nil, "Hello world", :unserialized)
23
- type = Serialization::Type.new(FakeColumn.new)
24
- type.type_cast(value)
25
- assert_equal "Hello world", type.type_cast(value)
26
- end
27
- end
28
- end
29
- end
1
+ require "cases/helper"
2
+
3
+ module ActiveRecord
4
+ module AttributeMethods
5
+ class SerializationTest < ActiveSupport::TestCase
6
+ class FakeColumn < Struct.new(:name)
7
+ def type; :integer; end
8
+ def type_cast(s); "#{s}!"; end
9
+ end
10
+
11
+ class NullCoder
12
+ def load(v); v; end
13
+ end
14
+
15
+ def test_type_cast_serialized_value
16
+ value = Serialization::Attribute.new(NullCoder.new, "Hello world", :serialized)
17
+ type = Serialization::Type.new(FakeColumn.new)
18
+ assert_equal "Hello world!", type.type_cast(value)
19
+ end
20
+
21
+ def test_type_cast_unserialized_value
22
+ value = Serialization::Attribute.new(nil, "Hello world", :unserialized)
23
+ type = Serialization::Type.new(FakeColumn.new)
24
+ type.type_cast(value)
25
+ assert_equal "Hello world", type.type_cast(value)
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,952 +1,952 @@
1
- require "cases/helper"
2
- require 'models/minimalistic'
3
- require 'models/developer'
4
- require 'models/computer'
5
- require 'models/auto_id'
6
- require 'models/boolean'
7
- require 'models/computer'
8
- require 'models/topic'
9
- require 'models/company'
10
- require 'models/category'
11
- require 'models/reply'
12
- require 'models/contact'
13
- require 'models/keyboard'
14
-
15
- class AttributeMethodsTest < ActiveRecord::TestCase
16
- include InTimeZone
17
-
18
- fixtures :topics, :developers, :companies, :computers
19
-
20
- def setup
21
- @old_matchers = ActiveRecord::Base.send(:attribute_method_matchers).dup
22
- @target = Class.new(ActiveRecord::Base)
23
- @target.table_name = 'topics'
24
- end
25
-
26
- teardown do
27
- ActiveRecord::Base.send(:attribute_method_matchers).clear
28
- ActiveRecord::Base.send(:attribute_method_matchers).concat(@old_matchers)
29
- end
30
-
31
- def test_attribute_for_inspect
32
- t = topics(:first)
33
- t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
34
-
35
- assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
36
- assert_equal '"The First Topic Now Has A Title With\nNewlines And ..."', t.attribute_for_inspect(:title)
37
- end
38
-
39
- def test_attribute_present
40
- t = Topic.new
41
- t.title = "hello there!"
42
- t.written_on = Time.now
43
- t.author_name = ""
44
- assert t.attribute_present?("title")
45
- assert t.attribute_present?("written_on")
46
- assert !t.attribute_present?("content")
47
- assert !t.attribute_present?("author_name")
48
- end
49
-
50
- def test_attribute_present_with_booleans
51
- b1 = Boolean.new
52
- b1.value = false
53
- assert b1.attribute_present?(:value)
54
-
55
- b2 = Boolean.new
56
- b2.value = true
57
- assert b2.attribute_present?(:value)
58
-
59
- b3 = Boolean.new
60
- assert !b3.attribute_present?(:value)
61
-
62
- b4 = Boolean.new
63
- b4.value = false
64
- b4.save!
65
- assert Boolean.find(b4.id).attribute_present?(:value)
66
- end
67
-
68
- def test_caching_nil_primary_key
69
- klass = Class.new(Minimalistic)
70
- klass.expects(:reset_primary_key).returns(nil).once
71
- 2.times { klass.primary_key }
72
- end
73
-
74
- def test_attribute_keys_on_new_instance
75
- t = Topic.new
76
- assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
77
- assert_raise(NoMethodError) { t.title2 }
78
- end
79
-
80
- def test_boolean_attributes
81
- assert !Topic.find(1).approved?
82
- assert Topic.find(2).approved?
83
- end
84
-
85
- def test_set_attributes
86
- topic = Topic.find(1)
87
- topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
88
- topic.save
89
- assert_equal("Budget", topic.title)
90
- assert_equal("Jason", topic.author_name)
91
- assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
92
- end
93
-
94
- def test_set_attributes_without_hash
95
- topic = Topic.new
96
- assert_raise(ArgumentError) { topic.attributes = '' }
97
- end
98
-
99
- def test_integers_as_nil
100
- test = AutoId.create('value' => '')
101
- assert_nil AutoId.find(test.id).value
102
- end
103
-
104
- def test_set_attributes_with_block
105
- topic = Topic.new do |t|
106
- t.title = "Budget"
107
- t.author_name = "Jason"
108
- end
109
-
110
- assert_equal("Budget", topic.title)
111
- assert_equal("Jason", topic.author_name)
112
- end
113
-
114
- def test_respond_to?
115
- topic = Topic.find(1)
116
- assert_respond_to topic, "title"
117
- assert_respond_to topic, "title?"
118
- assert_respond_to topic, "title="
119
- assert_respond_to topic, :title
120
- assert_respond_to topic, :title?
121
- assert_respond_to topic, :title=
122
- assert_respond_to topic, "author_name"
123
- assert_respond_to topic, "attribute_names"
124
- assert !topic.respond_to?("nothingness")
125
- assert !topic.respond_to?(:nothingness)
126
- end
127
-
128
- def test_respond_to_with_custom_primary_key
129
- keyboard = Keyboard.create
130
- assert_not_nil keyboard.key_number
131
- assert_equal keyboard.key_number, keyboard.id
132
- assert keyboard.respond_to?('key_number')
133
- assert keyboard.respond_to?('id')
134
- end
135
-
136
- def test_id_before_type_cast_with_custom_primary_key
137
- keyboard = Keyboard.create
138
- keyboard.key_number = '10'
139
- assert_equal '10', keyboard.id_before_type_cast
140
- assert_equal nil, keyboard.read_attribute_before_type_cast('id')
141
- assert_equal '10', keyboard.read_attribute_before_type_cast('key_number')
142
- assert_equal '10', keyboard.read_attribute_before_type_cast(:key_number)
143
- end
144
-
145
- # Syck calls respond_to? before actually calling initialize
146
- def test_respond_to_with_allocated_object
147
- klass = Class.new(ActiveRecord::Base) do
148
- self.table_name = 'topics'
149
- end
150
-
151
- topic = klass.allocate
152
- assert !topic.respond_to?("nothingness")
153
- assert !topic.respond_to?(:nothingness)
154
- assert_respond_to topic, "title"
155
- assert_respond_to topic, :title
156
- end
157
-
158
- # IRB inspects the return value of "MyModel.allocate".
159
- def test_allocated_object_can_be_inspected
160
- topic = Topic.allocate
161
- assert_equal "#<Topic not initialized>", topic.inspect
162
- end
163
-
164
- def test_array_content
165
- topic = Topic.new
166
- topic.content = %w( one two three )
167
- topic.save
168
-
169
- assert_equal(%w( one two three ), Topic.find(topic.id).content)
170
- end
171
-
172
- def test_read_attributes_before_type_cast
173
- category = Category.new({:name=>"Test category", :type => nil})
174
- category_attrs = {"name"=>"Test category", "id" => nil, "type" => nil, "categorizations_count" => nil}
175
- assert_equal category_attrs , category.attributes_before_type_cast
176
- end
177
-
178
- if current_adapter?(:MysqlAdapter)
179
- def test_read_attributes_before_type_cast_on_boolean
180
- bool = Boolean.create({ "value" => false })
181
- if RUBY_PLATFORM =~ /java/
182
- # JRuby will return the value before typecast as string
183
- assert_equal "0", bool.reload.attributes_before_type_cast["value"]
184
- else
185
- assert_equal 0, bool.reload.attributes_before_type_cast["value"]
186
- end
187
- end
188
- end
189
-
190
- def test_read_attributes_before_type_cast_on_datetime
191
- in_time_zone "Pacific Time (US & Canada)" do
192
- record = @target.new
193
-
194
- record.written_on = "345643456"
195
- assert_equal "345643456", record.written_on_before_type_cast
196
- assert_equal nil, record.written_on
197
-
198
- record.written_on = "2009-10-11 12:13:14"
199
- assert_equal "2009-10-11 12:13:14", record.written_on_before_type_cast
200
- assert_equal Time.zone.parse("2009-10-11 12:13:14"), record.written_on
201
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
202
- end
203
- end
204
-
205
- def test_read_attributes_after_type_cast_on_datetime
206
- tz = "Pacific Time (US & Canada)"
207
-
208
- in_time_zone tz do
209
- record = @target.new
210
-
211
- date_string = "2011-03-24"
212
- time = Time.zone.parse date_string
213
-
214
- record.written_on = date_string
215
- assert_equal date_string, record.written_on_before_type_cast
216
- assert_equal time, record.written_on
217
- assert_equal ActiveSupport::TimeZone[tz], record.written_on.time_zone
218
-
219
- record.save
220
- record.reload
221
-
222
- assert_equal time, record.written_on
223
- end
224
- end
225
-
226
- def test_hash_content
227
- topic = Topic.new
228
- topic.content = { "one" => 1, "two" => 2 }
229
- topic.save
230
-
231
- assert_equal 2, Topic.find(topic.id).content["two"]
232
-
233
- topic.content_will_change!
234
- topic.content["three"] = 3
235
- topic.save
236
-
237
- assert_equal 3, Topic.find(topic.id).content["three"]
238
- end
239
-
240
- def test_update_array_content
241
- topic = Topic.new
242
- topic.content = %w( one two three )
243
-
244
- topic.content.push "four"
245
- assert_equal(%w( one two three four ), topic.content)
246
-
247
- topic.save
248
-
249
- topic = Topic.find(topic.id)
250
- topic.content << "five"
251
- assert_equal(%w( one two three four five ), topic.content)
252
- end
253
-
254
- def test_case_sensitive_attributes_hash
255
- # DB2 is not case-sensitive
256
- return true if current_adapter?(:DB2Adapter) || current_adapter?(:IBM_DBAdapter)
257
-
258
- assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes
259
- end
260
-
261
- def test_attributes_without_primary_key
262
- klass = Class.new(ActiveRecord::Base) do
263
- self.table_name = 'developers_projects'
264
- end
265
-
266
- assert_equal klass.column_names, klass.new.attributes.keys
267
- assert_not klass.new.has_attribute?('id')
268
- end
269
-
270
- def test_hashes_not_mangled
271
- new_topic = { :title => "New Topic" }
272
- new_topic_values = { :title => "AnotherTopic" }
273
-
274
- topic = Topic.new(new_topic)
275
- assert_equal new_topic[:title], topic.title
276
-
277
- topic.attributes= new_topic_values
278
- assert_equal new_topic_values[:title], topic.title
279
- end
280
-
281
- def test_create_through_factory
282
- topic = Topic.create("title" => "New Topic")
283
- topicReloaded = Topic.find(topic.id)
284
- assert_equal(topic, topicReloaded)
285
- end
286
-
287
- def test_write_attribute
288
- topic = Topic.new
289
- topic.send(:write_attribute, :title, "Still another topic")
290
- assert_equal "Still another topic", topic.title
291
-
292
- topic[:title] = "Still another topic: part 2"
293
- assert_equal "Still another topic: part 2", topic.title
294
-
295
- topic.send(:write_attribute, "title", "Still another topic: part 3")
296
- assert_equal "Still another topic: part 3", topic.title
297
-
298
- topic["title"] = "Still another topic: part 4"
299
- assert_equal "Still another topic: part 4", topic.title
300
- end
301
-
302
- def test_read_attribute
303
- topic = Topic.new
304
- topic.title = "Don't change the topic"
305
- assert_equal "Don't change the topic", topic.read_attribute("title")
306
- assert_equal "Don't change the topic", topic["title"]
307
-
308
- assert_equal "Don't change the topic", topic.read_attribute(:title)
309
- assert_equal "Don't change the topic", topic[:title]
310
- end
311
-
312
- def test_read_attribute_raises_missing_attribute_error_when_not_exists
313
- computer = Computer.select('id').first
314
- assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
315
- assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
316
- assert_raises(ActiveModel::MissingAttributeError) { computer[:no_column_exists] = 'Hello!' }
317
- assert_nothing_raised { computer[:developer] = 'Hello!' }
318
- end
319
-
320
- def test_read_attribute_when_false
321
- topic = topics(:first)
322
- topic.approved = false
323
- assert !topic.approved?, "approved should be false"
324
- topic.approved = "false"
325
- assert !topic.approved?, "approved should be false"
326
- end
327
-
328
- def test_read_attribute_when_true
329
- topic = topics(:first)
330
- topic.approved = true
331
- assert topic.approved?, "approved should be true"
332
- topic.approved = "true"
333
- assert topic.approved?, "approved should be true"
334
- end
335
-
336
- def test_read_write_boolean_attribute
337
- topic = Topic.new
338
- topic.approved = "false"
339
- assert !topic.approved?, "approved should be false"
340
-
341
- topic.approved = "false"
342
- assert !topic.approved?, "approved should be false"
343
-
344
- topic.approved = "true"
345
- assert topic.approved?, "approved should be true"
346
-
347
- topic.approved = "true"
348
- assert topic.approved?, "approved should be true"
349
- end
350
-
351
- def test_overridden_write_attribute
352
- topic = Topic.new
353
- def topic.write_attribute(attr_name, value)
354
- super(attr_name, value.downcase)
355
- end
356
-
357
- topic.send(:write_attribute, :title, "Yet another topic")
358
- assert_equal "yet another topic", topic.title
359
-
360
- topic[:title] = "Yet another topic: part 2"
361
- assert_equal "yet another topic: part 2", topic.title
362
-
363
- topic.send(:write_attribute, "title", "Yet another topic: part 3")
364
- assert_equal "yet another topic: part 3", topic.title
365
-
366
- topic["title"] = "Yet another topic: part 4"
367
- assert_equal "yet another topic: part 4", topic.title
368
- end
369
-
370
- def test_overridden_read_attribute
371
- topic = Topic.new
372
- topic.title = "Stop changing the topic"
373
- def topic.read_attribute(attr_name)
374
- super(attr_name).upcase
375
- end
376
-
377
- assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute("title")
378
- assert_equal "STOP CHANGING THE TOPIC", topic["title"]
379
-
380
- assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute(:title)
381
- assert_equal "STOP CHANGING THE TOPIC", topic[:title]
382
- end
383
-
384
- def test_read_overridden_attribute
385
- topic = Topic.new(:title => 'a')
386
- def topic.title() 'b' end
387
- assert_equal 'a', topic[:title]
388
- end
389
-
390
- def test_query_attribute_string
391
- [nil, "", " "].each do |value|
392
- assert_equal false, Topic.new(:author_name => value).author_name?
393
- end
394
-
395
- assert_equal true, Topic.new(:author_name => "Name").author_name?
396
- end
397
-
398
- def test_query_attribute_number
399
- [nil, 0, "0"].each do |value|
400
- assert_equal false, Developer.new(:salary => value).salary?
401
- end
402
-
403
- assert_equal true, Developer.new(:salary => 1).salary?
404
- assert_equal true, Developer.new(:salary => "1").salary?
405
- end
406
-
407
- def test_query_attribute_boolean
408
- [nil, "", false, "false", "f", 0].each do |value|
409
- assert_equal false, Topic.new(:approved => value).approved?
410
- end
411
-
412
- [true, "true", "1", 1].each do |value|
413
- assert_equal true, Topic.new(:approved => value).approved?
414
- end
415
- end
416
-
417
- def test_query_attribute_with_custom_fields
418
- object = Company.find_by_sql(<<-SQL).first
419
- SELECT c1.*, c2.type as string_value, c2.rating as int_value
420
- FROM companies c1, companies c2
421
- WHERE c1.firm_id = c2.id
422
- AND c1.id = 2
423
- SQL
424
-
425
- assert_equal "Firm", object.string_value
426
- assert object.string_value?
427
-
428
- object.string_value = " "
429
- assert !object.string_value?
430
-
431
- assert_equal 1, object.int_value.to_i
432
- assert object.int_value?
433
-
434
- object.int_value = "0"
435
- assert !object.int_value?
436
- end
437
-
438
- def test_non_attribute_access_and_assignment
439
- topic = Topic.new
440
- assert !topic.respond_to?("mumbo")
441
- assert_raise(NoMethodError) { topic.mumbo }
442
- assert_raise(NoMethodError) { topic.mumbo = 5 }
443
- end
444
-
445
- def test_undeclared_attribute_method_does_not_affect_respond_to_and_method_missing
446
- topic = @target.new(:title => 'Budget')
447
- assert topic.respond_to?('title')
448
- assert_equal 'Budget', topic.title
449
- assert !topic.respond_to?('title_hello_world')
450
- assert_raise(NoMethodError) { topic.title_hello_world }
451
- end
452
-
453
- def test_declared_prefixed_attribute_method_affects_respond_to_and_method_missing
454
- topic = @target.new(:title => 'Budget')
455
- %w(default_ title_).each do |prefix|
456
- @target.class_eval "def #{prefix}attribute(*args) args end"
457
- @target.attribute_method_prefix prefix
458
-
459
- meth = "#{prefix}title"
460
- assert topic.respond_to?(meth)
461
- assert_equal ['title'], topic.send(meth)
462
- assert_equal ['title', 'a'], topic.send(meth, 'a')
463
- assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
464
- end
465
- end
466
-
467
- def test_declared_suffixed_attribute_method_affects_respond_to_and_method_missing
468
- %w(_default _title_default _it! _candidate= able?).each do |suffix|
469
- @target.class_eval "def attribute#{suffix}(*args) args end"
470
- @target.attribute_method_suffix suffix
471
- topic = @target.new(:title => 'Budget')
472
-
473
- meth = "title#{suffix}"
474
- assert topic.respond_to?(meth)
475
- assert_equal ['title'], topic.send(meth)
476
- assert_equal ['title', 'a'], topic.send(meth, 'a')
477
- assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
478
- end
479
- end
480
-
481
- def test_declared_affixed_attribute_method_affects_respond_to_and_method_missing
482
- [['mark_', '_for_update'], ['reset_', '!'], ['default_', '_value?']].each do |prefix, suffix|
483
- @target.class_eval "def #{prefix}attribute#{suffix}(*args) args end"
484
- @target.attribute_method_affix({ :prefix => prefix, :suffix => suffix })
485
- topic = @target.new(:title => 'Budget')
486
-
487
- meth = "#{prefix}title#{suffix}"
488
- assert topic.respond_to?(meth)
489
- assert_equal ['title'], topic.send(meth)
490
- assert_equal ['title', 'a'], topic.send(meth, 'a')
491
- assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
492
- end
493
- end
494
-
495
- def test_should_unserialize_attributes_for_frozen_records
496
- myobj = {:value1 => :value2}
497
- topic = Topic.create("content" => myobj)
498
- topic.freeze
499
- assert_equal myobj, topic.content
500
- end
501
-
502
- def test_typecast_attribute_from_select_to_false
503
- Topic.create(:title => 'Budget')
504
- # Oracle does not support boolean expressions in SELECT
505
- if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
506
- topic = Topic.all.merge!(:select => "topics.*, 0 as is_test").first
507
- else
508
- topic = Topic.all.merge!(:select => "topics.*, 1=2 as is_test").first
509
- end
510
- assert !topic.is_test?
511
- end
512
-
513
- def test_typecast_attribute_from_select_to_true
514
- Topic.create(:title => 'Budget')
515
- # Oracle does not support boolean expressions in SELECT
516
- if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
517
- topic = Topic.all.merge!(:select => "topics.*, 1 as is_test").first
518
- else
519
- topic = Topic.all.merge!(:select => "topics.*, 2=2 as is_test").first
520
- end
521
- assert topic.is_test?
522
- end
523
-
524
- def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
525
- %w(save create_or_update).each do |method|
526
- klass = Class.new ActiveRecord::Base
527
- klass.class_eval "def #{method}() 'defined #{method}' end"
528
- assert_raise ActiveRecord::DangerousAttributeError do
529
- klass.instance_method_already_implemented?(method)
530
- end
531
- end
532
- end
533
-
534
- def test_deprecated_cache_attributes
535
- assert_deprecated do
536
- Topic.cache_attributes :replies_count
537
- end
538
-
539
- assert_deprecated do
540
- Topic.cached_attributes
541
- end
542
-
543
- assert_deprecated do
544
- Topic.cache_attribute? :replies_count
545
- end
546
- end
547
-
548
- def test_converted_values_are_returned_after_assignment
549
- developer = Developer.new(name: 1337, salary: "50000")
550
-
551
- assert_equal "50000", developer.salary_before_type_cast
552
- assert_equal 1337, developer.name_before_type_cast
553
-
554
- assert_equal 50000, developer.salary
555
- assert_equal "1337", developer.name
556
-
557
- developer.save!
558
-
559
- assert_equal "50000", developer.salary_before_type_cast
560
- assert_equal 1337, developer.name_before_type_cast
561
-
562
- assert_equal 50000, developer.salary
563
- assert_equal "1337", developer.name
564
- end
565
-
566
- def test_write_nil_to_time_attributes
567
- in_time_zone "Pacific Time (US & Canada)" do
568
- record = @target.new
569
- record.written_on = nil
570
- assert_nil record.written_on
571
- end
572
- end
573
-
574
- def test_write_time_to_date_attributes
575
- in_time_zone "Pacific Time (US & Canada)" do
576
- record = @target.new
577
- record.last_read = Time.utc(2010, 1, 1, 10)
578
- assert_equal Date.civil(2010, 1, 1), record.last_read
579
- end
580
- end
581
-
582
- def test_time_attributes_are_retrieved_in_current_time_zone
583
- in_time_zone "Pacific Time (US & Canada)" do
584
- utc_time = Time.utc(2008, 1, 1)
585
- record = @target.new
586
- record[:written_on] = utc_time
587
- assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
588
- assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
589
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
590
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
591
- end
592
- end
593
-
594
- def test_setting_time_zone_aware_attribute_to_utc
595
- in_time_zone "Pacific Time (US & Canada)" do
596
- utc_time = Time.utc(2008, 1, 1)
597
- record = @target.new
598
- record.written_on = utc_time
599
- assert_equal utc_time, record.written_on
600
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
601
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
602
- end
603
- end
604
-
605
- def test_setting_time_zone_aware_attribute_in_other_time_zone
606
- utc_time = Time.utc(2008, 1, 1)
607
- cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
608
- in_time_zone "Pacific Time (US & Canada)" do
609
- record = @target.new
610
- record.written_on = cst_time
611
- assert_equal utc_time, record.written_on
612
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
613
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
614
- end
615
- end
616
-
617
- def test_setting_time_zone_aware_read_attribute
618
- utc_time = Time.utc(2008, 1, 1)
619
- cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
620
- in_time_zone "Pacific Time (US & Canada)" do
621
- record = @target.create(:written_on => cst_time).reload
622
- assert_equal utc_time, record[:written_on]
623
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record[:written_on].time_zone
624
- assert_equal Time.utc(2007, 12, 31, 16), record[:written_on].time
625
- end
626
- end
627
-
628
- def test_setting_time_zone_aware_attribute_with_string
629
- utc_time = Time.utc(2008, 1, 1)
630
- (-11..13).each do |timezone_offset|
631
- time_string = utc_time.in_time_zone(timezone_offset).to_s
632
- in_time_zone "Pacific Time (US & Canada)" do
633
- record = @target.new
634
- record.written_on = time_string
635
- assert_equal Time.zone.parse(time_string), record.written_on
636
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
637
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
638
- end
639
- end
640
- end
641
-
642
- def test_time_zone_aware_attribute_saved
643
- in_time_zone 1 do
644
- record = @target.create(:written_on => '2012-02-20 10:00')
645
-
646
- record.written_on = '2012-02-20 09:00'
647
- record.save
648
- assert_equal Time.zone.local(2012, 02, 20, 9), record.reload.written_on
649
- end
650
- end
651
-
652
- def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
653
- in_time_zone "Pacific Time (US & Canada)" do
654
- record = @target.new
655
- record.written_on = ' '
656
- assert_nil record.written_on
657
- assert_nil record[:written_on]
658
- end
659
- end
660
-
661
- def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
662
- time_string = 'Tue Jan 01 00:00:00 2008'
663
- (-11..13).each do |timezone_offset|
664
- in_time_zone timezone_offset do
665
- record = @target.new
666
- record.written_on = time_string
667
- assert_equal Time.zone.parse(time_string), record.written_on
668
- assert_equal ActiveSupport::TimeZone[timezone_offset], record.written_on.time_zone
669
- assert_equal Time.utc(2008, 1, 1), record.written_on.time
670
- end
671
- end
672
- end
673
-
674
- def test_setting_time_zone_aware_attribute_in_current_time_zone
675
- utc_time = Time.utc(2008, 1, 1)
676
- in_time_zone "Pacific Time (US & Canada)" do
677
- record = @target.new
678
- record.written_on = utc_time.in_time_zone
679
- assert_equal utc_time, record.written_on
680
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
681
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
682
- end
683
- end
684
-
685
- def test_yaml_dumping_record_with_time_zone_aware_attribute
686
- in_time_zone "Pacific Time (US & Canada)" do
687
- record = Topic.new(id: 1)
688
- record.written_on = "Jan 01 00:00:00 2014"
689
- assert_equal record, YAML.load(YAML.dump(record))
690
- end
691
- end
692
-
693
- def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
694
- Topic.skip_time_zone_conversion_for_attributes = [:field_a]
695
- Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
696
-
697
- assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
698
- assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
699
- end
700
-
701
- def test_read_attributes_respect_access_control
702
- privatize("title")
703
-
704
- topic = @target.new(:title => "The pros and cons of programming naked.")
705
- assert !topic.respond_to?(:title)
706
- exception = assert_raise(NoMethodError) { topic.title }
707
- assert exception.message.include?("private method")
708
- assert_equal "I'm private", topic.send(:title)
709
- end
710
-
711
- def test_write_attributes_respect_access_control
712
- privatize("title=(value)")
713
-
714
- topic = @target.new
715
- assert !topic.respond_to?(:title=)
716
- exception = assert_raise(NoMethodError) { topic.title = "Pants"}
717
- assert exception.message.include?("private method")
718
- topic.send(:title=, "Very large pants")
719
- end
720
-
721
- def test_question_attributes_respect_access_control
722
- privatize("title?")
723
-
724
- topic = @target.new(:title => "Isaac Newton's pants")
725
- assert !topic.respond_to?(:title?)
726
- exception = assert_raise(NoMethodError) { topic.title? }
727
- assert exception.message.include?("private method")
728
- assert topic.send(:title?)
729
- end
730
-
731
- def test_bulk_update_respects_access_control
732
- privatize("title=(value)")
733
-
734
- assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
735
- assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
736
- end
737
-
738
- def test_bulk_update_raise_unknown_attribute_error
739
- error = assert_raises(ActiveRecord::UnknownAttributeError) {
740
- Topic.new(hello: "world")
741
- }
742
- assert_instance_of Topic, error.record
743
- assert_equal "hello", error.attribute
744
- assert_equal "unknown attribute 'hello' for Topic.", error.message
745
- end
746
-
747
- # This test is related to a bug in Ruby 2.2.1.
748
- # It can be safely removed once that bug is fixed.
749
- #
750
- # xref: https://bugs.ruby-lang.org/issues/10969
751
- def test_bulk_does_not_raise_name_error
752
- nope rescue nil # necessary to trigger the bug
753
- assert_raises(ActiveRecord::UnknownAttributeError) {
754
- Topic.new(hello: "world")
755
- }
756
- end
757
-
758
- def test_methods_override_in_multi_level_subclass
759
- klass = Class.new(Developer) do
760
- def name
761
- "dev:#{read_attribute(:name)}"
762
- end
763
- end
764
-
765
- 2.times { klass = Class.new klass }
766
- dev = klass.new(name: 'arthurnn')
767
- dev.save!
768
- assert_equal 'dev:arthurnn', dev.reload.name
769
- end
770
-
771
- def test_global_methods_are_overwritten
772
- klass = Class.new(ActiveRecord::Base) do
773
- self.table_name = 'computers'
774
- end
775
-
776
- assert !klass.instance_method_already_implemented?(:system)
777
- computer = klass.new
778
- assert_nil computer.system
779
- end
780
-
781
- def test_global_methods_are_overwritte_when_subclassing
782
- klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
783
-
784
- subklass = Class.new(klass) do
785
- self.table_name = 'computers'
786
- end
787
-
788
- assert !klass.instance_method_already_implemented?(:system)
789
- assert !subklass.instance_method_already_implemented?(:system)
790
- computer = subklass.new
791
- assert_nil computer.system
792
- end
793
-
794
- def test_instance_method_should_be_defined_on_the_base_class
795
- subklass = Class.new(Topic)
796
-
797
- Topic.define_attribute_methods
798
-
799
- instance = subklass.new
800
- instance.id = 5
801
- assert_equal 5, instance.id
802
- assert subklass.method_defined?(:id), "subklass is missing id method"
803
-
804
- Topic.undefine_attribute_methods
805
-
806
- assert_equal 5, instance.id
807
- assert subklass.method_defined?(:id), "subklass is missing id method"
808
- end
809
-
810
- def test_read_attribute_with_nil_should_not_asplode
811
- assert_equal nil, Topic.new.read_attribute(nil)
812
- end
813
-
814
- # If B < A, and A defines an accessor for 'foo', we don't want to override
815
- # that by defining a 'foo' method in the generated methods module for B.
816
- # (That module will be inserted between the two, e.g. [B, <GeneratedAttributes>, A].)
817
- def test_inherited_custom_accessors
818
- klass = new_topic_like_ar_class do
819
- self.abstract_class = true
820
- def title; "omg"; end
821
- def title=(val); self.author_name = val; end
822
- end
823
- subklass = Class.new(klass)
824
- [klass, subklass].each(&:define_attribute_methods)
825
-
826
- topic = subklass.find(1)
827
- assert_equal "omg", topic.title
828
-
829
- topic.title = "lol"
830
- assert_equal "lol", topic.author_name
831
- end
832
-
833
- def test_inherited_custom_accessors_with_reserved_names
834
- klass = Class.new(ActiveRecord::Base) do
835
- self.table_name = 'computers'
836
- self.abstract_class = true
837
- def system; "omg"; end
838
- def system=(val); self.developer = val; end
839
- end
840
-
841
- subklass = Class.new(klass)
842
- [klass, subklass].each(&:define_attribute_methods)
843
-
844
- computer = subklass.find(1)
845
- assert_equal "omg", computer.system
846
-
847
- computer.developer = 99
848
- assert_equal 99, computer.developer
849
- end
850
-
851
- def test_on_the_fly_super_invokable_generated_attribute_methods_via_method_missing
852
- klass = new_topic_like_ar_class do
853
- def title
854
- super + '!'
855
- end
856
- end
857
-
858
- real_topic = topics(:first)
859
- assert_equal real_topic.title + '!', klass.find(real_topic.id).title
860
- end
861
-
862
- def test_on_the_fly_super_invokable_generated_predicate_attribute_methods_via_method_missing
863
- klass = new_topic_like_ar_class do
864
- def title?
865
- !super
866
- end
867
- end
868
-
869
- real_topic = topics(:first)
870
- assert_equal !real_topic.title?, klass.find(real_topic.id).title?
871
- end
872
-
873
- def test_calling_super_when_parent_does_not_define_method_raises_error
874
- klass = new_topic_like_ar_class do
875
- def some_method_that_is_not_on_super
876
- super
877
- end
878
- end
879
-
880
- assert_raise(NoMethodError) do
881
- klass.new.some_method_that_is_not_on_super
882
- end
883
- end
884
-
885
- def test_attribute_method?
886
- assert @target.attribute_method?(:title)
887
- assert @target.attribute_method?(:title=)
888
- assert_not @target.attribute_method?(:wibble)
889
- end
890
-
891
- def test_attribute_method_returns_false_if_table_does_not_exist
892
- @target.table_name = 'wibble'
893
- assert_not @target.attribute_method?(:title)
894
- end
895
-
896
- def test_attribute_names_on_new_record
897
- model = @target.new
898
-
899
- assert_equal @target.column_names, model.attribute_names
900
- end
901
-
902
- def test_attribute_names_on_queried_record
903
- model = @target.last!
904
-
905
- assert_equal @target.column_names, model.attribute_names
906
- end
907
-
908
- def test_attribute_names_with_custom_select
909
- model = @target.select('id').last!
910
-
911
- assert_equal ['id'], model.attribute_names
912
- # Sanity check, make sure other columns exist
913
- assert_not_equal ['id'], @target.column_names
914
- end
915
-
916
- def test_came_from_user
917
- model = @target.first
918
-
919
- assert_not model.id_came_from_user?
920
- model.id = "omg"
921
- assert model.id_came_from_user?
922
- end
923
-
924
- private
925
-
926
- def new_topic_like_ar_class(&block)
927
- klass = Class.new(ActiveRecord::Base) do
928
- self.table_name = 'topics'
929
- class_eval(&block)
930
- end
931
-
932
- assert_empty klass.generated_attribute_methods.instance_methods(false)
933
- klass
934
- end
935
-
936
- def cached_columns
937
- Topic.columns.map(&:name)
938
- end
939
-
940
- def time_related_columns_on_topic
941
- Topic.columns.select { |c| [:time, :date, :datetime, :timestamp].include?(c.type) }
942
- end
943
-
944
- def privatize(method_signature)
945
- @target.class_eval(<<-private_method, __FILE__, __LINE__ + 1)
946
- private
947
- def #{method_signature}
948
- "I'm private"
949
- end
950
- private_method
951
- end
952
- end
1
+ require "cases/helper"
2
+ require 'models/minimalistic'
3
+ require 'models/developer'
4
+ require 'models/computer'
5
+ require 'models/auto_id'
6
+ require 'models/boolean'
7
+ require 'models/computer'
8
+ require 'models/topic'
9
+ require 'models/company'
10
+ require 'models/category'
11
+ require 'models/reply'
12
+ require 'models/contact'
13
+ require 'models/keyboard'
14
+
15
+ class AttributeMethodsTest < ActiveRecord::TestCase
16
+ include InTimeZone
17
+
18
+ fixtures :topics, :developers, :companies, :computers
19
+
20
+ def setup
21
+ @old_matchers = ActiveRecord::Base.send(:attribute_method_matchers).dup
22
+ @target = Class.new(ActiveRecord::Base)
23
+ @target.table_name = 'topics'
24
+ end
25
+
26
+ teardown do
27
+ ActiveRecord::Base.send(:attribute_method_matchers).clear
28
+ ActiveRecord::Base.send(:attribute_method_matchers).concat(@old_matchers)
29
+ end
30
+
31
+ def test_attribute_for_inspect
32
+ t = topics(:first)
33
+ t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
34
+
35
+ assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
36
+ assert_equal '"The First Topic Now Has A Title With\nNewlines And ..."', t.attribute_for_inspect(:title)
37
+ end
38
+
39
+ def test_attribute_present
40
+ t = Topic.new
41
+ t.title = "hello there!"
42
+ t.written_on = Time.now
43
+ t.author_name = ""
44
+ assert t.attribute_present?("title")
45
+ assert t.attribute_present?("written_on")
46
+ assert !t.attribute_present?("content")
47
+ assert !t.attribute_present?("author_name")
48
+ end
49
+
50
+ def test_attribute_present_with_booleans
51
+ b1 = Boolean.new
52
+ b1.value = false
53
+ assert b1.attribute_present?(:value)
54
+
55
+ b2 = Boolean.new
56
+ b2.value = true
57
+ assert b2.attribute_present?(:value)
58
+
59
+ b3 = Boolean.new
60
+ assert !b3.attribute_present?(:value)
61
+
62
+ b4 = Boolean.new
63
+ b4.value = false
64
+ b4.save!
65
+ assert Boolean.find(b4.id).attribute_present?(:value)
66
+ end
67
+
68
+ def test_caching_nil_primary_key
69
+ klass = Class.new(Minimalistic)
70
+ klass.expects(:reset_primary_key).returns(nil).once
71
+ 2.times { klass.primary_key }
72
+ end
73
+
74
+ def test_attribute_keys_on_new_instance
75
+ t = Topic.new
76
+ assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
77
+ assert_raise(NoMethodError) { t.title2 }
78
+ end
79
+
80
+ def test_boolean_attributes
81
+ assert !Topic.find(1).approved?
82
+ assert Topic.find(2).approved?
83
+ end
84
+
85
+ def test_set_attributes
86
+ topic = Topic.find(1)
87
+ topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
88
+ topic.save
89
+ assert_equal("Budget", topic.title)
90
+ assert_equal("Jason", topic.author_name)
91
+ assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
92
+ end
93
+
94
+ def test_set_attributes_without_hash
95
+ topic = Topic.new
96
+ assert_raise(ArgumentError) { topic.attributes = '' }
97
+ end
98
+
99
+ def test_integers_as_nil
100
+ test = AutoId.create('value' => '')
101
+ assert_nil AutoId.find(test.id).value
102
+ end
103
+
104
+ def test_set_attributes_with_block
105
+ topic = Topic.new do |t|
106
+ t.title = "Budget"
107
+ t.author_name = "Jason"
108
+ end
109
+
110
+ assert_equal("Budget", topic.title)
111
+ assert_equal("Jason", topic.author_name)
112
+ end
113
+
114
+ def test_respond_to?
115
+ topic = Topic.find(1)
116
+ assert_respond_to topic, "title"
117
+ assert_respond_to topic, "title?"
118
+ assert_respond_to topic, "title="
119
+ assert_respond_to topic, :title
120
+ assert_respond_to topic, :title?
121
+ assert_respond_to topic, :title=
122
+ assert_respond_to topic, "author_name"
123
+ assert_respond_to topic, "attribute_names"
124
+ assert !topic.respond_to?("nothingness")
125
+ assert !topic.respond_to?(:nothingness)
126
+ end
127
+
128
+ def test_respond_to_with_custom_primary_key
129
+ keyboard = Keyboard.create
130
+ assert_not_nil keyboard.key_number
131
+ assert_equal keyboard.key_number, keyboard.id
132
+ assert keyboard.respond_to?('key_number')
133
+ assert keyboard.respond_to?('id')
134
+ end
135
+
136
+ def test_id_before_type_cast_with_custom_primary_key
137
+ keyboard = Keyboard.create
138
+ keyboard.key_number = '10'
139
+ assert_equal '10', keyboard.id_before_type_cast
140
+ assert_equal nil, keyboard.read_attribute_before_type_cast('id')
141
+ assert_equal '10', keyboard.read_attribute_before_type_cast('key_number')
142
+ assert_equal '10', keyboard.read_attribute_before_type_cast(:key_number)
143
+ end
144
+
145
+ # Syck calls respond_to? before actually calling initialize
146
+ def test_respond_to_with_allocated_object
147
+ klass = Class.new(ActiveRecord::Base) do
148
+ self.table_name = 'topics'
149
+ end
150
+
151
+ topic = klass.allocate
152
+ assert !topic.respond_to?("nothingness")
153
+ assert !topic.respond_to?(:nothingness)
154
+ assert_respond_to topic, "title"
155
+ assert_respond_to topic, :title
156
+ end
157
+
158
+ # IRB inspects the return value of "MyModel.allocate".
159
+ def test_allocated_object_can_be_inspected
160
+ topic = Topic.allocate
161
+ assert_equal "#<Topic not initialized>", topic.inspect
162
+ end
163
+
164
+ def test_array_content
165
+ topic = Topic.new
166
+ topic.content = %w( one two three )
167
+ topic.save
168
+
169
+ assert_equal(%w( one two three ), Topic.find(topic.id).content)
170
+ end
171
+
172
+ def test_read_attributes_before_type_cast
173
+ category = Category.new({:name=>"Test category", :type => nil})
174
+ category_attrs = {"name"=>"Test category", "id" => nil, "type" => nil, "categorizations_count" => nil}
175
+ assert_equal category_attrs , category.attributes_before_type_cast
176
+ end
177
+
178
+ if current_adapter?(:MysqlAdapter)
179
+ def test_read_attributes_before_type_cast_on_boolean
180
+ bool = Boolean.create({ "value" => false })
181
+ if RUBY_PLATFORM =~ /java/
182
+ # JRuby will return the value before typecast as string
183
+ assert_equal "0", bool.reload.attributes_before_type_cast["value"]
184
+ else
185
+ assert_equal 0, bool.reload.attributes_before_type_cast["value"]
186
+ end
187
+ end
188
+ end
189
+
190
+ def test_read_attributes_before_type_cast_on_datetime
191
+ in_time_zone "Pacific Time (US & Canada)" do
192
+ record = @target.new
193
+
194
+ record.written_on = "345643456"
195
+ assert_equal "345643456", record.written_on_before_type_cast
196
+ assert_equal nil, record.written_on
197
+
198
+ record.written_on = "2009-10-11 12:13:14"
199
+ assert_equal "2009-10-11 12:13:14", record.written_on_before_type_cast
200
+ assert_equal Time.zone.parse("2009-10-11 12:13:14"), record.written_on
201
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
202
+ end
203
+ end
204
+
205
+ def test_read_attributes_after_type_cast_on_datetime
206
+ tz = "Pacific Time (US & Canada)"
207
+
208
+ in_time_zone tz do
209
+ record = @target.new
210
+
211
+ date_string = "2011-03-24"
212
+ time = Time.zone.parse date_string
213
+
214
+ record.written_on = date_string
215
+ assert_equal date_string, record.written_on_before_type_cast
216
+ assert_equal time, record.written_on
217
+ assert_equal ActiveSupport::TimeZone[tz], record.written_on.time_zone
218
+
219
+ record.save
220
+ record.reload
221
+
222
+ assert_equal time, record.written_on
223
+ end
224
+ end
225
+
226
+ def test_hash_content
227
+ topic = Topic.new
228
+ topic.content = { "one" => 1, "two" => 2 }
229
+ topic.save
230
+
231
+ assert_equal 2, Topic.find(topic.id).content["two"]
232
+
233
+ topic.content_will_change!
234
+ topic.content["three"] = 3
235
+ topic.save
236
+
237
+ assert_equal 3, Topic.find(topic.id).content["three"]
238
+ end
239
+
240
+ def test_update_array_content
241
+ topic = Topic.new
242
+ topic.content = %w( one two three )
243
+
244
+ topic.content.push "four"
245
+ assert_equal(%w( one two three four ), topic.content)
246
+
247
+ topic.save
248
+
249
+ topic = Topic.find(topic.id)
250
+ topic.content << "five"
251
+ assert_equal(%w( one two three four five ), topic.content)
252
+ end
253
+
254
+ def test_case_sensitive_attributes_hash
255
+ # DB2 is not case-sensitive
256
+ return true if current_adapter?(:DB2Adapter) || current_adapter?(:IBM_DBAdapter)
257
+
258
+ assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes
259
+ end
260
+
261
+ def test_attributes_without_primary_key
262
+ klass = Class.new(ActiveRecord::Base) do
263
+ self.table_name = 'developers_projects'
264
+ end
265
+
266
+ assert_equal klass.column_names, klass.new.attributes.keys
267
+ assert_not klass.new.has_attribute?('id')
268
+ end
269
+
270
+ def test_hashes_not_mangled
271
+ new_topic = { :title => "New Topic" }
272
+ new_topic_values = { :title => "AnotherTopic" }
273
+
274
+ topic = Topic.new(new_topic)
275
+ assert_equal new_topic[:title], topic.title
276
+
277
+ topic.attributes= new_topic_values
278
+ assert_equal new_topic_values[:title], topic.title
279
+ end
280
+
281
+ def test_create_through_factory
282
+ topic = Topic.create("title" => "New Topic")
283
+ topicReloaded = Topic.find(topic.id)
284
+ assert_equal(topic, topicReloaded)
285
+ end
286
+
287
+ def test_write_attribute
288
+ topic = Topic.new
289
+ topic.send(:write_attribute, :title, "Still another topic")
290
+ assert_equal "Still another topic", topic.title
291
+
292
+ topic[:title] = "Still another topic: part 2"
293
+ assert_equal "Still another topic: part 2", topic.title
294
+
295
+ topic.send(:write_attribute, "title", "Still another topic: part 3")
296
+ assert_equal "Still another topic: part 3", topic.title
297
+
298
+ topic["title"] = "Still another topic: part 4"
299
+ assert_equal "Still another topic: part 4", topic.title
300
+ end
301
+
302
+ def test_read_attribute
303
+ topic = Topic.new
304
+ topic.title = "Don't change the topic"
305
+ assert_equal "Don't change the topic", topic.read_attribute("title")
306
+ assert_equal "Don't change the topic", topic["title"]
307
+
308
+ assert_equal "Don't change the topic", topic.read_attribute(:title)
309
+ assert_equal "Don't change the topic", topic[:title]
310
+ end
311
+
312
+ def test_read_attribute_raises_missing_attribute_error_when_not_exists
313
+ computer = Computer.select('id').first
314
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
315
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
316
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:no_column_exists] = 'Hello!' }
317
+ assert_nothing_raised { computer[:developer] = 'Hello!' }
318
+ end
319
+
320
+ def test_read_attribute_when_false
321
+ topic = topics(:first)
322
+ topic.approved = false
323
+ assert !topic.approved?, "approved should be false"
324
+ topic.approved = "false"
325
+ assert !topic.approved?, "approved should be false"
326
+ end
327
+
328
+ def test_read_attribute_when_true
329
+ topic = topics(:first)
330
+ topic.approved = true
331
+ assert topic.approved?, "approved should be true"
332
+ topic.approved = "true"
333
+ assert topic.approved?, "approved should be true"
334
+ end
335
+
336
+ def test_read_write_boolean_attribute
337
+ topic = Topic.new
338
+ topic.approved = "false"
339
+ assert !topic.approved?, "approved should be false"
340
+
341
+ topic.approved = "false"
342
+ assert !topic.approved?, "approved should be false"
343
+
344
+ topic.approved = "true"
345
+ assert topic.approved?, "approved should be true"
346
+
347
+ topic.approved = "true"
348
+ assert topic.approved?, "approved should be true"
349
+ end
350
+
351
+ def test_overridden_write_attribute
352
+ topic = Topic.new
353
+ def topic.write_attribute(attr_name, value)
354
+ super(attr_name, value.downcase)
355
+ end
356
+
357
+ topic.send(:write_attribute, :title, "Yet another topic")
358
+ assert_equal "yet another topic", topic.title
359
+
360
+ topic[:title] = "Yet another topic: part 2"
361
+ assert_equal "yet another topic: part 2", topic.title
362
+
363
+ topic.send(:write_attribute, "title", "Yet another topic: part 3")
364
+ assert_equal "yet another topic: part 3", topic.title
365
+
366
+ topic["title"] = "Yet another topic: part 4"
367
+ assert_equal "yet another topic: part 4", topic.title
368
+ end
369
+
370
+ def test_overridden_read_attribute
371
+ topic = Topic.new
372
+ topic.title = "Stop changing the topic"
373
+ def topic.read_attribute(attr_name)
374
+ super(attr_name).upcase
375
+ end
376
+
377
+ assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute("title")
378
+ assert_equal "STOP CHANGING THE TOPIC", topic["title"]
379
+
380
+ assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute(:title)
381
+ assert_equal "STOP CHANGING THE TOPIC", topic[:title]
382
+ end
383
+
384
+ def test_read_overridden_attribute
385
+ topic = Topic.new(:title => 'a')
386
+ def topic.title() 'b' end
387
+ assert_equal 'a', topic[:title]
388
+ end
389
+
390
+ def test_query_attribute_string
391
+ [nil, "", " "].each do |value|
392
+ assert_equal false, Topic.new(:author_name => value).author_name?
393
+ end
394
+
395
+ assert_equal true, Topic.new(:author_name => "Name").author_name?
396
+ end
397
+
398
+ def test_query_attribute_number
399
+ [nil, 0, "0"].each do |value|
400
+ assert_equal false, Developer.new(:salary => value).salary?
401
+ end
402
+
403
+ assert_equal true, Developer.new(:salary => 1).salary?
404
+ assert_equal true, Developer.new(:salary => "1").salary?
405
+ end
406
+
407
+ def test_query_attribute_boolean
408
+ [nil, "", false, "false", "f", 0].each do |value|
409
+ assert_equal false, Topic.new(:approved => value).approved?
410
+ end
411
+
412
+ [true, "true", "1", 1].each do |value|
413
+ assert_equal true, Topic.new(:approved => value).approved?
414
+ end
415
+ end
416
+
417
+ def test_query_attribute_with_custom_fields
418
+ object = Company.find_by_sql(<<-SQL).first
419
+ SELECT c1.*, c2.type as string_value, c2.rating as int_value
420
+ FROM companies c1, companies c2
421
+ WHERE c1.firm_id = c2.id
422
+ AND c1.id = 2
423
+ SQL
424
+
425
+ assert_equal "Firm", object.string_value
426
+ assert object.string_value?
427
+
428
+ object.string_value = " "
429
+ assert !object.string_value?
430
+
431
+ assert_equal 1, object.int_value.to_i
432
+ assert object.int_value?
433
+
434
+ object.int_value = "0"
435
+ assert !object.int_value?
436
+ end
437
+
438
+ def test_non_attribute_access_and_assignment
439
+ topic = Topic.new
440
+ assert !topic.respond_to?("mumbo")
441
+ assert_raise(NoMethodError) { topic.mumbo }
442
+ assert_raise(NoMethodError) { topic.mumbo = 5 }
443
+ end
444
+
445
+ def test_undeclared_attribute_method_does_not_affect_respond_to_and_method_missing
446
+ topic = @target.new(:title => 'Budget')
447
+ assert topic.respond_to?('title')
448
+ assert_equal 'Budget', topic.title
449
+ assert !topic.respond_to?('title_hello_world')
450
+ assert_raise(NoMethodError) { topic.title_hello_world }
451
+ end
452
+
453
+ def test_declared_prefixed_attribute_method_affects_respond_to_and_method_missing
454
+ topic = @target.new(:title => 'Budget')
455
+ %w(default_ title_).each do |prefix|
456
+ @target.class_eval "def #{prefix}attribute(*args) args end"
457
+ @target.attribute_method_prefix prefix
458
+
459
+ meth = "#{prefix}title"
460
+ assert topic.respond_to?(meth)
461
+ assert_equal ['title'], topic.send(meth)
462
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
463
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
464
+ end
465
+ end
466
+
467
+ def test_declared_suffixed_attribute_method_affects_respond_to_and_method_missing
468
+ %w(_default _title_default _it! _candidate= able?).each do |suffix|
469
+ @target.class_eval "def attribute#{suffix}(*args) args end"
470
+ @target.attribute_method_suffix suffix
471
+ topic = @target.new(:title => 'Budget')
472
+
473
+ meth = "title#{suffix}"
474
+ assert topic.respond_to?(meth)
475
+ assert_equal ['title'], topic.send(meth)
476
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
477
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
478
+ end
479
+ end
480
+
481
+ def test_declared_affixed_attribute_method_affects_respond_to_and_method_missing
482
+ [['mark_', '_for_update'], ['reset_', '!'], ['default_', '_value?']].each do |prefix, suffix|
483
+ @target.class_eval "def #{prefix}attribute#{suffix}(*args) args end"
484
+ @target.attribute_method_affix({ :prefix => prefix, :suffix => suffix })
485
+ topic = @target.new(:title => 'Budget')
486
+
487
+ meth = "#{prefix}title#{suffix}"
488
+ assert topic.respond_to?(meth)
489
+ assert_equal ['title'], topic.send(meth)
490
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
491
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
492
+ end
493
+ end
494
+
495
+ def test_should_unserialize_attributes_for_frozen_records
496
+ myobj = {:value1 => :value2}
497
+ topic = Topic.create("content" => myobj)
498
+ topic.freeze
499
+ assert_equal myobj, topic.content
500
+ end
501
+
502
+ def test_typecast_attribute_from_select_to_false
503
+ Topic.create(:title => 'Budget')
504
+ # Oracle does not support boolean expressions in SELECT
505
+ if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
506
+ topic = Topic.all.merge!(:select => "topics.*, 0 as is_test").first
507
+ else
508
+ topic = Topic.all.merge!(:select => "topics.*, 1=2 as is_test").first
509
+ end
510
+ assert !topic.is_test?
511
+ end
512
+
513
+ def test_typecast_attribute_from_select_to_true
514
+ Topic.create(:title => 'Budget')
515
+ # Oracle does not support boolean expressions in SELECT
516
+ if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
517
+ topic = Topic.all.merge!(:select => "topics.*, 1 as is_test").first
518
+ else
519
+ topic = Topic.all.merge!(:select => "topics.*, 2=2 as is_test").first
520
+ end
521
+ assert topic.is_test?
522
+ end
523
+
524
+ def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
525
+ %w(save create_or_update).each do |method|
526
+ klass = Class.new ActiveRecord::Base
527
+ klass.class_eval "def #{method}() 'defined #{method}' end"
528
+ assert_raise ActiveRecord::DangerousAttributeError do
529
+ klass.instance_method_already_implemented?(method)
530
+ end
531
+ end
532
+ end
533
+
534
+ def test_deprecated_cache_attributes
535
+ assert_deprecated do
536
+ Topic.cache_attributes :replies_count
537
+ end
538
+
539
+ assert_deprecated do
540
+ Topic.cached_attributes
541
+ end
542
+
543
+ assert_deprecated do
544
+ Topic.cache_attribute? :replies_count
545
+ end
546
+ end
547
+
548
+ def test_converted_values_are_returned_after_assignment
549
+ developer = Developer.new(name: 1337, salary: "50000")
550
+
551
+ assert_equal "50000", developer.salary_before_type_cast
552
+ assert_equal 1337, developer.name_before_type_cast
553
+
554
+ assert_equal 50000, developer.salary
555
+ assert_equal "1337", developer.name
556
+
557
+ developer.save!
558
+
559
+ assert_equal "50000", developer.salary_before_type_cast
560
+ assert_equal 1337, developer.name_before_type_cast
561
+
562
+ assert_equal 50000, developer.salary
563
+ assert_equal "1337", developer.name
564
+ end
565
+
566
+ def test_write_nil_to_time_attributes
567
+ in_time_zone "Pacific Time (US & Canada)" do
568
+ record = @target.new
569
+ record.written_on = nil
570
+ assert_nil record.written_on
571
+ end
572
+ end
573
+
574
+ def test_write_time_to_date_attributes
575
+ in_time_zone "Pacific Time (US & Canada)" do
576
+ record = @target.new
577
+ record.last_read = Time.utc(2010, 1, 1, 10)
578
+ assert_equal Date.civil(2010, 1, 1), record.last_read
579
+ end
580
+ end
581
+
582
+ def test_time_attributes_are_retrieved_in_current_time_zone
583
+ in_time_zone "Pacific Time (US & Canada)" do
584
+ utc_time = Time.utc(2008, 1, 1)
585
+ record = @target.new
586
+ record[:written_on] = utc_time
587
+ assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
588
+ assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
589
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
590
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
591
+ end
592
+ end
593
+
594
+ def test_setting_time_zone_aware_attribute_to_utc
595
+ in_time_zone "Pacific Time (US & Canada)" do
596
+ utc_time = Time.utc(2008, 1, 1)
597
+ record = @target.new
598
+ record.written_on = utc_time
599
+ assert_equal utc_time, record.written_on
600
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
601
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
602
+ end
603
+ end
604
+
605
+ def test_setting_time_zone_aware_attribute_in_other_time_zone
606
+ utc_time = Time.utc(2008, 1, 1)
607
+ cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
608
+ in_time_zone "Pacific Time (US & Canada)" do
609
+ record = @target.new
610
+ record.written_on = cst_time
611
+ assert_equal utc_time, record.written_on
612
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
613
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
614
+ end
615
+ end
616
+
617
+ def test_setting_time_zone_aware_read_attribute
618
+ utc_time = Time.utc(2008, 1, 1)
619
+ cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
620
+ in_time_zone "Pacific Time (US & Canada)" do
621
+ record = @target.create(:written_on => cst_time).reload
622
+ assert_equal utc_time, record[:written_on]
623
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record[:written_on].time_zone
624
+ assert_equal Time.utc(2007, 12, 31, 16), record[:written_on].time
625
+ end
626
+ end
627
+
628
+ def test_setting_time_zone_aware_attribute_with_string
629
+ utc_time = Time.utc(2008, 1, 1)
630
+ (-11..13).each do |timezone_offset|
631
+ time_string = utc_time.in_time_zone(timezone_offset).to_s
632
+ in_time_zone "Pacific Time (US & Canada)" do
633
+ record = @target.new
634
+ record.written_on = time_string
635
+ assert_equal Time.zone.parse(time_string), record.written_on
636
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
637
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
638
+ end
639
+ end
640
+ end
641
+
642
+ def test_time_zone_aware_attribute_saved
643
+ in_time_zone 1 do
644
+ record = @target.create(:written_on => '2012-02-20 10:00')
645
+
646
+ record.written_on = '2012-02-20 09:00'
647
+ record.save
648
+ assert_equal Time.zone.local(2012, 02, 20, 9), record.reload.written_on
649
+ end
650
+ end
651
+
652
+ def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
653
+ in_time_zone "Pacific Time (US & Canada)" do
654
+ record = @target.new
655
+ record.written_on = ' '
656
+ assert_nil record.written_on
657
+ assert_nil record[:written_on]
658
+ end
659
+ end
660
+
661
+ def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
662
+ time_string = 'Tue Jan 01 00:00:00 2008'
663
+ (-11..13).each do |timezone_offset|
664
+ in_time_zone timezone_offset do
665
+ record = @target.new
666
+ record.written_on = time_string
667
+ assert_equal Time.zone.parse(time_string), record.written_on
668
+ assert_equal ActiveSupport::TimeZone[timezone_offset], record.written_on.time_zone
669
+ assert_equal Time.utc(2008, 1, 1), record.written_on.time
670
+ end
671
+ end
672
+ end
673
+
674
+ def test_setting_time_zone_aware_attribute_in_current_time_zone
675
+ utc_time = Time.utc(2008, 1, 1)
676
+ in_time_zone "Pacific Time (US & Canada)" do
677
+ record = @target.new
678
+ record.written_on = utc_time.in_time_zone
679
+ assert_equal utc_time, record.written_on
680
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
681
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
682
+ end
683
+ end
684
+
685
+ def test_yaml_dumping_record_with_time_zone_aware_attribute
686
+ in_time_zone "Pacific Time (US & Canada)" do
687
+ record = Topic.new(id: 1)
688
+ record.written_on = "Jan 01 00:00:00 2014"
689
+ assert_equal record, YAML.load(YAML.dump(record))
690
+ end
691
+ end
692
+
693
+ def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
694
+ Topic.skip_time_zone_conversion_for_attributes = [:field_a]
695
+ Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
696
+
697
+ assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
698
+ assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
699
+ end
700
+
701
+ def test_read_attributes_respect_access_control
702
+ privatize("title")
703
+
704
+ topic = @target.new(:title => "The pros and cons of programming naked.")
705
+ assert !topic.respond_to?(:title)
706
+ exception = assert_raise(NoMethodError) { topic.title }
707
+ assert exception.message.include?("private method")
708
+ assert_equal "I'm private", topic.send(:title)
709
+ end
710
+
711
+ def test_write_attributes_respect_access_control
712
+ privatize("title=(value)")
713
+
714
+ topic = @target.new
715
+ assert !topic.respond_to?(:title=)
716
+ exception = assert_raise(NoMethodError) { topic.title = "Pants"}
717
+ assert exception.message.include?("private method")
718
+ topic.send(:title=, "Very large pants")
719
+ end
720
+
721
+ def test_question_attributes_respect_access_control
722
+ privatize("title?")
723
+
724
+ topic = @target.new(:title => "Isaac Newton's pants")
725
+ assert !topic.respond_to?(:title?)
726
+ exception = assert_raise(NoMethodError) { topic.title? }
727
+ assert exception.message.include?("private method")
728
+ assert topic.send(:title?)
729
+ end
730
+
731
+ def test_bulk_update_respects_access_control
732
+ privatize("title=(value)")
733
+
734
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
735
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
736
+ end
737
+
738
+ def test_bulk_update_raise_unknown_attribute_error
739
+ error = assert_raises(ActiveRecord::UnknownAttributeError) {
740
+ Topic.new(hello: "world")
741
+ }
742
+ assert_instance_of Topic, error.record
743
+ assert_equal "hello", error.attribute
744
+ assert_equal "unknown attribute 'hello' for Topic.", error.message
745
+ end
746
+
747
+ # This test is related to a bug in Ruby 2.2.1.
748
+ # It can be safely removed once that bug is fixed.
749
+ #
750
+ # xref: https://bugs.ruby-lang.org/issues/10969
751
+ def test_bulk_does_not_raise_name_error
752
+ nope rescue nil # necessary to trigger the bug
753
+ assert_raises(ActiveRecord::UnknownAttributeError) {
754
+ Topic.new(hello: "world")
755
+ }
756
+ end
757
+
758
+ def test_methods_override_in_multi_level_subclass
759
+ klass = Class.new(Developer) do
760
+ def name
761
+ "dev:#{read_attribute(:name)}"
762
+ end
763
+ end
764
+
765
+ 2.times { klass = Class.new klass }
766
+ dev = klass.new(name: 'arthurnn')
767
+ dev.save!
768
+ assert_equal 'dev:arthurnn', dev.reload.name
769
+ end
770
+
771
+ def test_global_methods_are_overwritten
772
+ klass = Class.new(ActiveRecord::Base) do
773
+ self.table_name = 'computers'
774
+ end
775
+
776
+ assert !klass.instance_method_already_implemented?(:system)
777
+ computer = klass.new
778
+ assert_nil computer.system
779
+ end
780
+
781
+ def test_global_methods_are_overwritte_when_subclassing
782
+ klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
783
+
784
+ subklass = Class.new(klass) do
785
+ self.table_name = 'computers'
786
+ end
787
+
788
+ assert !klass.instance_method_already_implemented?(:system)
789
+ assert !subklass.instance_method_already_implemented?(:system)
790
+ computer = subklass.new
791
+ assert_nil computer.system
792
+ end
793
+
794
+ def test_instance_method_should_be_defined_on_the_base_class
795
+ subklass = Class.new(Topic)
796
+
797
+ Topic.define_attribute_methods
798
+
799
+ instance = subklass.new
800
+ instance.id = 5
801
+ assert_equal 5, instance.id
802
+ assert subklass.method_defined?(:id), "subklass is missing id method"
803
+
804
+ Topic.undefine_attribute_methods
805
+
806
+ assert_equal 5, instance.id
807
+ assert subklass.method_defined?(:id), "subklass is missing id method"
808
+ end
809
+
810
+ def test_read_attribute_with_nil_should_not_asplode
811
+ assert_equal nil, Topic.new.read_attribute(nil)
812
+ end
813
+
814
+ # If B < A, and A defines an accessor for 'foo', we don't want to override
815
+ # that by defining a 'foo' method in the generated methods module for B.
816
+ # (That module will be inserted between the two, e.g. [B, <GeneratedAttributes>, A].)
817
+ def test_inherited_custom_accessors
818
+ klass = new_topic_like_ar_class do
819
+ self.abstract_class = true
820
+ def title; "omg"; end
821
+ def title=(val); self.author_name = val; end
822
+ end
823
+ subklass = Class.new(klass)
824
+ [klass, subklass].each(&:define_attribute_methods)
825
+
826
+ topic = subklass.find(1)
827
+ assert_equal "omg", topic.title
828
+
829
+ topic.title = "lol"
830
+ assert_equal "lol", topic.author_name
831
+ end
832
+
833
+ def test_inherited_custom_accessors_with_reserved_names
834
+ klass = Class.new(ActiveRecord::Base) do
835
+ self.table_name = 'computers'
836
+ self.abstract_class = true
837
+ def system; "omg"; end
838
+ def system=(val); self.developer = val; end
839
+ end
840
+
841
+ subklass = Class.new(klass)
842
+ [klass, subklass].each(&:define_attribute_methods)
843
+
844
+ computer = subklass.find(1)
845
+ assert_equal "omg", computer.system
846
+
847
+ computer.developer = 99
848
+ assert_equal 99, computer.developer
849
+ end
850
+
851
+ def test_on_the_fly_super_invokable_generated_attribute_methods_via_method_missing
852
+ klass = new_topic_like_ar_class do
853
+ def title
854
+ super + '!'
855
+ end
856
+ end
857
+
858
+ real_topic = topics(:first)
859
+ assert_equal real_topic.title + '!', klass.find(real_topic.id).title
860
+ end
861
+
862
+ def test_on_the_fly_super_invokable_generated_predicate_attribute_methods_via_method_missing
863
+ klass = new_topic_like_ar_class do
864
+ def title?
865
+ !super
866
+ end
867
+ end
868
+
869
+ real_topic = topics(:first)
870
+ assert_equal !real_topic.title?, klass.find(real_topic.id).title?
871
+ end
872
+
873
+ def test_calling_super_when_parent_does_not_define_method_raises_error
874
+ klass = new_topic_like_ar_class do
875
+ def some_method_that_is_not_on_super
876
+ super
877
+ end
878
+ end
879
+
880
+ assert_raise(NoMethodError) do
881
+ klass.new.some_method_that_is_not_on_super
882
+ end
883
+ end
884
+
885
+ def test_attribute_method?
886
+ assert @target.attribute_method?(:title)
887
+ assert @target.attribute_method?(:title=)
888
+ assert_not @target.attribute_method?(:wibble)
889
+ end
890
+
891
+ def test_attribute_method_returns_false_if_table_does_not_exist
892
+ @target.table_name = 'wibble'
893
+ assert_not @target.attribute_method?(:title)
894
+ end
895
+
896
+ def test_attribute_names_on_new_record
897
+ model = @target.new
898
+
899
+ assert_equal @target.column_names, model.attribute_names
900
+ end
901
+
902
+ def test_attribute_names_on_queried_record
903
+ model = @target.last!
904
+
905
+ assert_equal @target.column_names, model.attribute_names
906
+ end
907
+
908
+ def test_attribute_names_with_custom_select
909
+ model = @target.select('id').last!
910
+
911
+ assert_equal ['id'], model.attribute_names
912
+ # Sanity check, make sure other columns exist
913
+ assert_not_equal ['id'], @target.column_names
914
+ end
915
+
916
+ def test_came_from_user
917
+ model = @target.first
918
+
919
+ assert_not model.id_came_from_user?
920
+ model.id = "omg"
921
+ assert model.id_came_from_user?
922
+ end
923
+
924
+ private
925
+
926
+ def new_topic_like_ar_class(&block)
927
+ klass = Class.new(ActiveRecord::Base) do
928
+ self.table_name = 'topics'
929
+ class_eval(&block)
930
+ end
931
+
932
+ assert_empty klass.generated_attribute_methods.instance_methods(false)
933
+ klass
934
+ end
935
+
936
+ def cached_columns
937
+ Topic.columns.map(&:name)
938
+ end
939
+
940
+ def time_related_columns_on_topic
941
+ Topic.columns.select { |c| [:time, :date, :datetime, :timestamp].include?(c.type) }
942
+ end
943
+
944
+ def privatize(method_signature)
945
+ @target.class_eval(<<-private_method, __FILE__, __LINE__ + 1)
946
+ private
947
+ def #{method_signature}
948
+ "I'm private"
949
+ end
950
+ private_method
951
+ end
952
+ end