ibm_db 4.0.0-x86-mingw32 → 5.0.2-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 (570) hide show
  1. checksums.yaml +5 -5
  2. data/MANIFEST +14 -14
  3. data/README +208 -208
  4. data/ext/Makefile +269 -0
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/extconf.rb +322 -291
  8. data/ext/gil_release_version +3 -0
  9. data/ext/ibm_db.c +11879 -11887
  10. data/ext/mkmf.log +110 -0
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.c +866 -866
  13. data/ext/ruby_ibm_db_cli.h +500 -500
  14. data/ext/unicode_support_version +3 -0
  15. data/init.rb +41 -41
  16. data/lib/IBM_DB.rb +27 -27
  17. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3533 -3452
  18. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -5
  19. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  20. data/lib/mswin32/ibm_db.rb +90 -90
  21. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  22. data/test/active_record/connection_adapters/fake_adapter.rb +49 -49
  23. data/test/assets/example.log +1 -1
  24. data/test/assets/test.txt +1 -1
  25. data/test/cases/adapter_test.rb +351 -351
  26. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -193
  27. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -50
  28. data/test/cases/adapters/mysql2/boolean_test.rb +100 -100
  29. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -63
  30. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -54
  31. data/test/cases/adapters/mysql2/connection_test.rb +210 -210
  32. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -45
  33. data/test/cases/adapters/mysql2/enum_test.rb +26 -26
  34. data/test/cases/adapters/mysql2/explain_test.rb +21 -21
  35. data/test/cases/adapters/mysql2/json_test.rb +195 -195
  36. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -83
  37. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -152
  38. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -59
  39. data/test/cases/adapters/mysql2/schema_test.rb +126 -126
  40. data/test/cases/adapters/mysql2/sp_test.rb +36 -36
  41. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -14
  42. data/test/cases/adapters/mysql2/table_options_test.rb +42 -42
  43. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -66
  44. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -98
  45. data/test/cases/adapters/postgresql/array_test.rb +339 -339
  46. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -82
  47. data/test/cases/adapters/postgresql/bytea_test.rb +134 -134
  48. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -26
  49. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -38
  50. data/test/cases/adapters/postgresql/cidr_test.rb +25 -25
  51. data/test/cases/adapters/postgresql/citext_test.rb +78 -78
  52. data/test/cases/adapters/postgresql/collation_test.rb +53 -53
  53. data/test/cases/adapters/postgresql/composite_test.rb +132 -132
  54. data/test/cases/adapters/postgresql/connection_test.rb +257 -257
  55. data/test/cases/adapters/postgresql/datatype_test.rb +92 -92
  56. data/test/cases/adapters/postgresql/domain_test.rb +47 -47
  57. data/test/cases/adapters/postgresql/enum_test.rb +91 -91
  58. data/test/cases/adapters/postgresql/explain_test.rb +20 -20
  59. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -63
  60. data/test/cases/adapters/postgresql/full_text_test.rb +44 -44
  61. data/test/cases/adapters/postgresql/geometric_test.rb +378 -378
  62. data/test/cases/adapters/postgresql/hstore_test.rb +382 -382
  63. data/test/cases/adapters/postgresql/infinity_test.rb +69 -69
  64. data/test/cases/adapters/postgresql/integer_test.rb +25 -25
  65. data/test/cases/adapters/postgresql/json_test.rb +237 -237
  66. data/test/cases/adapters/postgresql/ltree_test.rb +53 -53
  67. data/test/cases/adapters/postgresql/money_test.rb +96 -96
  68. data/test/cases/adapters/postgresql/network_test.rb +94 -94
  69. data/test/cases/adapters/postgresql/numbers_test.rb +49 -49
  70. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -405
  71. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -22
  72. data/test/cases/adapters/postgresql/quoting_test.rb +44 -44
  73. data/test/cases/adapters/postgresql/range_test.rb +343 -343
  74. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -111
  75. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -34
  76. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -119
  77. data/test/cases/adapters/postgresql/schema_test.rb +597 -597
  78. data/test/cases/adapters/postgresql/serial_test.rb +154 -154
  79. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -41
  80. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -90
  81. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -33
  82. data/test/cases/adapters/postgresql/utils_test.rb +62 -62
  83. data/test/cases/adapters/postgresql/uuid_test.rb +294 -294
  84. data/test/cases/adapters/postgresql/xml_test.rb +54 -54
  85. data/test/cases/adapters/sqlite3/collation_test.rb +53 -53
  86. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -98
  87. data/test/cases/adapters/sqlite3/explain_test.rb +21 -21
  88. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -101
  89. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -441
  90. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -24
  91. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -20
  92. data/test/cases/aggregations_test.rb +168 -168
  93. data/test/cases/ar_schema_test.rb +146 -146
  94. data/test/cases/associations/association_scope_test.rb +16 -16
  95. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1141
  96. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -41
  97. data/test/cases/associations/callbacks_test.rb +190 -190
  98. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  99. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  100. data/test/cases/associations/eager_load_nested_include_test.rb +126 -126
  101. data/test/cases/associations/eager_singularization_test.rb +148 -148
  102. data/test/cases/associations/eager_test.rb +1514 -1514
  103. data/test/cases/associations/extension_test.rb +87 -87
  104. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -1004
  105. data/test/cases/associations/has_many_associations_test.rb +2501 -2501
  106. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1271
  107. data/test/cases/associations/has_one_associations_test.rb +707 -707
  108. data/test/cases/associations/has_one_through_associations_test.rb +383 -383
  109. data/test/cases/associations/inner_join_association_test.rb +139 -139
  110. data/test/cases/associations/inverse_associations_test.rb +733 -733
  111. data/test/cases/associations/join_model_test.rb +777 -777
  112. data/test/cases/associations/left_outer_join_association_test.rb +88 -88
  113. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  114. data/test/cases/associations/required_test.rb +102 -102
  115. data/test/cases/associations_test.rb +385 -385
  116. data/test/cases/attribute_decorators_test.rb +126 -125
  117. data/test/cases/attribute_methods/read_test.rb +60 -60
  118. data/test/cases/attribute_methods_test.rb +1009 -1009
  119. data/test/cases/attribute_set_test.rb +270 -270
  120. data/test/cases/attribute_test.rb +246 -246
  121. data/test/cases/attributes_test.rb +253 -253
  122. data/test/cases/autosave_association_test.rb +1708 -1708
  123. data/test/cases/base_test.rb +1713 -1713
  124. data/test/cases/batches_test.rb +489 -489
  125. data/test/cases/binary_test.rb +44 -44
  126. data/test/cases/bind_parameter_test.rb +110 -110
  127. data/test/cases/cache_key_test.rb +26 -25
  128. data/test/cases/calculations_test.rb +798 -798
  129. data/test/cases/callbacks_test.rb +636 -636
  130. data/test/cases/clone_test.rb +40 -40
  131. data/test/cases/coders/json_test.rb +15 -15
  132. data/test/cases/coders/yaml_column_test.rb +63 -63
  133. data/test/cases/collection_cache_key_test.rb +115 -115
  134. data/test/cases/column_alias_test.rb +17 -17
  135. data/test/cases/column_definition_test.rb +92 -92
  136. data/test/cases/comment_test.rb +145 -143
  137. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -56
  138. data/test/cases/connection_adapters/connection_handler_test.rb +160 -160
  139. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  140. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -255
  141. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -69
  142. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  143. data/test/cases/connection_adapters/schema_cache_test.rb +61 -61
  144. data/test/cases/connection_adapters/type_lookup_test.rb +118 -118
  145. data/test/cases/connection_management_test.rb +112 -112
  146. data/test/cases/connection_pool_test.rb +521 -521
  147. data/test/cases/connection_specification/resolver_test.rb +131 -131
  148. data/test/cases/core_test.rb +112 -112
  149. data/test/cases/counter_cache_test.rb +214 -214
  150. data/test/cases/custom_locking_test.rb +17 -17
  151. data/test/cases/database_statements_test.rb +34 -34
  152. data/test/cases/date_test.rb +44 -44
  153. data/test/cases/date_time_precision_test.rb +107 -106
  154. data/test/cases/date_time_test.rb +61 -61
  155. data/test/cases/defaults_test.rb +219 -218
  156. data/test/cases/dirty_test.rb +763 -763
  157. data/test/cases/disconnected_test.rb +30 -30
  158. data/test/cases/dup_test.rb +157 -157
  159. data/test/cases/enum_test.rb +444 -444
  160. data/test/cases/errors_test.rb +16 -16
  161. data/test/cases/explain_subscriber_test.rb +64 -64
  162. data/test/cases/explain_test.rb +87 -87
  163. data/test/cases/finder_respond_to_test.rb +60 -60
  164. data/test/cases/finder_test.rb +1294 -1294
  165. data/test/cases/fixture_set/file_test.rb +156 -156
  166. data/test/cases/fixtures_test.rb +988 -988
  167. data/test/cases/forbidden_attributes_protection_test.rb +165 -165
  168. data/test/cases/habtm_destroy_order_test.rb +61 -61
  169. data/test/cases/helper.rb +204 -204
  170. data/test/cases/hot_compatibility_test.rb +142 -142
  171. data/test/cases/i18n_test.rb +45 -45
  172. data/test/cases/inheritance_test.rb +606 -606
  173. data/test/cases/integration_test.rb +155 -155
  174. data/test/cases/invalid_connection_test.rb +24 -24
  175. data/test/cases/invertible_migration_test.rb +387 -387
  176. data/test/cases/json_serialization_test.rb +311 -311
  177. data/test/cases/locking_test.rb +493 -493
  178. data/test/cases/log_subscriber_test.rb +225 -225
  179. data/test/cases/migration/change_schema_test.rb +458 -458
  180. data/test/cases/migration/change_table_test.rb +256 -256
  181. data/test/cases/migration/column_attributes_test.rb +176 -176
  182. data/test/cases/migration/column_positioning_test.rb +56 -56
  183. data/test/cases/migration/columns_test.rb +310 -310
  184. data/test/cases/migration/command_recorder_test.rb +350 -350
  185. data/test/cases/migration/compatibility_test.rb +118 -118
  186. data/test/cases/migration/create_join_table_test.rb +157 -157
  187. data/test/cases/migration/foreign_key_test.rb +362 -360
  188. data/test/cases/migration/helper.rb +39 -39
  189. data/test/cases/migration/index_test.rb +218 -218
  190. data/test/cases/migration/logger_test.rb +36 -36
  191. data/test/cases/migration/pending_migrations_test.rb +52 -52
  192. data/test/cases/migration/references_foreign_key_test.rb +221 -216
  193. data/test/cases/migration/references_index_test.rb +101 -101
  194. data/test/cases/migration/references_statements_test.rb +136 -136
  195. data/test/cases/migration/rename_table_test.rb +93 -93
  196. data/test/cases/migration_test.rb +1157 -1157
  197. data/test/cases/migrator_test.rb +471 -470
  198. data/test/cases/mixin_test.rb +68 -68
  199. data/test/cases/modules_test.rb +172 -172
  200. data/test/cases/multiparameter_attributes_test.rb +372 -372
  201. data/test/cases/multiple_db_test.rb +122 -122
  202. data/test/cases/nested_attributes_test.rb +1098 -1098
  203. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  204. data/test/cases/persistence_test.rb +1001 -1001
  205. data/test/cases/pooled_connections_test.rb +81 -81
  206. data/test/cases/primary_keys_test.rb +376 -376
  207. data/test/cases/query_cache_test.rb +446 -446
  208. data/test/cases/quoting_test.rb +202 -202
  209. data/test/cases/readonly_test.rb +119 -119
  210. data/test/cases/reaper_test.rb +85 -85
  211. data/test/cases/reflection_test.rb +509 -509
  212. data/test/cases/relation/delegation_test.rb +63 -63
  213. data/test/cases/relation/merging_test.rb +157 -157
  214. data/test/cases/relation/mutation_test.rb +183 -183
  215. data/test/cases/relation/or_test.rb +92 -92
  216. data/test/cases/relation/predicate_builder_test.rb +16 -16
  217. data/test/cases/relation/record_fetch_warning_test.rb +40 -40
  218. data/test/cases/relation/where_chain_test.rb +105 -105
  219. data/test/cases/relation/where_clause_test.rb +182 -182
  220. data/test/cases/relation/where_test.rb +322 -322
  221. data/test/cases/relation_test.rb +328 -328
  222. data/test/cases/relations_test.rb +2026 -2026
  223. data/test/cases/reload_models_test.rb +22 -22
  224. data/test/cases/result_test.rb +90 -90
  225. data/test/cases/sanitize_test.rb +176 -176
  226. data/test/cases/schema_dumper_test.rb +457 -457
  227. data/test/cases/schema_loading_test.rb +52 -52
  228. data/test/cases/scoping/default_scoping_test.rb +528 -528
  229. data/test/cases/scoping/named_scoping_test.rb +561 -561
  230. data/test/cases/scoping/relation_scoping_test.rb +400 -400
  231. data/test/cases/secure_token_test.rb +32 -32
  232. data/test/cases/serialization_test.rb +104 -104
  233. data/test/cases/serialized_attribute_test.rb +364 -364
  234. data/test/cases/statement_cache_test.rb +136 -136
  235. data/test/cases/store_test.rb +195 -195
  236. data/test/cases/suppressor_test.rb +63 -63
  237. data/test/cases/tasks/database_tasks_test.rb +462 -462
  238. data/test/cases/tasks/mysql_rake_test.rb +345 -345
  239. data/test/cases/tasks/postgresql_rake_test.rb +304 -304
  240. data/test/cases/tasks/sqlite_rake_test.rb +220 -220
  241. data/test/cases/test_case.rb +131 -131
  242. data/test/cases/test_fixtures_test.rb +36 -36
  243. data/test/cases/time_precision_test.rb +103 -102
  244. data/test/cases/timestamp_test.rb +501 -501
  245. data/test/cases/touch_later_test.rb +121 -121
  246. data/test/cases/transaction_callbacks_test.rb +518 -518
  247. data/test/cases/transaction_isolation_test.rb +106 -106
  248. data/test/cases/transactions_test.rb +835 -834
  249. data/test/cases/type/adapter_specific_registry_test.rb +133 -133
  250. data/test/cases/type/date_time_test.rb +14 -14
  251. data/test/cases/type/integer_test.rb +27 -27
  252. data/test/cases/type/string_test.rb +22 -22
  253. data/test/cases/type/type_map_test.rb +177 -177
  254. data/test/cases/type_test.rb +39 -39
  255. data/test/cases/types_test.rb +24 -24
  256. data/test/cases/unconnected_test.rb +33 -33
  257. data/test/cases/validations/absence_validation_test.rb +73 -73
  258. data/test/cases/validations/association_validation_test.rb +97 -97
  259. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  260. data/test/cases/validations/i18n_validation_test.rb +86 -86
  261. data/test/cases/validations/length_validation_test.rb +79 -79
  262. data/test/cases/validations/presence_validation_test.rb +103 -103
  263. data/test/cases/validations/uniqueness_validation_test.rb +548 -548
  264. data/test/cases/validations_repair_helper.rb +19 -19
  265. data/test/cases/validations_test.rb +194 -194
  266. data/test/cases/view_test.rb +216 -216
  267. data/test/cases/yaml_serialization_test.rb +121 -121
  268. data/test/config.example.yml +97 -97
  269. data/test/config.rb +5 -5
  270. data/test/connections/native_ibm_db/connection.rb +44 -0
  271. data/test/fixtures/accounts.yml +29 -29
  272. data/test/fixtures/admin/accounts.yml +2 -2
  273. data/test/fixtures/admin/users.yml +10 -10
  274. data/test/fixtures/author_addresses.yml +17 -17
  275. data/test/fixtures/author_favorites.yml +3 -3
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -9
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -31
  280. data/test/fixtures/bulbs.yml +5 -5
  281. data/test/fixtures/cars.yml +9 -9
  282. data/test/fixtures/categories.yml +19 -19
  283. data/test/fixtures/categories/special_categories.yml +9 -9
  284. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
  285. data/test/fixtures/categories_ordered.yml +7 -7
  286. data/test/fixtures/categories_posts.yml +31 -31
  287. data/test/fixtures/categorizations.yml +23 -23
  288. data/test/fixtures/clubs.yml +8 -8
  289. data/test/fixtures/collections.yml +3 -3
  290. data/test/fixtures/colleges.yml +3 -3
  291. data/test/fixtures/comments.yml +65 -65
  292. data/test/fixtures/companies.yml +67 -67
  293. data/test/fixtures/computers.yml +10 -10
  294. data/test/fixtures/content.yml +3 -3
  295. data/test/fixtures/content_positions.yml +3 -3
  296. data/test/fixtures/courses.yml +8 -8
  297. data/test/fixtures/customers.yml +25 -25
  298. data/test/fixtures/dashboards.yml +6 -6
  299. data/test/fixtures/dead_parrots.yml +5 -5
  300. data/test/fixtures/developers.yml +22 -22
  301. data/test/fixtures/developers_projects.yml +16 -16
  302. data/test/fixtures/dog_lovers.yml +7 -7
  303. data/test/fixtures/dogs.yml +4 -4
  304. data/test/fixtures/doubloons.yml +3 -3
  305. data/test/fixtures/edges.yml +5 -5
  306. data/test/fixtures/entrants.yml +14 -14
  307. data/test/fixtures/essays.yml +6 -6
  308. data/test/fixtures/faces.yml +11 -11
  309. data/test/fixtures/fk_test_has_fk.yml +3 -3
  310. data/test/fixtures/fk_test_has_pk.yml +1 -1
  311. data/test/fixtures/friendships.yml +4 -4
  312. data/test/fixtures/funny_jokes.yml +10 -10
  313. data/test/fixtures/interests.yml +33 -33
  314. data/test/fixtures/items.yml +3 -3
  315. data/test/fixtures/jobs.yml +7 -7
  316. data/test/fixtures/legacy_things.yml +3 -3
  317. data/test/fixtures/live_parrots.yml +4 -4
  318. data/test/fixtures/mateys.yml +4 -4
  319. data/test/fixtures/member_details.yml +8 -8
  320. data/test/fixtures/member_types.yml +6 -6
  321. data/test/fixtures/members.yml +11 -11
  322. data/test/fixtures/memberships.yml +34 -34
  323. data/test/fixtures/men.yml +5 -5
  324. data/test/fixtures/minimalistics.yml +2 -2
  325. data/test/fixtures/minivans.yml +5 -5
  326. data/test/fixtures/mixed_case_monkeys.yml +6 -6
  327. data/test/fixtures/mixins.yml +29 -29
  328. data/test/fixtures/movies.yml +7 -7
  329. data/test/fixtures/naked/yml/accounts.yml +1 -1
  330. data/test/fixtures/naked/yml/companies.yml +1 -1
  331. data/test/fixtures/naked/yml/courses.yml +1 -1
  332. data/test/fixtures/naked/yml/parrots.yml +2 -2
  333. data/test/fixtures/naked/yml/trees.yml +3 -3
  334. data/test/fixtures/nodes.yml +29 -29
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -6
  337. data/test/fixtures/other_dogs.yml +2 -2
  338. data/test/fixtures/other_posts.yml +7 -7
  339. data/test/fixtures/other_topics.yml +42 -42
  340. data/test/fixtures/owners.yml +9 -9
  341. data/test/fixtures/parrots.yml +27 -27
  342. data/test/fixtures/parrots_pirates.yml +7 -7
  343. data/test/fixtures/people.yml +24 -24
  344. data/test/fixtures/peoples_treasures.yml +3 -3
  345. data/test/fixtures/pets.yml +19 -19
  346. data/test/fixtures/pirates.yml +12 -15
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -16
  349. data/test/fixtures/products.yml +4 -4
  350. data/test/fixtures/projects.yml +7 -7
  351. data/test/fixtures/ratings.yml +14 -14
  352. data/test/fixtures/readers.yml +11 -11
  353. data/test/fixtures/references.yml +17 -17
  354. data/test/fixtures/reserved_words/distinct.yml +5 -5
  355. data/test/fixtures/reserved_words/distinct_select.yml +11 -11
  356. data/test/fixtures/reserved_words/group.yml +14 -14
  357. data/test/fixtures/reserved_words/select.yml +8 -8
  358. data/test/fixtures/reserved_words/values.yml +7 -7
  359. data/test/fixtures/ships.yml +6 -6
  360. data/test/fixtures/speedometers.yml +8 -8
  361. data/test/fixtures/sponsors.yml +12 -12
  362. data/test/fixtures/string_key_objects.yml +7 -7
  363. data/test/fixtures/subscribers.yml +10 -10
  364. data/test/fixtures/subscriptions.yml +12 -12
  365. data/test/fixtures/taggings.yml +78 -78
  366. data/test/fixtures/tags.yml +11 -11
  367. data/test/fixtures/tasks.yml +7 -7
  368. data/test/fixtures/teapots.yml +3 -3
  369. data/test/fixtures/to_be_linked/accounts.yml +2 -2
  370. data/test/fixtures/to_be_linked/users.yml +10 -10
  371. data/test/fixtures/topics.yml +49 -49
  372. data/test/fixtures/toys.yml +14 -14
  373. data/test/fixtures/traffic_lights.yml +9 -9
  374. data/test/fixtures/treasures.yml +10 -10
  375. data/test/fixtures/trees.yml +3 -3
  376. data/test/fixtures/uuid_children.yml +3 -3
  377. data/test/fixtures/uuid_parents.yml +2 -2
  378. data/test/fixtures/variants.yml +4 -4
  379. data/test/fixtures/vegetables.yml +19 -19
  380. data/test/fixtures/vertices.yml +3 -3
  381. data/test/fixtures/warehouse_things.yml +2 -2
  382. data/test/fixtures/zines.yml +5 -5
  383. data/test/migrations/10_urban/9_add_expressions.rb +11 -11
  384. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
  385. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
  386. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
  387. data/test/migrations/missing/1_people_have_last_names.rb +9 -9
  388. data/test/migrations/missing/3_we_need_reminders.rb +12 -12
  389. data/test/migrations/missing/4_innocent_jointable.rb +12 -12
  390. data/test/migrations/rename/1_we_need_things.rb +11 -11
  391. data/test/migrations/rename/2_rename_things.rb +9 -9
  392. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
  393. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
  394. data/test/migrations/to_copy2/1_create_articles.rb +7 -7
  395. data/test/migrations/to_copy2/2_create_comments.rb +7 -7
  396. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
  397. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
  398. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
  399. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
  400. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
  401. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
  402. data/test/migrations/valid/2_we_need_reminders.rb +12 -12
  403. data/test/migrations/valid/3_innocent_jointable.rb +12 -12
  404. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
  405. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
  406. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
  407. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
  408. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
  409. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
  410. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
  411. data/test/models/admin.rb +5 -5
  412. data/test/models/admin/account.rb +3 -3
  413. data/test/models/admin/user.rb +40 -40
  414. data/test/models/aircraft.rb +5 -5
  415. data/test/models/arunit2_model.rb +3 -3
  416. data/test/models/author.rb +209 -209
  417. data/test/models/auto_id.rb +4 -4
  418. data/test/models/autoloadable/extra_firm.rb +2 -2
  419. data/test/models/binary.rb +2 -2
  420. data/test/models/bird.rb +12 -12
  421. data/test/models/book.rb +23 -23
  422. data/test/models/boolean.rb +2 -2
  423. data/test/models/bulb.rb +52 -52
  424. data/test/models/cake_designer.rb +3 -3
  425. data/test/models/car.rb +29 -29
  426. data/test/models/carrier.rb +2 -2
  427. data/test/models/cat.rb +10 -10
  428. data/test/models/categorization.rb +19 -19
  429. data/test/models/category.rb +35 -35
  430. data/test/models/chef.rb +8 -8
  431. data/test/models/citation.rb +3 -3
  432. data/test/models/club.rb +25 -25
  433. data/test/models/college.rb +10 -10
  434. data/test/models/column.rb +3 -3
  435. data/test/models/column_name.rb +3 -3
  436. data/test/models/comment.rb +76 -76
  437. data/test/models/company.rb +230 -230
  438. data/test/models/company_in_module.rb +98 -98
  439. data/test/models/computer.rb +3 -3
  440. data/test/models/contact.rb +41 -41
  441. data/test/models/content.rb +40 -40
  442. data/test/models/contract.rb +20 -20
  443. data/test/models/country.rb +7 -7
  444. data/test/models/course.rb +6 -6
  445. data/test/models/customer.rb +83 -83
  446. data/test/models/customer_carrier.rb +14 -14
  447. data/test/models/dashboard.rb +3 -3
  448. data/test/models/default.rb +2 -2
  449. data/test/models/department.rb +4 -4
  450. data/test/models/developer.rb +274 -274
  451. data/test/models/dog.rb +5 -5
  452. data/test/models/dog_lover.rb +5 -5
  453. data/test/models/doubloon.rb +12 -12
  454. data/test/models/drink_designer.rb +3 -3
  455. data/test/models/edge.rb +5 -5
  456. data/test/models/electron.rb +5 -5
  457. data/test/models/engine.rb +4 -4
  458. data/test/models/entrant.rb +3 -3
  459. data/test/models/essay.rb +5 -5
  460. data/test/models/event.rb +3 -3
  461. data/test/models/eye.rb +37 -37
  462. data/test/models/face.rb +9 -9
  463. data/test/models/friendship.rb +6 -6
  464. data/test/models/guid.rb +2 -2
  465. data/test/models/guitar.rb +4 -4
  466. data/test/models/hotel.rb +11 -11
  467. data/test/models/image.rb +3 -3
  468. data/test/models/interest.rb +5 -5
  469. data/test/models/invoice.rb +4 -4
  470. data/test/models/item.rb +7 -7
  471. data/test/models/job.rb +7 -7
  472. data/test/models/joke.rb +7 -7
  473. data/test/models/keyboard.rb +3 -3
  474. data/test/models/legacy_thing.rb +3 -3
  475. data/test/models/lesson.rb +11 -11
  476. data/test/models/line_item.rb +3 -3
  477. data/test/models/liquid.rb +4 -4
  478. data/test/models/man.rb +11 -11
  479. data/test/models/matey.rb +4 -4
  480. data/test/models/member.rb +42 -42
  481. data/test/models/member_detail.rb +8 -8
  482. data/test/models/member_type.rb +3 -3
  483. data/test/models/membership.rb +35 -35
  484. data/test/models/mentor.rb +2 -2
  485. data/test/models/minimalistic.rb +2 -2
  486. data/test/models/minivan.rb +9 -9
  487. data/test/models/mixed_case_monkey.rb +3 -3
  488. data/test/models/mocktail_designer.rb +2 -2
  489. data/test/models/molecule.rb +6 -6
  490. data/test/models/movie.rb +5 -5
  491. data/test/models/node.rb +5 -5
  492. data/test/models/non_primary_key.rb +2 -2
  493. data/test/models/notification.rb +3 -3
  494. data/test/models/order.rb +4 -4
  495. data/test/models/organization.rb +14 -14
  496. data/test/models/other_dog.rb +5 -5
  497. data/test/models/owner.rb +37 -37
  498. data/test/models/parrot.rb +28 -28
  499. data/test/models/person.rb +142 -142
  500. data/test/models/personal_legacy_thing.rb +4 -4
  501. data/test/models/pet.rb +18 -18
  502. data/test/models/pet_treasure.rb +6 -6
  503. data/test/models/pirate.rb +92 -92
  504. data/test/models/possession.rb +3 -3
  505. data/test/models/post.rb +273 -273
  506. data/test/models/price_estimate.rb +4 -4
  507. data/test/models/professor.rb +5 -5
  508. data/test/models/project.rb +40 -40
  509. data/test/models/publisher.rb +2 -2
  510. data/test/models/publisher/article.rb +4 -4
  511. data/test/models/publisher/magazine.rb +3 -3
  512. data/test/models/rating.rb +4 -4
  513. data/test/models/reader.rb +23 -23
  514. data/test/models/recipe.rb +3 -3
  515. data/test/models/record.rb +2 -2
  516. data/test/models/reference.rb +22 -22
  517. data/test/models/reply.rb +61 -61
  518. data/test/models/ship.rb +39 -39
  519. data/test/models/ship_part.rb +8 -8
  520. data/test/models/shop.rb +17 -17
  521. data/test/models/shop_account.rb +6 -6
  522. data/test/models/speedometer.rb +6 -6
  523. data/test/models/sponsor.rb +7 -7
  524. data/test/models/string_key_object.rb +3 -3
  525. data/test/models/student.rb +4 -4
  526. data/test/models/subject.rb +16 -16
  527. data/test/models/subscriber.rb +8 -8
  528. data/test/models/subscription.rb +4 -4
  529. data/test/models/tag.rb +13 -13
  530. data/test/models/tagging.rb +13 -13
  531. data/test/models/task.rb +5 -5
  532. data/test/models/topic.rb +118 -118
  533. data/test/models/toy.rb +6 -6
  534. data/test/models/traffic_light.rb +4 -4
  535. data/test/models/treasure.rb +14 -14
  536. data/test/models/treaty.rb +7 -7
  537. data/test/models/tree.rb +3 -3
  538. data/test/models/tuning_peg.rb +4 -4
  539. data/test/models/tyre.rb +11 -11
  540. data/test/models/user.rb +14 -14
  541. data/test/models/uuid_child.rb +3 -3
  542. data/test/models/uuid_item.rb +6 -6
  543. data/test/models/uuid_parent.rb +3 -3
  544. data/test/models/vegetables.rb +24 -24
  545. data/test/models/vehicle.rb +6 -6
  546. data/test/models/vertex.rb +9 -9
  547. data/test/models/warehouse_thing.rb +5 -5
  548. data/test/models/wheel.rb +3 -3
  549. data/test/models/without_table.rb +3 -3
  550. data/test/models/zine.rb +3 -3
  551. data/test/schema/i5/ibm_db_specific_schema.rb +137 -0
  552. data/test/schema/ids/ibm_db_specific_schema.rb +140 -0
  553. data/test/schema/luw/ibm_db_specific_schema.rb +137 -0
  554. data/test/schema/mysql2_specific_schema.rb +68 -68
  555. data/test/schema/oracle_specific_schema.rb +40 -40
  556. data/test/schema/postgresql_specific_schema.rb +114 -114
  557. data/test/schema/schema.rb +1057 -1057
  558. data/test/schema/schema.rb.original +1057 -1057
  559. data/test/schema/sqlite_specific_schema.rb +18 -18
  560. data/test/schema/zOS/ibm_db_specific_schema.rb +208 -0
  561. data/test/support/config.rb +43 -43
  562. data/test/support/connection.rb +23 -23
  563. data/test/support/connection_helper.rb +14 -14
  564. data/test/support/ddl_helper.rb +8 -8
  565. data/test/support/schema_dumping_helper.rb +20 -20
  566. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -22
  567. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -182
  568. metadata +24 -13
  569. data/test/fixtures/author_addresses.original +0 -11
  570. data/test/fixtures/authors.original +0 -17
@@ -1,125 +1,126 @@
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 cast(value)
16
- "#{super} #{@decoration}"
17
- end
18
-
19
- alias deserialize cast
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_exists: true
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, :string, 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, :string, 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 cast(value)
106
- return if value.nil?
107
- value * 2
108
- end
109
- alias deserialize cast
110
- end
111
-
112
- test "decorating with a proc" do
113
- Model.attribute :an_int, :integer
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 cast(value)
16
+ "#{super} #{@decoration}"
17
+ end
18
+
19
+ alias deserialize cast
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'
32
+ #, if_exists: true
33
+ Model.attribute_type_decorations.clear
34
+ Model.reset_column_information
35
+ end
36
+
37
+ test "attributes can be decorated" do
38
+ model = Model.new(a_string: 'Hello')
39
+ assert_equal 'Hello', model.a_string
40
+
41
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
42
+
43
+ model = Model.new(a_string: 'Hello')
44
+ assert_equal 'Hello decorated!', model.a_string
45
+ end
46
+
47
+ test "decoration does not eagerly load existing columns" do
48
+ Model.reset_column_information
49
+ assert_no_queries do
50
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
51
+ end
52
+ end
53
+
54
+ test "undecorated columns are not touched" do
55
+ Model.attribute :another_string, :string, default: 'something or other'
56
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
57
+
58
+ assert_equal 'something or other', Model.new.another_string
59
+ end
60
+
61
+ test "decorators can be chained" do
62
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
63
+ Model.decorate_attribute_type(:a_string, :other) { |t| StringDecorator.new(t) }
64
+
65
+ model = Model.new(a_string: 'Hello!')
66
+
67
+ assert_equal 'Hello! decorated! decorated!', model.a_string
68
+ end
69
+
70
+ test "decoration of the same type multiple times is idempotent" do
71
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
72
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
73
+
74
+ model = Model.new(a_string: 'Hello')
75
+ assert_equal 'Hello decorated!', model.a_string
76
+ end
77
+
78
+ test "decorations occur in order of declaration" do
79
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
80
+ Model.decorate_attribute_type(:a_string, :other) do |type|
81
+ StringDecorator.new(type, 'decorated again!')
82
+ end
83
+
84
+ model = Model.new(a_string: 'Hello!')
85
+
86
+ assert_equal 'Hello! decorated! decorated again!', model.a_string
87
+ end
88
+
89
+ test "decorating attributes does not modify parent classes" do
90
+ Model.attribute :another_string, :string, default: 'whatever'
91
+ Model.decorate_attribute_type(:a_string, :test) { |t| StringDecorator.new(t) }
92
+ child_class = Class.new(Model)
93
+ child_class.decorate_attribute_type(:another_string, :test) { |t| StringDecorator.new(t) }
94
+ child_class.decorate_attribute_type(:a_string, :other) { |t| StringDecorator.new(t) }
95
+
96
+ model = Model.new(a_string: 'Hello!')
97
+ child = child_class.new(a_string: 'Hello!')
98
+
99
+ assert_equal 'Hello! decorated!', model.a_string
100
+ assert_equal 'whatever', model.another_string
101
+ assert_equal 'Hello! decorated! decorated!', child.a_string
102
+ assert_equal 'whatever decorated!', child.another_string
103
+ end
104
+
105
+ class Multiplier < SimpleDelegator
106
+ def cast(value)
107
+ return if value.nil?
108
+ value * 2
109
+ end
110
+ alias deserialize cast
111
+ end
112
+
113
+ test "decorating with a proc" do
114
+ Model.attribute :an_int, :integer
115
+ type_is_integer = proc { |_, type| type.type == :integer }
116
+ Model.decorate_matching_attribute_types type_is_integer, :multiplier do |type|
117
+ Multiplier.new(type)
118
+ end
119
+
120
+ model = Model.new(a_string: 'whatever', an_int: 1)
121
+
122
+ assert_equal 'whatever', model.a_string
123
+ assert_equal 2, model.an_int
124
+ end
125
+ end
126
+ 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.attribute_names
21
- %w{ one two three }
22
- end
23
-
24
- def self.primary_key
25
- end
26
-
27
- def self.columns
28
- attribute_names.map { FakeColumn.new(name) }
29
- end
30
-
31
- def self.columns_hash
32
- Hash[attribute_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.attribute_names.each do |name|
43
- assert !instance.methods.map(&:to_s).include?(name)
44
- end
45
-
46
- @klass.define_attribute_methods
47
-
48
- @klass.attribute_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.attribute_names
21
+ %w{ one two three }
22
+ end
23
+
24
+ def self.primary_key
25
+ end
26
+
27
+ def self.columns
28
+ attribute_names.map { FakeColumn.new(name) }
29
+ end
30
+
31
+ def self.columns_hash
32
+ Hash[attribute_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.attribute_names.each do |name|
43
+ assert !instance.methods.map(&:to_s).include?(name)
44
+ end
45
+
46
+ @klass.define_attribute_methods
47
+
48
+ @klass.attribute_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,1009 +1,1009 @@
1
- require "cases/helper"
2
- require 'models/minimalistic'
3
- require 'models/developer'
4
- require 'models/auto_id'
5
- require 'models/boolean'
6
- require 'models/computer'
7
- require 'models/topic'
8
- require 'models/company'
9
- require 'models/category'
10
- require 'models/reply'
11
- require 'models/contact'
12
- require 'models/keyboard'
13
-
14
- class AttributeMethodsTest < ActiveRecord::TestCase
15
- include InTimeZone
16
-
17
- fixtures :topics, :developers, :companies, :computers
18
-
19
- def setup
20
- @old_matchers = ActiveRecord::Base.send(:attribute_method_matchers).dup
21
- @target = Class.new(ActiveRecord::Base)
22
- @target.table_name = 'topics'
23
- end
24
-
25
- teardown do
26
- ActiveRecord::Base.send(:attribute_method_matchers).clear
27
- ActiveRecord::Base.send(:attribute_method_matchers).concat(@old_matchers)
28
- end
29
-
30
- def test_attribute_for_inspect_string
31
- t = topics(:first)
32
- t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
33
-
34
- assert_equal '"The First Topic Now Has A Title With\nNewlines And ..."', t.attribute_for_inspect(:title)
35
- end
36
-
37
- def test_attribute_for_inspect_date
38
- t = topics(:first)
39
-
40
- assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
41
- end
42
-
43
- def test_attribute_for_inspect_array
44
- t = topics(:first)
45
- t.content = [Object.new]
46
-
47
- assert_match %r(\[#<Object:0x[0-9a-f]+>\]), t.attribute_for_inspect(:content)
48
- end
49
-
50
- def test_attribute_for_inspect_long_array
51
- t = topics(:first)
52
- t.content = (1..11).to_a
53
-
54
- assert_equal "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", t.attribute_for_inspect(:content)
55
- end
56
-
57
- def test_attribute_present
58
- t = Topic.new
59
- t.title = "hello there!"
60
- t.written_on = Time.now
61
- t.author_name = ""
62
- assert t.attribute_present?("title")
63
- assert t.attribute_present?("written_on")
64
- assert !t.attribute_present?("content")
65
- assert !t.attribute_present?("author_name")
66
- end
67
-
68
- def test_attribute_present_with_booleans
69
- b1 = Boolean.new
70
- b1.value = false
71
- assert b1.attribute_present?(:value)
72
-
73
- b2 = Boolean.new
74
- b2.value = true
75
- assert b2.attribute_present?(:value)
76
-
77
- b3 = Boolean.new
78
- assert !b3.attribute_present?(:value)
79
-
80
- b4 = Boolean.new
81
- b4.value = false
82
- b4.save!
83
- assert Boolean.find(b4.id).attribute_present?(:value)
84
- end
85
-
86
- def test_caching_nil_primary_key
87
- klass = Class.new(Minimalistic)
88
- assert_called(klass, :reset_primary_key, returns: nil) do
89
- 2.times { klass.primary_key }
90
- end
91
- end
92
-
93
- def test_attribute_keys_on_new_instance
94
- t = Topic.new
95
- assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
96
- assert_raise(NoMethodError) { t.title2 }
97
- end
98
-
99
- def test_boolean_attributes
100
- assert !Topic.find(1).approved?
101
- assert Topic.find(2).approved?
102
- end
103
-
104
- def test_set_attributes
105
- topic = Topic.find(1)
106
- topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
107
- topic.save
108
- assert_equal("Budget", topic.title)
109
- assert_equal("Jason", topic.author_name)
110
- assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
111
- end
112
-
113
- def test_set_attributes_without_hash
114
- topic = Topic.new
115
- assert_raise(ArgumentError) { topic.attributes = '' }
116
- end
117
-
118
- def test_integers_as_nil
119
- test = AutoId.create('value' => '')
120
- assert_nil AutoId.find(test.id).value
121
- end
122
-
123
- def test_set_attributes_with_block
124
- topic = Topic.new do |t|
125
- t.title = "Budget"
126
- t.author_name = "Jason"
127
- end
128
-
129
- assert_equal("Budget", topic.title)
130
- assert_equal("Jason", topic.author_name)
131
- end
132
-
133
- def test_respond_to?
134
- topic = Topic.find(1)
135
- assert_respond_to topic, "title"
136
- assert_respond_to topic, "title?"
137
- assert_respond_to topic, "title="
138
- assert_respond_to topic, :title
139
- assert_respond_to topic, :title?
140
- assert_respond_to topic, :title=
141
- assert_respond_to topic, "author_name"
142
- assert_respond_to topic, "attribute_names"
143
- assert !topic.respond_to?("nothingness")
144
- assert !topic.respond_to?(:nothingness)
145
- end
146
-
147
- def test_respond_to_with_custom_primary_key
148
- keyboard = Keyboard.create
149
- assert_not_nil keyboard.key_number
150
- assert_equal keyboard.key_number, keyboard.id
151
- assert keyboard.respond_to?('key_number')
152
- assert keyboard.respond_to?('id')
153
- end
154
-
155
- def test_id_before_type_cast_with_custom_primary_key
156
- keyboard = Keyboard.create
157
- keyboard.key_number = '10'
158
- assert_equal '10', keyboard.id_before_type_cast
159
- assert_equal nil, keyboard.read_attribute_before_type_cast('id')
160
- assert_equal '10', keyboard.read_attribute_before_type_cast('key_number')
161
- assert_equal '10', keyboard.read_attribute_before_type_cast(:key_number)
162
- end
163
-
164
- # Syck calls respond_to? before actually calling initialize
165
- def test_respond_to_with_allocated_object
166
- klass = Class.new(ActiveRecord::Base) do
167
- self.table_name = 'topics'
168
- end
169
-
170
- topic = klass.allocate
171
- assert !topic.respond_to?("nothingness")
172
- assert !topic.respond_to?(:nothingness)
173
- assert_respond_to topic, "title"
174
- assert_respond_to topic, :title
175
- end
176
-
177
- # IRB inspects the return value of "MyModel.allocate".
178
- def test_allocated_object_can_be_inspected
179
- topic = Topic.allocate
180
- assert_equal "#<Topic not initialized>", topic.inspect
181
- end
182
-
183
- def test_array_content
184
- topic = Topic.new
185
- topic.content = %w( one two three )
186
- topic.save
187
-
188
- assert_equal(%w( one two three ), Topic.find(topic.id).content)
189
- end
190
-
191
- def test_read_attributes_before_type_cast
192
- category = Category.new({:name=>"Test category", :type => nil})
193
- category_attrs = {"name"=>"Test category", "id" => nil, "type" => nil, "categorizations_count" => nil}
194
- assert_equal category_attrs , category.attributes_before_type_cast
195
- end
196
-
197
- if current_adapter?(:Mysql2Adapter)
198
- def test_read_attributes_before_type_cast_on_boolean
199
- bool = Boolean.create!({ "value" => false })
200
- if RUBY_PLATFORM =~ /java/
201
- # JRuby will return the value before typecast as string
202
- assert_equal "0", bool.reload.attributes_before_type_cast["value"]
203
- else
204
- assert_equal 0, bool.reload.attributes_before_type_cast["value"]
205
- end
206
- end
207
- end
208
-
209
- def test_read_attributes_before_type_cast_on_datetime
210
- in_time_zone "Pacific Time (US & Canada)" do
211
- record = @target.new
212
-
213
- record.written_on = "345643456"
214
- assert_equal "345643456", record.written_on_before_type_cast
215
- assert_equal nil, record.written_on
216
-
217
- record.written_on = "2009-10-11 12:13:14"
218
- assert_equal "2009-10-11 12:13:14", record.written_on_before_type_cast
219
- assert_equal Time.zone.parse("2009-10-11 12:13:14"), record.written_on
220
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
221
- end
222
- end
223
-
224
- def test_read_attributes_after_type_cast_on_datetime
225
- tz = "Pacific Time (US & Canada)"
226
-
227
- in_time_zone tz do
228
- record = @target.new
229
-
230
- date_string = "2011-03-24"
231
- time = Time.zone.parse date_string
232
-
233
- record.written_on = date_string
234
- assert_equal date_string, record.written_on_before_type_cast
235
- assert_equal time, record.written_on
236
- assert_equal ActiveSupport::TimeZone[tz], record.written_on.time_zone
237
-
238
- record.save
239
- record.reload
240
-
241
- assert_equal time, record.written_on
242
- end
243
- end
244
-
245
- def test_hash_content
246
- topic = Topic.new
247
- topic.content = { "one" => 1, "two" => 2 }
248
- topic.save
249
-
250
- assert_equal 2, Topic.find(topic.id).content["two"]
251
-
252
- topic.content_will_change!
253
- topic.content["three"] = 3
254
- topic.save
255
-
256
- assert_equal 3, Topic.find(topic.id).content["three"]
257
- end
258
-
259
- def test_update_array_content
260
- topic = Topic.new
261
- topic.content = %w( one two three )
262
-
263
- topic.content.push "four"
264
- assert_equal(%w( one two three four ), topic.content)
265
-
266
- topic.save
267
-
268
- topic = Topic.find(topic.id)
269
- topic.content << "five"
270
- assert_equal(%w( one two three four five ), topic.content)
271
- end
272
-
273
- def test_case_sensitive_attributes_hash
274
- # DB2 is not case-sensitive
275
- return true if current_adapter?(:DB2Adapter)
276
-
277
- assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes
278
- end
279
-
280
- def test_attributes_without_primary_key
281
- klass = Class.new(ActiveRecord::Base) do
282
- self.table_name = 'developers_projects'
283
- end
284
-
285
- assert_equal klass.column_names, klass.new.attributes.keys
286
- assert_not klass.new.has_attribute?('id')
287
- end
288
-
289
- def test_hashes_not_mangled
290
- new_topic = { :title => "New Topic" }
291
- new_topic_values = { :title => "AnotherTopic" }
292
-
293
- topic = Topic.new(new_topic)
294
- assert_equal new_topic[:title], topic.title
295
-
296
- topic.attributes= new_topic_values
297
- assert_equal new_topic_values[:title], topic.title
298
- end
299
-
300
- def test_create_through_factory
301
- topic = Topic.create("title" => "New Topic")
302
- topicReloaded = Topic.find(topic.id)
303
- assert_equal(topic, topicReloaded)
304
- end
305
-
306
- def test_write_attribute
307
- topic = Topic.new
308
- topic.send(:write_attribute, :title, "Still another topic")
309
- assert_equal "Still another topic", topic.title
310
-
311
- topic[:title] = "Still another topic: part 2"
312
- assert_equal "Still another topic: part 2", topic.title
313
-
314
- topic.send(:write_attribute, "title", "Still another topic: part 3")
315
- assert_equal "Still another topic: part 3", topic.title
316
-
317
- topic["title"] = "Still another topic: part 4"
318
- assert_equal "Still another topic: part 4", topic.title
319
- end
320
-
321
- def test_read_attribute
322
- topic = Topic.new
323
- topic.title = "Don't change the topic"
324
- assert_equal "Don't change the topic", topic.read_attribute("title")
325
- assert_equal "Don't change the topic", topic["title"]
326
-
327
- assert_equal "Don't change the topic", topic.read_attribute(:title)
328
- assert_equal "Don't change the topic", topic[:title]
329
- end
330
-
331
- def test_read_attribute_raises_missing_attribute_error_when_not_exists
332
- computer = Computer.select('id').first
333
- assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
334
- assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
335
- assert_raises(ActiveModel::MissingAttributeError) { computer[:no_column_exists] = 'Hello!' }
336
- assert_nothing_raised { computer[:developer] = 'Hello!' }
337
- end
338
-
339
- def test_read_attribute_when_false
340
- topic = topics(:first)
341
- topic.approved = false
342
- assert !topic.approved?, "approved should be false"
343
- topic.approved = "false"
344
- assert !topic.approved?, "approved should be false"
345
- end
346
-
347
- def test_read_attribute_when_true
348
- topic = topics(:first)
349
- topic.approved = true
350
- assert topic.approved?, "approved should be true"
351
- topic.approved = "true"
352
- assert topic.approved?, "approved should be true"
353
- end
354
-
355
- def test_read_write_boolean_attribute
356
- topic = Topic.new
357
- topic.approved = "false"
358
- assert !topic.approved?, "approved should be false"
359
-
360
- topic.approved = "false"
361
- assert !topic.approved?, "approved should be false"
362
-
363
- topic.approved = "true"
364
- assert topic.approved?, "approved should be true"
365
-
366
- topic.approved = "true"
367
- assert topic.approved?, "approved should be true"
368
- end
369
-
370
- def test_overridden_write_attribute
371
- topic = Topic.new
372
- def topic.write_attribute(attr_name, value)
373
- super(attr_name, value.downcase)
374
- end
375
-
376
- topic.send(:write_attribute, :title, "Yet another topic")
377
- assert_equal "yet another topic", topic.title
378
-
379
- topic[:title] = "Yet another topic: part 2"
380
- assert_equal "yet another topic: part 2", topic.title
381
-
382
- topic.send(:write_attribute, "title", "Yet another topic: part 3")
383
- assert_equal "yet another topic: part 3", topic.title
384
-
385
- topic["title"] = "Yet another topic: part 4"
386
- assert_equal "yet another topic: part 4", topic.title
387
- end
388
-
389
- def test_overridden_read_attribute
390
- topic = Topic.new
391
- topic.title = "Stop changing the topic"
392
- def topic.read_attribute(attr_name)
393
- super(attr_name).upcase
394
- end
395
-
396
- assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute("title")
397
- assert_equal "STOP CHANGING THE TOPIC", topic["title"]
398
-
399
- assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute(:title)
400
- assert_equal "STOP CHANGING THE TOPIC", topic[:title]
401
- end
402
-
403
- def test_read_overridden_attribute
404
- topic = Topic.new(:title => 'a')
405
- def topic.title() 'b' end
406
- assert_equal 'a', topic[:title]
407
- end
408
-
409
- def test_query_attribute_string
410
- [nil, "", " "].each do |value|
411
- assert_equal false, Topic.new(:author_name => value).author_name?
412
- end
413
-
414
- assert_equal true, Topic.new(:author_name => "Name").author_name?
415
- end
416
-
417
- def test_query_attribute_number
418
- [nil, 0, "0"].each do |value|
419
- assert_equal false, Developer.new(:salary => value).salary?
420
- end
421
-
422
- assert_equal true, Developer.new(:salary => 1).salary?
423
- assert_equal true, Developer.new(:salary => "1").salary?
424
- end
425
-
426
- def test_query_attribute_boolean
427
- [nil, "", false, "false", "f", 0].each do |value|
428
- assert_equal false, Topic.new(:approved => value).approved?
429
- end
430
-
431
- [true, "true", "1", 1].each do |value|
432
- assert_equal true, Topic.new(:approved => value).approved?
433
- end
434
- end
435
-
436
- def test_query_attribute_with_custom_fields
437
- object = Company.find_by_sql(<<-SQL).first
438
- SELECT c1.*, c2.type as string_value, c2.rating as int_value
439
- FROM companies c1, companies c2
440
- WHERE c1.firm_id = c2.id
441
- AND c1.id = 2
442
- SQL
443
-
444
- assert_equal "Firm", object.string_value
445
- assert object.string_value?
446
-
447
- object.string_value = " "
448
- assert !object.string_value?
449
-
450
- assert_equal 1, object.int_value.to_i
451
- assert object.int_value?
452
-
453
- object.int_value = "0"
454
- assert !object.int_value?
455
- end
456
-
457
- def test_non_attribute_access_and_assignment
458
- topic = Topic.new
459
- assert !topic.respond_to?("mumbo")
460
- assert_raise(NoMethodError) { topic.mumbo }
461
- assert_raise(NoMethodError) { topic.mumbo = 5 }
462
- end
463
-
464
- def test_undeclared_attribute_method_does_not_affect_respond_to_and_method_missing
465
- topic = @target.new(:title => 'Budget')
466
- assert topic.respond_to?('title')
467
- assert_equal 'Budget', topic.title
468
- assert !topic.respond_to?('title_hello_world')
469
- assert_raise(NoMethodError) { topic.title_hello_world }
470
- end
471
-
472
- def test_declared_prefixed_attribute_method_affects_respond_to_and_method_missing
473
- topic = @target.new(:title => 'Budget')
474
- %w(default_ title_).each do |prefix|
475
- @target.class_eval "def #{prefix}attribute(*args) args end"
476
- @target.attribute_method_prefix prefix
477
-
478
- meth = "#{prefix}title"
479
- assert topic.respond_to?(meth)
480
- assert_equal ['title'], topic.send(meth)
481
- assert_equal ['title', 'a'], topic.send(meth, 'a')
482
- assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
483
- end
484
- end
485
-
486
- def test_declared_suffixed_attribute_method_affects_respond_to_and_method_missing
487
- %w(_default _title_default _it! _candidate= able?).each do |suffix|
488
- @target.class_eval "def attribute#{suffix}(*args) args end"
489
- @target.attribute_method_suffix suffix
490
- topic = @target.new(:title => 'Budget')
491
-
492
- meth = "title#{suffix}"
493
- assert topic.respond_to?(meth)
494
- assert_equal ['title'], topic.send(meth)
495
- assert_equal ['title', 'a'], topic.send(meth, 'a')
496
- assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
497
- end
498
- end
499
-
500
- def test_declared_affixed_attribute_method_affects_respond_to_and_method_missing
501
- [['mark_', '_for_update'], ['reset_', '!'], ['default_', '_value?']].each do |prefix, suffix|
502
- @target.class_eval "def #{prefix}attribute#{suffix}(*args) args end"
503
- @target.attribute_method_affix({ :prefix => prefix, :suffix => suffix })
504
- topic = @target.new(:title => 'Budget')
505
-
506
- meth = "#{prefix}title#{suffix}"
507
- assert topic.respond_to?(meth)
508
- assert_equal ['title'], topic.send(meth)
509
- assert_equal ['title', 'a'], topic.send(meth, 'a')
510
- assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
511
- end
512
- end
513
-
514
- def test_should_unserialize_attributes_for_frozen_records
515
- myobj = {:value1 => :value2}
516
- topic = Topic.create("content" => myobj)
517
- topic.freeze
518
- assert_equal myobj, topic.content
519
- end
520
-
521
- def test_typecast_attribute_from_select_to_false
522
- Topic.create(:title => 'Budget')
523
- # Oracle does not support boolean expressions in SELECT
524
- if current_adapter?(:OracleAdapter, :FbAdapter)
525
- topic = Topic.all.merge!(:select => "topics.*, 0 as is_test").first
526
- else
527
- topic = Topic.all.merge!(:select => "topics.*, 1=2 as is_test").first
528
- end
529
- assert !topic.is_test?
530
- end
531
-
532
- def test_typecast_attribute_from_select_to_true
533
- Topic.create(:title => 'Budget')
534
- # Oracle does not support boolean expressions in SELECT
535
- if current_adapter?(:OracleAdapter, :FbAdapter)
536
- topic = Topic.all.merge!(:select => "topics.*, 1 as is_test").first
537
- else
538
- topic = Topic.all.merge!(:select => "topics.*, 2=2 as is_test").first
539
- end
540
- assert topic.is_test?
541
- end
542
-
543
- def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
544
- %w(save create_or_update).each do |method|
545
- klass = Class.new ActiveRecord::Base
546
- klass.class_eval "def #{method}() 'defined #{method}' end"
547
- assert_raise ActiveRecord::DangerousAttributeError do
548
- klass.instance_method_already_implemented?(method)
549
- end
550
- end
551
- end
552
-
553
- def test_converted_values_are_returned_after_assignment
554
- developer = Developer.new(name: 1337, salary: "50000")
555
-
556
- assert_equal "50000", developer.salary_before_type_cast
557
- assert_equal 1337, developer.name_before_type_cast
558
-
559
- assert_equal 50000, developer.salary
560
- assert_equal "1337", developer.name
561
-
562
- developer.save!
563
-
564
- assert_equal 50000, developer.salary
565
- assert_equal "1337", developer.name
566
- end
567
-
568
- def test_write_nil_to_time_attributes
569
- in_time_zone "Pacific Time (US & Canada)" do
570
- record = @target.new
571
- record.written_on = nil
572
- assert_nil record.written_on
573
- end
574
- end
575
-
576
- def test_write_time_to_date_attributes
577
- in_time_zone "Pacific Time (US & Canada)" do
578
- record = @target.new
579
- record.last_read = Time.utc(2010, 1, 1, 10)
580
- assert_equal Date.civil(2010, 1, 1), record.last_read
581
- end
582
- end
583
-
584
- def test_time_attributes_are_retrieved_in_current_time_zone
585
- in_time_zone "Pacific Time (US & Canada)" do
586
- utc_time = Time.utc(2008, 1, 1)
587
- record = @target.new
588
- record[:written_on] = utc_time
589
- assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
590
- assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
591
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
592
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
593
- end
594
- end
595
-
596
- def test_setting_time_zone_aware_attribute_to_utc
597
- in_time_zone "Pacific Time (US & Canada)" do
598
- utc_time = Time.utc(2008, 1, 1)
599
- record = @target.new
600
- record.written_on = utc_time
601
- assert_equal utc_time, record.written_on
602
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
603
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
604
- end
605
- end
606
-
607
- def test_setting_time_zone_aware_attribute_in_other_time_zone
608
- utc_time = Time.utc(2008, 1, 1)
609
- cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
610
- in_time_zone "Pacific Time (US & Canada)" do
611
- record = @target.new
612
- record.written_on = cst_time
613
- assert_equal utc_time, record.written_on
614
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
615
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
616
- end
617
- end
618
-
619
- def test_setting_time_zone_aware_read_attribute
620
- utc_time = Time.utc(2008, 1, 1)
621
- cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
622
- in_time_zone "Pacific Time (US & Canada)" do
623
- record = @target.create(:written_on => cst_time).reload
624
- assert_equal utc_time, record[:written_on]
625
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record[:written_on].time_zone
626
- assert_equal Time.utc(2007, 12, 31, 16), record[:written_on].time
627
- end
628
- end
629
-
630
- def test_setting_time_zone_aware_attribute_with_string
631
- utc_time = Time.utc(2008, 1, 1)
632
- (-11..13).each do |timezone_offset|
633
- time_string = utc_time.in_time_zone(timezone_offset).to_s
634
- in_time_zone "Pacific Time (US & Canada)" do
635
- record = @target.new
636
- record.written_on = time_string
637
- assert_equal Time.zone.parse(time_string), record.written_on
638
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
639
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
640
- end
641
- end
642
- end
643
-
644
- def test_time_zone_aware_attribute_saved
645
- in_time_zone 1 do
646
- record = @target.create(:written_on => '2012-02-20 10:00')
647
-
648
- record.written_on = '2012-02-20 09:00'
649
- record.save
650
- assert_equal Time.zone.local(2012, 02, 20, 9), record.reload.written_on
651
- end
652
- end
653
-
654
- def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
655
- in_time_zone "Pacific Time (US & Canada)" do
656
- record = @target.new
657
- record.written_on = ' '
658
- assert_nil record.written_on
659
- assert_nil record[:written_on]
660
- end
661
- end
662
-
663
- def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
664
- time_string = 'Tue Jan 01 00:00:00 2008'
665
- (-11..13).each do |timezone_offset|
666
- in_time_zone timezone_offset do
667
- record = @target.new
668
- record.written_on = time_string
669
- assert_equal Time.zone.parse(time_string), record.written_on
670
- assert_equal ActiveSupport::TimeZone[timezone_offset], record.written_on.time_zone
671
- assert_equal Time.utc(2008, 1, 1), record.written_on.time
672
- end
673
- end
674
- end
675
-
676
- def test_setting_time_zone_aware_datetime_in_current_time_zone
677
- utc_time = Time.utc(2008, 1, 1)
678
- in_time_zone "Pacific Time (US & Canada)" do
679
- record = @target.new
680
- record.written_on = utc_time.in_time_zone
681
- assert_equal utc_time, record.written_on
682
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
683
- assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
684
- end
685
- end
686
-
687
- def test_yaml_dumping_record_with_time_zone_aware_attribute
688
- in_time_zone "Pacific Time (US & Canada)" do
689
- record = Topic.new(id: 1)
690
- record.written_on = "Jan 01 00:00:00 2014"
691
- assert_equal record, YAML.load(YAML.dump(record))
692
- end
693
- end
694
-
695
- def test_setting_time_zone_aware_time_in_current_time_zone
696
- in_time_zone "Pacific Time (US & Canada)" do
697
- record = @target.new
698
- time_string = "10:00:00"
699
- expected_time = Time.zone.parse("2000-01-01 #{time_string}")
700
-
701
- record.bonus_time = time_string
702
- assert_equal expected_time, record.bonus_time
703
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.bonus_time.time_zone
704
-
705
- record.bonus_time = ''
706
- assert_nil record.bonus_time
707
- end
708
- end
709
-
710
- def test_setting_time_zone_aware_time_with_dst
711
- in_time_zone "Pacific Time (US & Canada)" do
712
- current_time = Time.zone.local(2014, 06, 15, 10)
713
- record = @target.new(bonus_time: current_time)
714
- time_before_save = record.bonus_time
715
-
716
- record.save
717
- record.reload
718
-
719
- assert_equal time_before_save, record.bonus_time
720
- assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.bonus_time.time_zone
721
- end
722
- end
723
-
724
- def test_removing_time_zone_aware_types
725
- with_time_zone_aware_types(:datetime) do
726
- in_time_zone "Pacific Time (US & Canada)" do
727
- record = @target.new(bonus_time: "10:00:00")
728
- expected_time = Time.utc(2000, 01, 01, 10)
729
-
730
- assert_equal expected_time, record.bonus_time
731
- assert record.bonus_time.utc?
732
- end
733
- end
734
- end
735
-
736
- def test_time_zone_aware_attributes_dont_recurse_infinitely_on_invalid_values
737
- in_time_zone "Pacific Time (US & Canada)" do
738
- record = @target.new(bonus_time: [])
739
- assert_equal nil, record.bonus_time
740
- end
741
- end
742
-
743
- def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
744
- Topic.skip_time_zone_conversion_for_attributes = [:field_a]
745
- Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
746
-
747
- assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
748
- assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
749
- end
750
-
751
- def test_read_attributes_respect_access_control
752
- privatize("title")
753
-
754
- topic = @target.new(:title => "The pros and cons of programming naked.")
755
- assert !topic.respond_to?(:title)
756
- exception = assert_raise(NoMethodError) { topic.title }
757
- assert exception.message.include?("private method")
758
- assert_equal "I'm private", topic.send(:title)
759
- end
760
-
761
- def test_write_attributes_respect_access_control
762
- privatize("title=(value)")
763
-
764
- topic = @target.new
765
- assert !topic.respond_to?(:title=)
766
- exception = assert_raise(NoMethodError) { topic.title = "Pants"}
767
- assert exception.message.include?("private method")
768
- topic.send(:title=, "Very large pants")
769
- end
770
-
771
- def test_question_attributes_respect_access_control
772
- privatize("title?")
773
-
774
- topic = @target.new(:title => "Isaac Newton's pants")
775
- assert !topic.respond_to?(:title?)
776
- exception = assert_raise(NoMethodError) { topic.title? }
777
- assert exception.message.include?("private method")
778
- assert topic.send(:title?)
779
- end
780
-
781
- def test_bulk_update_respects_access_control
782
- privatize("title=(value)")
783
-
784
- assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
785
- assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
786
- end
787
-
788
- def test_bulk_update_raise_unknown_attribute_error
789
- error = assert_raises(ActiveRecord::UnknownAttributeError) {
790
- Topic.new(hello: "world")
791
- }
792
- assert_instance_of Topic, error.record
793
- assert_equal "hello", error.attribute
794
- assert_equal "unknown attribute 'hello' for Topic.", error.message
795
- end
796
-
797
- def test_methods_override_in_multi_level_subclass
798
- klass = Class.new(Developer) do
799
- def name
800
- "dev:#{read_attribute(:name)}"
801
- end
802
- end
803
-
804
- 2.times { klass = Class.new klass }
805
- dev = klass.new(name: 'arthurnn')
806
- dev.save!
807
- assert_equal 'dev:arthurnn', dev.reload.name
808
- end
809
-
810
- def test_global_methods_are_overwritten
811
- klass = Class.new(ActiveRecord::Base) do
812
- self.table_name = 'computers'
813
- end
814
-
815
- assert !klass.instance_method_already_implemented?(:system)
816
- computer = klass.new
817
- assert_nil computer.system
818
- end
819
-
820
- def test_global_methods_are_overwritten_when_subclassing
821
- klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
822
-
823
- subklass = Class.new(klass) do
824
- self.table_name = 'computers'
825
- end
826
-
827
- assert !klass.instance_method_already_implemented?(:system)
828
- assert !subklass.instance_method_already_implemented?(:system)
829
- computer = subklass.new
830
- assert_nil computer.system
831
- end
832
-
833
- def test_instance_method_should_be_defined_on_the_base_class
834
- subklass = Class.new(Topic)
835
-
836
- Topic.define_attribute_methods
837
-
838
- instance = subklass.new
839
- instance.id = 5
840
- assert_equal 5, instance.id
841
- assert subklass.method_defined?(:id), "subklass is missing id method"
842
-
843
- Topic.undefine_attribute_methods
844
-
845
- assert_equal 5, instance.id
846
- assert subklass.method_defined?(:id), "subklass is missing id method"
847
- end
848
-
849
- def test_read_attribute_with_nil_should_not_asplode
850
- assert_equal nil, Topic.new.read_attribute(nil)
851
- end
852
-
853
- # If B < A, and A defines an accessor for 'foo', we don't want to override
854
- # that by defining a 'foo' method in the generated methods module for B.
855
- # (That module will be inserted between the two, e.g. [B, <GeneratedAttributes>, A].)
856
- def test_inherited_custom_accessors
857
- klass = new_topic_like_ar_class do
858
- self.abstract_class = true
859
- def title; "omg"; end
860
- def title=(val); self.author_name = val; end
861
- end
862
- subklass = Class.new(klass)
863
- [klass, subklass].each(&:define_attribute_methods)
864
-
865
- topic = subklass.find(1)
866
- assert_equal "omg", topic.title
867
-
868
- topic.title = "lol"
869
- assert_equal "lol", topic.author_name
870
- end
871
-
872
- def test_inherited_custom_accessors_with_reserved_names
873
- klass = Class.new(ActiveRecord::Base) do
874
- self.table_name = 'computers'
875
- self.abstract_class = true
876
- def system; "omg"; end
877
- def system=(val); self.developer = val; end
878
- end
879
-
880
- subklass = Class.new(klass)
881
- [klass, subklass].each(&:define_attribute_methods)
882
-
883
- computer = subklass.find(1)
884
- assert_equal "omg", computer.system
885
-
886
- computer.developer = 99
887
- assert_equal 99, computer.developer
888
- end
889
-
890
- def test_on_the_fly_super_invokable_generated_attribute_methods_via_method_missing
891
- klass = new_topic_like_ar_class do
892
- def title
893
- super + '!'
894
- end
895
- end
896
-
897
- real_topic = topics(:first)
898
- assert_equal real_topic.title + '!', klass.find(real_topic.id).title
899
- end
900
-
901
- def test_on_the_fly_super_invokable_generated_predicate_attribute_methods_via_method_missing
902
- klass = new_topic_like_ar_class do
903
- def title?
904
- !super
905
- end
906
- end
907
-
908
- real_topic = topics(:first)
909
- assert_equal !real_topic.title?, klass.find(real_topic.id).title?
910
- end
911
-
912
- def test_calling_super_when_parent_does_not_define_method_raises_error
913
- klass = new_topic_like_ar_class do
914
- def some_method_that_is_not_on_super
915
- super
916
- end
917
- end
918
-
919
- assert_raise(NoMethodError) do
920
- klass.new.some_method_that_is_not_on_super
921
- end
922
- end
923
-
924
- def test_attribute_method?
925
- assert @target.attribute_method?(:title)
926
- assert @target.attribute_method?(:title=)
927
- assert_not @target.attribute_method?(:wibble)
928
- end
929
-
930
- def test_attribute_method_returns_false_if_table_does_not_exist
931
- @target.table_name = 'wibble'
932
- assert_not @target.attribute_method?(:title)
933
- end
934
-
935
- def test_attribute_names_on_new_record
936
- model = @target.new
937
-
938
- assert_equal @target.column_names, model.attribute_names
939
- end
940
-
941
- def test_attribute_names_on_queried_record
942
- model = @target.last!
943
-
944
- assert_equal @target.column_names, model.attribute_names
945
- end
946
-
947
- def test_attribute_names_with_custom_select
948
- model = @target.select('id').last!
949
-
950
- assert_equal ['id'], model.attribute_names
951
- # Sanity check, make sure other columns exist
952
- assert_not_equal ['id'], @target.column_names
953
- end
954
-
955
- def test_came_from_user
956
- model = @target.first
957
-
958
- assert_not model.id_came_from_user?
959
- model.id = "omg"
960
- assert model.id_came_from_user?
961
- end
962
-
963
- def test_accessed_fields
964
- model = @target.first
965
-
966
- assert_equal [], model.accessed_fields
967
-
968
- model.title
969
-
970
- assert_equal ["title"], model.accessed_fields
971
- end
972
-
973
- private
974
-
975
- def new_topic_like_ar_class(&block)
976
- klass = Class.new(ActiveRecord::Base) do
977
- self.table_name = 'topics'
978
- class_eval(&block)
979
- end
980
-
981
- assert_empty klass.generated_attribute_methods.instance_methods(false)
982
- klass
983
- end
984
-
985
- def with_time_zone_aware_types(*types)
986
- old_types = ActiveRecord::Base.time_zone_aware_types
987
- ActiveRecord::Base.time_zone_aware_types = types
988
- yield
989
- ensure
990
- ActiveRecord::Base.time_zone_aware_types = old_types
991
- end
992
-
993
- def cached_columns
994
- Topic.columns.map(&:name)
995
- end
996
-
997
- def time_related_columns_on_topic
998
- Topic.columns.select { |c| [:time, :date, :datetime, :timestamp].include?(c.type) }
999
- end
1000
-
1001
- def privatize(method_signature)
1002
- @target.class_eval(<<-private_method, __FILE__, __LINE__ + 1)
1003
- private
1004
- def #{method_signature}
1005
- "I'm private"
1006
- end
1007
- private_method
1008
- end
1009
- end
1
+ require "cases/helper"
2
+ require 'models/minimalistic'
3
+ require 'models/developer'
4
+ require 'models/auto_id'
5
+ require 'models/boolean'
6
+ require 'models/computer'
7
+ require 'models/topic'
8
+ require 'models/company'
9
+ require 'models/category'
10
+ require 'models/reply'
11
+ require 'models/contact'
12
+ require 'models/keyboard'
13
+
14
+ class AttributeMethodsTest < ActiveRecord::TestCase
15
+ include InTimeZone
16
+
17
+ fixtures :topics, :developers, :companies, :computers
18
+
19
+ def setup
20
+ @old_matchers = ActiveRecord::Base.send(:attribute_method_matchers).dup
21
+ @target = Class.new(ActiveRecord::Base)
22
+ @target.table_name = 'topics'
23
+ end
24
+
25
+ teardown do
26
+ ActiveRecord::Base.send(:attribute_method_matchers).clear
27
+ ActiveRecord::Base.send(:attribute_method_matchers).concat(@old_matchers)
28
+ end
29
+
30
+ def test_attribute_for_inspect_string
31
+ t = topics(:first)
32
+ t.title = "The First Topic Now Has A Title With\nNewlines And More Than 50 Characters"
33
+
34
+ assert_equal '"The First Topic Now Has A Title With\nNewlines And ..."', t.attribute_for_inspect(:title)
35
+ end
36
+
37
+ def test_attribute_for_inspect_date
38
+ t = topics(:first)
39
+
40
+ assert_equal %("#{t.written_on.to_s(:db)}"), t.attribute_for_inspect(:written_on)
41
+ end
42
+
43
+ def test_attribute_for_inspect_array
44
+ t = topics(:first)
45
+ t.content = [Object.new]
46
+
47
+ assert_match %r(\[#<Object:0x[0-9a-f]+>\]), t.attribute_for_inspect(:content)
48
+ end
49
+
50
+ def test_attribute_for_inspect_long_array
51
+ t = topics(:first)
52
+ t.content = (1..11).to_a
53
+
54
+ assert_equal "[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]", t.attribute_for_inspect(:content)
55
+ end
56
+
57
+ def test_attribute_present
58
+ t = Topic.new
59
+ t.title = "hello there!"
60
+ t.written_on = Time.now
61
+ t.author_name = ""
62
+ assert t.attribute_present?("title")
63
+ assert t.attribute_present?("written_on")
64
+ assert !t.attribute_present?("content")
65
+ assert !t.attribute_present?("author_name")
66
+ end
67
+
68
+ def test_attribute_present_with_booleans
69
+ b1 = Boolean.new
70
+ b1.value = false
71
+ assert b1.attribute_present?(:value)
72
+
73
+ b2 = Boolean.new
74
+ b2.value = true
75
+ assert b2.attribute_present?(:value)
76
+
77
+ b3 = Boolean.new
78
+ assert !b3.attribute_present?(:value)
79
+
80
+ b4 = Boolean.new
81
+ b4.value = false
82
+ b4.save!
83
+ assert Boolean.find(b4.id).attribute_present?(:value)
84
+ end
85
+
86
+ def test_caching_nil_primary_key
87
+ klass = Class.new(Minimalistic)
88
+ assert_called(klass, :reset_primary_key, returns: nil) do
89
+ 2.times { klass.primary_key }
90
+ end
91
+ end
92
+
93
+ def test_attribute_keys_on_new_instance
94
+ t = Topic.new
95
+ assert_equal nil, t.title, "The topics table has a title column, so it should be nil"
96
+ assert_raise(NoMethodError) { t.title2 }
97
+ end
98
+
99
+ def test_boolean_attributes
100
+ assert !Topic.find(1).approved?
101
+ assert Topic.find(2).approved?
102
+ end
103
+
104
+ def test_set_attributes
105
+ topic = Topic.find(1)
106
+ topic.attributes = { "title" => "Budget", "author_name" => "Jason" }
107
+ topic.save
108
+ assert_equal("Budget", topic.title)
109
+ assert_equal("Jason", topic.author_name)
110
+ assert_equal(topics(:first).author_email_address, Topic.find(1).author_email_address)
111
+ end
112
+
113
+ def test_set_attributes_without_hash
114
+ topic = Topic.new
115
+ assert_raise(ArgumentError) { topic.attributes = '' }
116
+ end
117
+
118
+ def test_integers_as_nil
119
+ test = AutoId.create('value' => '')
120
+ assert_nil AutoId.find(test.id).value
121
+ end
122
+
123
+ def test_set_attributes_with_block
124
+ topic = Topic.new do |t|
125
+ t.title = "Budget"
126
+ t.author_name = "Jason"
127
+ end
128
+
129
+ assert_equal("Budget", topic.title)
130
+ assert_equal("Jason", topic.author_name)
131
+ end
132
+
133
+ def test_respond_to?
134
+ topic = Topic.find(1)
135
+ assert_respond_to topic, "title"
136
+ assert_respond_to topic, "title?"
137
+ assert_respond_to topic, "title="
138
+ assert_respond_to topic, :title
139
+ assert_respond_to topic, :title?
140
+ assert_respond_to topic, :title=
141
+ assert_respond_to topic, "author_name"
142
+ assert_respond_to topic, "attribute_names"
143
+ assert !topic.respond_to?("nothingness")
144
+ assert !topic.respond_to?(:nothingness)
145
+ end
146
+
147
+ def test_respond_to_with_custom_primary_key
148
+ keyboard = Keyboard.create
149
+ assert_not_nil keyboard.key_number
150
+ assert_equal keyboard.key_number, keyboard.id
151
+ assert keyboard.respond_to?('key_number')
152
+ assert keyboard.respond_to?('id')
153
+ end
154
+
155
+ def test_id_before_type_cast_with_custom_primary_key
156
+ keyboard = Keyboard.create
157
+ keyboard.key_number = '10'
158
+ assert_equal '10', keyboard.id_before_type_cast
159
+ assert_equal nil, keyboard.read_attribute_before_type_cast('id')
160
+ assert_equal '10', keyboard.read_attribute_before_type_cast('key_number')
161
+ assert_equal '10', keyboard.read_attribute_before_type_cast(:key_number)
162
+ end
163
+
164
+ # Syck calls respond_to? before actually calling initialize
165
+ def test_respond_to_with_allocated_object
166
+ klass = Class.new(ActiveRecord::Base) do
167
+ self.table_name = 'topics'
168
+ end
169
+
170
+ topic = klass.allocate
171
+ assert !topic.respond_to?("nothingness")
172
+ assert !topic.respond_to?(:nothingness)
173
+ assert_respond_to topic, "title"
174
+ assert_respond_to topic, :title
175
+ end
176
+
177
+ # IRB inspects the return value of "MyModel.allocate".
178
+ def test_allocated_object_can_be_inspected
179
+ topic = Topic.allocate
180
+ assert_equal "#<Topic not initialized>", topic.inspect
181
+ end
182
+
183
+ def test_array_content
184
+ topic = Topic.new
185
+ topic.content = %w( one two three )
186
+ topic.save
187
+
188
+ assert_equal(%w( one two three ), Topic.find(topic.id).content)
189
+ end
190
+
191
+ def test_read_attributes_before_type_cast
192
+ category = Category.new({:name=>"Test category", :type => nil})
193
+ category_attrs = {"name"=>"Test category", "id" => nil, "type" => nil, "categorizations_count" => nil}
194
+ assert_equal category_attrs , category.attributes_before_type_cast
195
+ end
196
+
197
+ if current_adapter?(:Mysql2Adapter)
198
+ def test_read_attributes_before_type_cast_on_boolean
199
+ bool = Boolean.create!({ "value" => false })
200
+ if RUBY_PLATFORM =~ /java/
201
+ # JRuby will return the value before typecast as string
202
+ assert_equal "0", bool.reload.attributes_before_type_cast["value"]
203
+ else
204
+ assert_equal 0, bool.reload.attributes_before_type_cast["value"]
205
+ end
206
+ end
207
+ end
208
+
209
+ def test_read_attributes_before_type_cast_on_datetime
210
+ in_time_zone "Pacific Time (US & Canada)" do
211
+ record = @target.new
212
+
213
+ record.written_on = "345643456"
214
+ assert_equal "345643456", record.written_on_before_type_cast
215
+ assert_equal nil, record.written_on
216
+
217
+ record.written_on = "2009-10-11 12:13:14"
218
+ assert_equal "2009-10-11 12:13:14", record.written_on_before_type_cast
219
+ assert_equal Time.zone.parse("2009-10-11 12:13:14"), record.written_on
220
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
221
+ end
222
+ end
223
+
224
+ def test_read_attributes_after_type_cast_on_datetime
225
+ tz = "Pacific Time (US & Canada)"
226
+
227
+ in_time_zone tz do
228
+ record = @target.new
229
+
230
+ date_string = "2011-03-24"
231
+ time = Time.zone.parse date_string
232
+
233
+ record.written_on = date_string
234
+ assert_equal date_string, record.written_on_before_type_cast
235
+ assert_equal time, record.written_on
236
+ assert_equal ActiveSupport::TimeZone[tz], record.written_on.time_zone
237
+
238
+ record.save
239
+ record.reload
240
+
241
+ assert_equal time, record.written_on
242
+ end
243
+ end
244
+
245
+ def test_hash_content
246
+ topic = Topic.new
247
+ topic.content = { "one" => 1, "two" => 2 }
248
+ topic.save
249
+
250
+ assert_equal 2, Topic.find(topic.id).content["two"]
251
+
252
+ topic.content_will_change!
253
+ topic.content["three"] = 3
254
+ topic.save
255
+
256
+ assert_equal 3, Topic.find(topic.id).content["three"]
257
+ end
258
+
259
+ def test_update_array_content
260
+ topic = Topic.new
261
+ topic.content = %w( one two three )
262
+
263
+ topic.content.push "four"
264
+ assert_equal(%w( one two three four ), topic.content)
265
+
266
+ topic.save
267
+
268
+ topic = Topic.find(topic.id)
269
+ topic.content << "five"
270
+ assert_equal(%w( one two three four five ), topic.content)
271
+ end
272
+
273
+ def test_case_sensitive_attributes_hash
274
+ # DB2 is not case-sensitive
275
+ return true if current_adapter?(:DB2Adapter)
276
+
277
+ assert_equal @loaded_fixtures['computers']['workstation'].to_hash, Computer.first.attributes
278
+ end
279
+
280
+ def test_attributes_without_primary_key
281
+ klass = Class.new(ActiveRecord::Base) do
282
+ self.table_name = 'developers_projects'
283
+ end
284
+
285
+ assert_equal klass.column_names, klass.new.attributes.keys
286
+ assert_not klass.new.has_attribute?('id')
287
+ end
288
+
289
+ def test_hashes_not_mangled
290
+ new_topic = { :title => "New Topic" }
291
+ new_topic_values = { :title => "AnotherTopic" }
292
+
293
+ topic = Topic.new(new_topic)
294
+ assert_equal new_topic[:title], topic.title
295
+
296
+ topic.attributes= new_topic_values
297
+ assert_equal new_topic_values[:title], topic.title
298
+ end
299
+
300
+ def test_create_through_factory
301
+ topic = Topic.create("title" => "New Topic")
302
+ topicReloaded = Topic.find(topic.id)
303
+ assert_equal(topic, topicReloaded)
304
+ end
305
+
306
+ def test_write_attribute
307
+ topic = Topic.new
308
+ topic.send(:write_attribute, :title, "Still another topic")
309
+ assert_equal "Still another topic", topic.title
310
+
311
+ topic[:title] = "Still another topic: part 2"
312
+ assert_equal "Still another topic: part 2", topic.title
313
+
314
+ topic.send(:write_attribute, "title", "Still another topic: part 3")
315
+ assert_equal "Still another topic: part 3", topic.title
316
+
317
+ topic["title"] = "Still another topic: part 4"
318
+ assert_equal "Still another topic: part 4", topic.title
319
+ end
320
+
321
+ def test_read_attribute
322
+ topic = Topic.new
323
+ topic.title = "Don't change the topic"
324
+ assert_equal "Don't change the topic", topic.read_attribute("title")
325
+ assert_equal "Don't change the topic", topic["title"]
326
+
327
+ assert_equal "Don't change the topic", topic.read_attribute(:title)
328
+ assert_equal "Don't change the topic", topic[:title]
329
+ end
330
+
331
+ def test_read_attribute_raises_missing_attribute_error_when_not_exists
332
+ computer = Computer.select('id').first
333
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] }
334
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] }
335
+ assert_raises(ActiveModel::MissingAttributeError) { computer[:no_column_exists] = 'Hello!' }
336
+ assert_nothing_raised { computer[:developer] = 'Hello!' }
337
+ end
338
+
339
+ def test_read_attribute_when_false
340
+ topic = topics(:first)
341
+ topic.approved = false
342
+ assert !topic.approved?, "approved should be false"
343
+ topic.approved = "false"
344
+ assert !topic.approved?, "approved should be false"
345
+ end
346
+
347
+ def test_read_attribute_when_true
348
+ topic = topics(:first)
349
+ topic.approved = true
350
+ assert topic.approved?, "approved should be true"
351
+ topic.approved = "true"
352
+ assert topic.approved?, "approved should be true"
353
+ end
354
+
355
+ def test_read_write_boolean_attribute
356
+ topic = Topic.new
357
+ topic.approved = "false"
358
+ assert !topic.approved?, "approved should be false"
359
+
360
+ topic.approved = "false"
361
+ assert !topic.approved?, "approved should be false"
362
+
363
+ topic.approved = "true"
364
+ assert topic.approved?, "approved should be true"
365
+
366
+ topic.approved = "true"
367
+ assert topic.approved?, "approved should be true"
368
+ end
369
+
370
+ def test_overridden_write_attribute
371
+ topic = Topic.new
372
+ def topic.write_attribute(attr_name, value)
373
+ super(attr_name, value.downcase)
374
+ end
375
+
376
+ topic.send(:write_attribute, :title, "Yet another topic")
377
+ assert_equal "yet another topic", topic.title
378
+
379
+ topic[:title] = "Yet another topic: part 2"
380
+ assert_equal "yet another topic: part 2", topic.title
381
+
382
+ topic.send(:write_attribute, "title", "Yet another topic: part 3")
383
+ assert_equal "yet another topic: part 3", topic.title
384
+
385
+ topic["title"] = "Yet another topic: part 4"
386
+ assert_equal "yet another topic: part 4", topic.title
387
+ end
388
+
389
+ def test_overridden_read_attribute
390
+ topic = Topic.new
391
+ topic.title = "Stop changing the topic"
392
+ def topic.read_attribute(attr_name)
393
+ super(attr_name).upcase
394
+ end
395
+
396
+ assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute("title")
397
+ assert_equal "STOP CHANGING THE TOPIC", topic["title"]
398
+
399
+ assert_equal "STOP CHANGING THE TOPIC", topic.read_attribute(:title)
400
+ assert_equal "STOP CHANGING THE TOPIC", topic[:title]
401
+ end
402
+
403
+ def test_read_overridden_attribute
404
+ topic = Topic.new(:title => 'a')
405
+ def topic.title() 'b' end
406
+ assert_equal 'a', topic[:title]
407
+ end
408
+
409
+ def test_query_attribute_string
410
+ [nil, "", " "].each do |value|
411
+ assert_equal false, Topic.new(:author_name => value).author_name?
412
+ end
413
+
414
+ assert_equal true, Topic.new(:author_name => "Name").author_name?
415
+ end
416
+
417
+ def test_query_attribute_number
418
+ [nil, 0, "0"].each do |value|
419
+ assert_equal false, Developer.new(:salary => value).salary?
420
+ end
421
+
422
+ assert_equal true, Developer.new(:salary => 1).salary?
423
+ assert_equal true, Developer.new(:salary => "1").salary?
424
+ end
425
+
426
+ def test_query_attribute_boolean
427
+ [nil, "", false, "false", "f", 0].each do |value|
428
+ assert_equal false, Topic.new(:approved => value).approved?
429
+ end
430
+
431
+ [true, "true", "1", 1].each do |value|
432
+ assert_equal true, Topic.new(:approved => value).approved?
433
+ end
434
+ end
435
+
436
+ def test_query_attribute_with_custom_fields
437
+ object = Company.find_by_sql(<<-SQL).first
438
+ SELECT c1.*, c2.type as string_value, c2.rating as int_value
439
+ FROM companies c1, companies c2
440
+ WHERE c1.firm_id = c2.id
441
+ AND c1.id = 2
442
+ SQL
443
+
444
+ assert_equal "Firm", object.string_value
445
+ assert object.string_value?
446
+
447
+ object.string_value = " "
448
+ assert !object.string_value?
449
+
450
+ assert_equal 1, object.int_value.to_i
451
+ assert object.int_value?
452
+
453
+ object.int_value = "0"
454
+ assert !object.int_value?
455
+ end
456
+
457
+ def test_non_attribute_access_and_assignment
458
+ topic = Topic.new
459
+ assert !topic.respond_to?("mumbo")
460
+ assert_raise(NoMethodError) { topic.mumbo }
461
+ assert_raise(NoMethodError) { topic.mumbo = 5 }
462
+ end
463
+
464
+ def test_undeclared_attribute_method_does_not_affect_respond_to_and_method_missing
465
+ topic = @target.new(:title => 'Budget')
466
+ assert topic.respond_to?('title')
467
+ assert_equal 'Budget', topic.title
468
+ assert !topic.respond_to?('title_hello_world')
469
+ assert_raise(NoMethodError) { topic.title_hello_world }
470
+ end
471
+
472
+ def test_declared_prefixed_attribute_method_affects_respond_to_and_method_missing
473
+ topic = @target.new(:title => 'Budget')
474
+ %w(default_ title_).each do |prefix|
475
+ @target.class_eval "def #{prefix}attribute(*args) args end"
476
+ @target.attribute_method_prefix prefix
477
+
478
+ meth = "#{prefix}title"
479
+ assert topic.respond_to?(meth)
480
+ assert_equal ['title'], topic.send(meth)
481
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
482
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
483
+ end
484
+ end
485
+
486
+ def test_declared_suffixed_attribute_method_affects_respond_to_and_method_missing
487
+ %w(_default _title_default _it! _candidate= able?).each do |suffix|
488
+ @target.class_eval "def attribute#{suffix}(*args) args end"
489
+ @target.attribute_method_suffix suffix
490
+ topic = @target.new(:title => 'Budget')
491
+
492
+ meth = "title#{suffix}"
493
+ assert topic.respond_to?(meth)
494
+ assert_equal ['title'], topic.send(meth)
495
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
496
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
497
+ end
498
+ end
499
+
500
+ def test_declared_affixed_attribute_method_affects_respond_to_and_method_missing
501
+ [['mark_', '_for_update'], ['reset_', '!'], ['default_', '_value?']].each do |prefix, suffix|
502
+ @target.class_eval "def #{prefix}attribute#{suffix}(*args) args end"
503
+ @target.attribute_method_affix({ :prefix => prefix, :suffix => suffix })
504
+ topic = @target.new(:title => 'Budget')
505
+
506
+ meth = "#{prefix}title#{suffix}"
507
+ assert topic.respond_to?(meth)
508
+ assert_equal ['title'], topic.send(meth)
509
+ assert_equal ['title', 'a'], topic.send(meth, 'a')
510
+ assert_equal ['title', 1, 2, 3], topic.send(meth, 1, 2, 3)
511
+ end
512
+ end
513
+
514
+ def test_should_unserialize_attributes_for_frozen_records
515
+ myobj = {:value1 => :value2}
516
+ topic = Topic.create("content" => myobj)
517
+ topic.freeze
518
+ assert_equal myobj, topic.content
519
+ end
520
+
521
+ def test_typecast_attribute_from_select_to_false
522
+ Topic.create(:title => 'Budget')
523
+ # Oracle does not support boolean expressions in SELECT
524
+ if current_adapter?(:OracleAdapter, :FbAdapter)
525
+ topic = Topic.all.merge!(:select => "topics.*, 0 as is_test").first
526
+ else
527
+ topic = Topic.all.merge!(:select => "topics.*, 1=2 as is_test").first
528
+ end
529
+ assert !topic.is_test?
530
+ end
531
+
532
+ def test_typecast_attribute_from_select_to_true
533
+ Topic.create(:title => 'Budget')
534
+ # Oracle does not support boolean expressions in SELECT
535
+ if current_adapter?(:OracleAdapter, :FbAdapter)
536
+ topic = Topic.all.merge!(:select => "topics.*, 1 as is_test").first
537
+ else
538
+ topic = Topic.all.merge!(:select => "topics.*, 2=2 as is_test").first
539
+ end
540
+ assert topic.is_test?
541
+ end
542
+
543
+ def test_raises_dangerous_attribute_error_when_defining_activerecord_method_in_model
544
+ %w(save create_or_update).each do |method|
545
+ klass = Class.new ActiveRecord::Base
546
+ klass.class_eval "def #{method}() 'defined #{method}' end"
547
+ assert_raise ActiveRecord::DangerousAttributeError do
548
+ klass.instance_method_already_implemented?(method)
549
+ end
550
+ end
551
+ end
552
+
553
+ def test_converted_values_are_returned_after_assignment
554
+ developer = Developer.new(name: 1337, salary: "50000")
555
+
556
+ assert_equal "50000", developer.salary_before_type_cast
557
+ assert_equal 1337, developer.name_before_type_cast
558
+
559
+ assert_equal 50000, developer.salary
560
+ assert_equal "1337", developer.name
561
+
562
+ developer.save!
563
+
564
+ assert_equal 50000, developer.salary
565
+ assert_equal "1337", developer.name
566
+ end
567
+
568
+ def test_write_nil_to_time_attributes
569
+ in_time_zone "Pacific Time (US & Canada)" do
570
+ record = @target.new
571
+ record.written_on = nil
572
+ assert_nil record.written_on
573
+ end
574
+ end
575
+
576
+ def test_write_time_to_date_attributes
577
+ in_time_zone "Pacific Time (US & Canada)" do
578
+ record = @target.new
579
+ record.last_read = Time.utc(2010, 1, 1, 10)
580
+ assert_equal Date.civil(2010, 1, 1), record.last_read
581
+ end
582
+ end
583
+
584
+ def test_time_attributes_are_retrieved_in_current_time_zone
585
+ in_time_zone "Pacific Time (US & Canada)" do
586
+ utc_time = Time.utc(2008, 1, 1)
587
+ record = @target.new
588
+ record[:written_on] = utc_time
589
+ assert_equal utc_time, record.written_on # record.written on is equal to (i.e., simultaneous with) utc_time
590
+ assert_kind_of ActiveSupport::TimeWithZone, record.written_on # but is a TimeWithZone
591
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone # and is in the current Time.zone
592
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time # and represents time values adjusted accordingly
593
+ end
594
+ end
595
+
596
+ def test_setting_time_zone_aware_attribute_to_utc
597
+ in_time_zone "Pacific Time (US & Canada)" do
598
+ utc_time = Time.utc(2008, 1, 1)
599
+ record = @target.new
600
+ record.written_on = utc_time
601
+ assert_equal utc_time, record.written_on
602
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
603
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
604
+ end
605
+ end
606
+
607
+ def test_setting_time_zone_aware_attribute_in_other_time_zone
608
+ utc_time = Time.utc(2008, 1, 1)
609
+ cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
610
+ in_time_zone "Pacific Time (US & Canada)" do
611
+ record = @target.new
612
+ record.written_on = cst_time
613
+ assert_equal utc_time, record.written_on
614
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
615
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
616
+ end
617
+ end
618
+
619
+ def test_setting_time_zone_aware_read_attribute
620
+ utc_time = Time.utc(2008, 1, 1)
621
+ cst_time = utc_time.in_time_zone("Central Time (US & Canada)")
622
+ in_time_zone "Pacific Time (US & Canada)" do
623
+ record = @target.create(:written_on => cst_time).reload
624
+ assert_equal utc_time, record[:written_on]
625
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record[:written_on].time_zone
626
+ assert_equal Time.utc(2007, 12, 31, 16), record[:written_on].time
627
+ end
628
+ end
629
+
630
+ def test_setting_time_zone_aware_attribute_with_string
631
+ utc_time = Time.utc(2008, 1, 1)
632
+ (-11..13).each do |timezone_offset|
633
+ time_string = utc_time.in_time_zone(timezone_offset).to_s
634
+ in_time_zone "Pacific Time (US & Canada)" do
635
+ record = @target.new
636
+ record.written_on = time_string
637
+ assert_equal Time.zone.parse(time_string), record.written_on
638
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
639
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
640
+ end
641
+ end
642
+ end
643
+
644
+ def test_time_zone_aware_attribute_saved
645
+ in_time_zone 1 do
646
+ record = @target.create(:written_on => '2012-02-20 10:00')
647
+
648
+ record.written_on = '2012-02-20 09:00'
649
+ record.save
650
+ assert_equal Time.zone.local(2012, 02, 20, 9), record.reload.written_on
651
+ end
652
+ end
653
+
654
+ def test_setting_time_zone_aware_attribute_to_blank_string_returns_nil
655
+ in_time_zone "Pacific Time (US & Canada)" do
656
+ record = @target.new
657
+ record.written_on = ' '
658
+ assert_nil record.written_on
659
+ assert_nil record[:written_on]
660
+ end
661
+ end
662
+
663
+ def test_setting_time_zone_aware_attribute_interprets_time_zone_unaware_string_in_time_zone
664
+ time_string = 'Tue Jan 01 00:00:00 2008'
665
+ (-11..13).each do |timezone_offset|
666
+ in_time_zone timezone_offset do
667
+ record = @target.new
668
+ record.written_on = time_string
669
+ assert_equal Time.zone.parse(time_string), record.written_on
670
+ assert_equal ActiveSupport::TimeZone[timezone_offset], record.written_on.time_zone
671
+ assert_equal Time.utc(2008, 1, 1), record.written_on.time
672
+ end
673
+ end
674
+ end
675
+
676
+ def test_setting_time_zone_aware_datetime_in_current_time_zone
677
+ utc_time = Time.utc(2008, 1, 1)
678
+ in_time_zone "Pacific Time (US & Canada)" do
679
+ record = @target.new
680
+ record.written_on = utc_time.in_time_zone
681
+ assert_equal utc_time, record.written_on
682
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.written_on.time_zone
683
+ assert_equal Time.utc(2007, 12, 31, 16), record.written_on.time
684
+ end
685
+ end
686
+
687
+ def test_yaml_dumping_record_with_time_zone_aware_attribute
688
+ in_time_zone "Pacific Time (US & Canada)" do
689
+ record = Topic.new(id: 1)
690
+ record.written_on = "Jan 01 00:00:00 2014"
691
+ assert_equal record, YAML.load(YAML.dump(record))
692
+ end
693
+ end
694
+
695
+ def test_setting_time_zone_aware_time_in_current_time_zone
696
+ in_time_zone "Pacific Time (US & Canada)" do
697
+ record = @target.new
698
+ time_string = "10:00:00"
699
+ expected_time = Time.zone.parse("2000-01-01 #{time_string}")
700
+
701
+ record.bonus_time = time_string
702
+ assert_equal expected_time, record.bonus_time
703
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.bonus_time.time_zone
704
+
705
+ record.bonus_time = ''
706
+ assert_nil record.bonus_time
707
+ end
708
+ end
709
+
710
+ def test_setting_time_zone_aware_time_with_dst
711
+ in_time_zone "Pacific Time (US & Canada)" do
712
+ current_time = Time.zone.local(2014, 06, 15, 10)
713
+ record = @target.new(bonus_time: current_time)
714
+ time_before_save = record.bonus_time
715
+
716
+ record.save
717
+ record.reload
718
+
719
+ assert_equal time_before_save, record.bonus_time
720
+ assert_equal ActiveSupport::TimeZone["Pacific Time (US & Canada)"], record.bonus_time.time_zone
721
+ end
722
+ end
723
+
724
+ def test_removing_time_zone_aware_types
725
+ with_time_zone_aware_types(:datetime) do
726
+ in_time_zone "Pacific Time (US & Canada)" do
727
+ record = @target.new(bonus_time: "10:00:00")
728
+ expected_time = Time.utc(2000, 01, 01, 10)
729
+
730
+ assert_equal expected_time, record.bonus_time
731
+ assert record.bonus_time.utc?
732
+ end
733
+ end
734
+ end
735
+
736
+ def test_time_zone_aware_attributes_dont_recurse_infinitely_on_invalid_values
737
+ in_time_zone "Pacific Time (US & Canada)" do
738
+ record = @target.new(bonus_time: [])
739
+ assert_equal nil, record.bonus_time
740
+ end
741
+ end
742
+
743
+ def test_setting_time_zone_conversion_for_attributes_should_write_value_on_class_variable
744
+ Topic.skip_time_zone_conversion_for_attributes = [:field_a]
745
+ Minimalistic.skip_time_zone_conversion_for_attributes = [:field_b]
746
+
747
+ assert_equal [:field_a], Topic.skip_time_zone_conversion_for_attributes
748
+ assert_equal [:field_b], Minimalistic.skip_time_zone_conversion_for_attributes
749
+ end
750
+
751
+ def test_read_attributes_respect_access_control
752
+ privatize("title")
753
+
754
+ topic = @target.new(:title => "The pros and cons of programming naked.")
755
+ assert !topic.respond_to?(:title)
756
+ exception = assert_raise(NoMethodError) { topic.title }
757
+ assert exception.message.include?("private method")
758
+ assert_equal "I'm private", topic.send(:title)
759
+ end
760
+
761
+ def test_write_attributes_respect_access_control
762
+ privatize("title=(value)")
763
+
764
+ topic = @target.new
765
+ assert !topic.respond_to?(:title=)
766
+ exception = assert_raise(NoMethodError) { topic.title = "Pants"}
767
+ assert exception.message.include?("private method")
768
+ topic.send(:title=, "Very large pants")
769
+ end
770
+
771
+ def test_question_attributes_respect_access_control
772
+ privatize("title?")
773
+
774
+ topic = @target.new(:title => "Isaac Newton's pants")
775
+ assert !topic.respond_to?(:title?)
776
+ exception = assert_raise(NoMethodError) { topic.title? }
777
+ assert exception.message.include?("private method")
778
+ assert topic.send(:title?)
779
+ end
780
+
781
+ def test_bulk_update_respects_access_control
782
+ privatize("title=(value)")
783
+
784
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new(:title => "Rants about pants") }
785
+ assert_raise(ActiveRecord::UnknownAttributeError) { @target.new.attributes = { :title => "Ants in pants" } }
786
+ end
787
+
788
+ def test_bulk_update_raise_unknown_attribute_error
789
+ error = assert_raises(ActiveRecord::UnknownAttributeError) {
790
+ Topic.new(hello: "world")
791
+ }
792
+ assert_instance_of Topic, error.record
793
+ assert_equal "hello", error.attribute
794
+ assert_equal "unknown attribute 'hello' for Topic.", error.message
795
+ end
796
+
797
+ def test_methods_override_in_multi_level_subclass
798
+ klass = Class.new(Developer) do
799
+ def name
800
+ "dev:#{read_attribute(:name)}"
801
+ end
802
+ end
803
+
804
+ 2.times { klass = Class.new klass }
805
+ dev = klass.new(name: 'arthurnn')
806
+ dev.save!
807
+ assert_equal 'dev:arthurnn', dev.reload.name
808
+ end
809
+
810
+ def test_global_methods_are_overwritten
811
+ klass = Class.new(ActiveRecord::Base) do
812
+ self.table_name = 'computers'
813
+ end
814
+
815
+ assert !klass.instance_method_already_implemented?(:system)
816
+ computer = klass.new
817
+ assert_nil computer.system
818
+ end
819
+
820
+ def test_global_methods_are_overwritten_when_subclassing
821
+ klass = Class.new(ActiveRecord::Base) { self.abstract_class = true }
822
+
823
+ subklass = Class.new(klass) do
824
+ self.table_name = 'computers'
825
+ end
826
+
827
+ assert !klass.instance_method_already_implemented?(:system)
828
+ assert !subklass.instance_method_already_implemented?(:system)
829
+ computer = subklass.new
830
+ assert_nil computer.system
831
+ end
832
+
833
+ def test_instance_method_should_be_defined_on_the_base_class
834
+ subklass = Class.new(Topic)
835
+
836
+ Topic.define_attribute_methods
837
+
838
+ instance = subklass.new
839
+ instance.id = 5
840
+ assert_equal 5, instance.id
841
+ assert subklass.method_defined?(:id), "subklass is missing id method"
842
+
843
+ Topic.undefine_attribute_methods
844
+
845
+ assert_equal 5, instance.id
846
+ assert subklass.method_defined?(:id), "subklass is missing id method"
847
+ end
848
+
849
+ def test_read_attribute_with_nil_should_not_asplode
850
+ assert_equal nil, Topic.new.read_attribute(nil)
851
+ end
852
+
853
+ # If B < A, and A defines an accessor for 'foo', we don't want to override
854
+ # that by defining a 'foo' method in the generated methods module for B.
855
+ # (That module will be inserted between the two, e.g. [B, <GeneratedAttributes>, A].)
856
+ def test_inherited_custom_accessors
857
+ klass = new_topic_like_ar_class do
858
+ self.abstract_class = true
859
+ def title; "omg"; end
860
+ def title=(val); self.author_name = val; end
861
+ end
862
+ subklass = Class.new(klass)
863
+ [klass, subklass].each(&:define_attribute_methods)
864
+
865
+ topic = subklass.find(1)
866
+ assert_equal "omg", topic.title
867
+
868
+ topic.title = "lol"
869
+ assert_equal "lol", topic.author_name
870
+ end
871
+
872
+ def test_inherited_custom_accessors_with_reserved_names
873
+ klass = Class.new(ActiveRecord::Base) do
874
+ self.table_name = 'computers'
875
+ self.abstract_class = true
876
+ def system; "omg"; end
877
+ def system=(val); self.developer = val; end
878
+ end
879
+
880
+ subklass = Class.new(klass)
881
+ [klass, subklass].each(&:define_attribute_methods)
882
+
883
+ computer = subklass.find(1)
884
+ assert_equal "omg", computer.system
885
+
886
+ computer.developer = 99
887
+ assert_equal 99, computer.developer
888
+ end
889
+
890
+ def test_on_the_fly_super_invokable_generated_attribute_methods_via_method_missing
891
+ klass = new_topic_like_ar_class do
892
+ def title
893
+ super + '!'
894
+ end
895
+ end
896
+
897
+ real_topic = topics(:first)
898
+ assert_equal real_topic.title + '!', klass.find(real_topic.id).title
899
+ end
900
+
901
+ def test_on_the_fly_super_invokable_generated_predicate_attribute_methods_via_method_missing
902
+ klass = new_topic_like_ar_class do
903
+ def title?
904
+ !super
905
+ end
906
+ end
907
+
908
+ real_topic = topics(:first)
909
+ assert_equal !real_topic.title?, klass.find(real_topic.id).title?
910
+ end
911
+
912
+ def test_calling_super_when_parent_does_not_define_method_raises_error
913
+ klass = new_topic_like_ar_class do
914
+ def some_method_that_is_not_on_super
915
+ super
916
+ end
917
+ end
918
+
919
+ assert_raise(NoMethodError) do
920
+ klass.new.some_method_that_is_not_on_super
921
+ end
922
+ end
923
+
924
+ def test_attribute_method?
925
+ assert @target.attribute_method?(:title)
926
+ assert @target.attribute_method?(:title=)
927
+ assert_not @target.attribute_method?(:wibble)
928
+ end
929
+
930
+ def test_attribute_method_returns_false_if_table_does_not_exist
931
+ @target.table_name = 'wibble'
932
+ assert_not @target.attribute_method?(:title)
933
+ end
934
+
935
+ def test_attribute_names_on_new_record
936
+ model = @target.new
937
+
938
+ assert_equal @target.column_names, model.attribute_names
939
+ end
940
+
941
+ def test_attribute_names_on_queried_record
942
+ model = @target.last!
943
+
944
+ assert_equal @target.column_names, model.attribute_names
945
+ end
946
+
947
+ def test_attribute_names_with_custom_select
948
+ model = @target.select('id').last!
949
+
950
+ assert_equal ['id'], model.attribute_names
951
+ # Sanity check, make sure other columns exist
952
+ assert_not_equal ['id'], @target.column_names
953
+ end
954
+
955
+ def test_came_from_user
956
+ model = @target.first
957
+
958
+ assert_not model.id_came_from_user?
959
+ model.id = "omg"
960
+ assert model.id_came_from_user?
961
+ end
962
+
963
+ def test_accessed_fields
964
+ model = @target.first
965
+
966
+ assert_equal [], model.accessed_fields
967
+
968
+ model.title
969
+
970
+ assert_equal ["title"], model.accessed_fields
971
+ end
972
+
973
+ private
974
+
975
+ def new_topic_like_ar_class(&block)
976
+ klass = Class.new(ActiveRecord::Base) do
977
+ self.table_name = 'topics'
978
+ class_eval(&block)
979
+ end
980
+
981
+ assert_empty klass.generated_attribute_methods.instance_methods(false)
982
+ klass
983
+ end
984
+
985
+ def with_time_zone_aware_types(*types)
986
+ old_types = ActiveRecord::Base.time_zone_aware_types
987
+ ActiveRecord::Base.time_zone_aware_types = types
988
+ yield
989
+ ensure
990
+ ActiveRecord::Base.time_zone_aware_types = old_types
991
+ end
992
+
993
+ def cached_columns
994
+ Topic.columns.map(&:name)
995
+ end
996
+
997
+ def time_related_columns_on_topic
998
+ Topic.columns.select { |c| [:time, :date, :datetime, :timestamp].include?(c.type) }
999
+ end
1000
+
1001
+ def privatize(method_signature)
1002
+ @target.class_eval(<<-private_method, __FILE__, __LINE__ + 1)
1003
+ private
1004
+ def #{method_signature}
1005
+ "I'm private"
1006
+ end
1007
+ private_method
1008
+ end
1009
+ end