ibm_db 3.0.5-x86-mingw32 → 4.0.0-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 (586) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/LICENSE +1 -1
  4. data/MANIFEST +14 -14
  5. data/ParameterizedQueries README +6 -6
  6. data/README +208 -225
  7. data/ext/Makefile.nt32 +181 -181
  8. data/ext/Makefile.nt32.191 +212 -212
  9. data/ext/extconf.rb +291 -291
  10. data/ext/ibm_db.c +11887 -11887
  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/init.rb +41 -41
  15. data/lib/IBM_DB.rb +27 -27
  16. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
  17. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
  18. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  19. data/lib/mswin32/ibm_db.rb +91 -123
  20. data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
  21. data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
  22. data/test/assets/example.log +1 -1
  23. data/test/assets/test.txt +1 -1
  24. data/test/cases/adapter_test.rb +351 -276
  25. data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
  26. data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
  27. data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
  28. data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
  29. data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
  30. data/test/cases/adapters/mysql2/connection_test.rb +210 -0
  31. data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
  32. data/test/cases/adapters/mysql2/enum_test.rb +26 -0
  33. data/test/cases/adapters/mysql2/explain_test.rb +21 -0
  34. data/test/cases/adapters/mysql2/json_test.rb +195 -0
  35. data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
  36. data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
  37. data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
  38. data/test/cases/adapters/mysql2/schema_test.rb +126 -0
  39. data/test/cases/adapters/mysql2/sp_test.rb +36 -0
  40. data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
  41. data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
  42. data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
  43. data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
  44. data/test/cases/adapters/postgresql/array_test.rb +339 -0
  45. data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
  46. data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
  47. data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
  48. data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
  49. data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
  50. data/test/cases/adapters/postgresql/citext_test.rb +78 -0
  51. data/test/cases/adapters/postgresql/collation_test.rb +53 -0
  52. data/test/cases/adapters/postgresql/composite_test.rb +132 -0
  53. data/test/cases/adapters/postgresql/connection_test.rb +257 -0
  54. data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
  55. data/test/cases/adapters/postgresql/domain_test.rb +47 -0
  56. data/test/cases/adapters/postgresql/enum_test.rb +91 -0
  57. data/test/cases/adapters/postgresql/explain_test.rb +20 -0
  58. data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
  59. data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
  60. data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
  61. data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
  62. data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
  63. data/test/cases/adapters/postgresql/integer_test.rb +25 -0
  64. data/test/cases/adapters/postgresql/json_test.rb +237 -0
  65. data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
  66. data/test/cases/adapters/postgresql/money_test.rb +96 -0
  67. data/test/cases/adapters/postgresql/network_test.rb +94 -0
  68. data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
  69. data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
  70. data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
  71. data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
  72. data/test/cases/adapters/postgresql/range_test.rb +343 -0
  73. data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
  74. data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
  75. data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
  76. data/test/cases/adapters/postgresql/schema_test.rb +597 -0
  77. data/test/cases/adapters/postgresql/serial_test.rb +154 -0
  78. data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
  79. data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
  80. data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
  81. data/test/cases/adapters/postgresql/utils_test.rb +62 -0
  82. data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
  83. data/test/cases/adapters/postgresql/xml_test.rb +54 -0
  84. data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
  85. data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
  86. data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
  87. data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
  88. data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
  89. data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
  90. data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
  91. data/test/cases/aggregations_test.rb +168 -158
  92. data/test/cases/ar_schema_test.rb +146 -161
  93. data/test/cases/associations/association_scope_test.rb +16 -21
  94. data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
  95. data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
  96. data/test/cases/associations/callbacks_test.rb +190 -192
  97. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
  98. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
  99. data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
  100. data/test/cases/associations/eager_singularization_test.rb +148 -148
  101. data/test/cases/associations/eager_test.rb +1514 -1429
  102. data/test/cases/associations/extension_test.rb +87 -82
  103. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
  104. data/test/cases/associations/has_many_associations_test.rb +2501 -2182
  105. data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
  106. data/test/cases/associations/has_one_associations_test.rb +707 -610
  107. data/test/cases/associations/has_one_through_associations_test.rb +383 -380
  108. data/test/cases/associations/inner_join_association_test.rb +139 -139
  109. data/test/cases/associations/inverse_associations_test.rb +733 -706
  110. data/test/cases/associations/join_model_test.rb +777 -754
  111. data/test/cases/associations/left_outer_join_association_test.rb +88 -0
  112. data/test/cases/associations/nested_through_associations_test.rb +579 -579
  113. data/test/cases/associations/required_test.rb +102 -82
  114. data/test/cases/associations_test.rb +385 -380
  115. data/test/cases/attribute_decorators_test.rb +125 -125
  116. data/test/cases/attribute_methods/read_test.rb +60 -60
  117. data/test/cases/attribute_methods_test.rb +1009 -952
  118. data/test/cases/attribute_set_test.rb +270 -210
  119. data/test/cases/attribute_test.rb +246 -180
  120. data/test/cases/attributes_test.rb +253 -136
  121. data/test/cases/autosave_association_test.rb +1708 -1595
  122. data/test/cases/base_test.rb +1713 -1664
  123. data/test/cases/batches_test.rb +489 -212
  124. data/test/cases/binary_test.rb +44 -52
  125. data/test/cases/bind_parameter_test.rb +110 -100
  126. data/test/cases/cache_key_test.rb +25 -0
  127. data/test/cases/calculations_test.rb +798 -646
  128. data/test/cases/callbacks_test.rb +636 -543
  129. data/test/cases/clone_test.rb +40 -40
  130. data/test/cases/coders/json_test.rb +15 -0
  131. data/test/cases/coders/yaml_column_test.rb +63 -63
  132. data/test/cases/collection_cache_key_test.rb +115 -0
  133. data/test/cases/column_alias_test.rb +17 -17
  134. data/test/cases/column_definition_test.rb +92 -123
  135. data/test/cases/comment_test.rb +143 -0
  136. data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
  137. data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
  138. data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
  139. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
  140. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
  141. data/test/cases/connection_adapters/quoting_test.rb +13 -13
  142. data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
  143. data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
  144. data/test/cases/connection_management_test.rb +112 -122
  145. data/test/cases/connection_pool_test.rb +521 -346
  146. data/test/cases/connection_specification/resolver_test.rb +131 -116
  147. data/test/cases/core_test.rb +112 -112
  148. data/test/cases/counter_cache_test.rb +214 -209
  149. data/test/cases/custom_locking_test.rb +17 -17
  150. data/test/cases/database_statements_test.rb +34 -19
  151. data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
  152. data/test/cases/date_time_precision_test.rb +106 -0
  153. data/test/cases/date_time_test.rb +61 -61
  154. data/test/cases/defaults_test.rb +218 -223
  155. data/test/cases/dirty_test.rb +763 -785
  156. data/test/cases/disconnected_test.rb +30 -28
  157. data/test/cases/dup_test.rb +157 -157
  158. data/test/cases/enum_test.rb +444 -290
  159. data/test/cases/errors_test.rb +16 -0
  160. data/test/cases/explain_subscriber_test.rb +64 -64
  161. data/test/cases/explain_test.rb +87 -76
  162. data/test/cases/finder_respond_to_test.rb +60 -60
  163. data/test/cases/finder_test.rb +1294 -1169
  164. data/test/cases/fixture_set/file_test.rb +156 -138
  165. data/test/cases/fixtures_test.rb +988 -908
  166. data/test/cases/forbidden_attributes_protection_test.rb +165 -99
  167. data/test/cases/habtm_destroy_order_test.rb +61 -61
  168. data/test/cases/helper.rb +204 -210
  169. data/test/cases/hot_compatibility_test.rb +142 -54
  170. data/test/cases/i18n_test.rb +45 -45
  171. data/test/cases/inheritance_test.rb +606 -375
  172. data/test/cases/integration_test.rb +155 -139
  173. data/test/cases/invalid_connection_test.rb +24 -22
  174. data/test/cases/invertible_migration_test.rb +387 -295
  175. data/test/cases/json_serialization_test.rb +311 -302
  176. data/test/cases/locking_test.rb +493 -477
  177. data/test/cases/log_subscriber_test.rb +225 -136
  178. data/test/cases/migration/change_schema_test.rb +458 -512
  179. data/test/cases/migration/change_table_test.rb +256 -224
  180. data/test/cases/migration/column_attributes_test.rb +176 -192
  181. data/test/cases/migration/column_positioning_test.rb +56 -56
  182. data/test/cases/migration/columns_test.rb +310 -304
  183. data/test/cases/migration/command_recorder_test.rb +350 -305
  184. data/test/cases/migration/compatibility_test.rb +118 -0
  185. data/test/cases/migration/create_join_table_test.rb +157 -148
  186. data/test/cases/migration/foreign_key_test.rb +360 -328
  187. data/test/cases/migration/helper.rb +39 -39
  188. data/test/cases/migration/index_test.rb +218 -216
  189. data/test/cases/migration/logger_test.rb +36 -36
  190. data/test/cases/migration/pending_migrations_test.rb +52 -53
  191. data/test/cases/migration/references_foreign_key_test.rb +216 -169
  192. data/test/cases/migration/references_index_test.rb +101 -101
  193. data/test/cases/migration/references_statements_test.rb +136 -116
  194. data/test/cases/migration/rename_table_test.rb +93 -93
  195. data/test/cases/migration_test.rb +1157 -959
  196. data/test/cases/migrator_test.rb +470 -388
  197. data/test/cases/mixin_test.rb +68 -70
  198. data/test/cases/modules_test.rb +172 -173
  199. data/test/cases/multiparameter_attributes_test.rb +372 -350
  200. data/test/cases/multiple_db_test.rb +122 -115
  201. data/test/cases/nested_attributes_test.rb +1098 -1070
  202. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
  203. data/test/cases/persistence_test.rb +1001 -909
  204. data/test/cases/pooled_connections_test.rb +81 -81
  205. data/test/cases/primary_keys_test.rb +376 -237
  206. data/test/cases/query_cache_test.rb +446 -326
  207. data/test/cases/quoting_test.rb +202 -156
  208. data/test/cases/readonly_test.rb +119 -118
  209. data/test/cases/reaper_test.rb +85 -85
  210. data/test/cases/reflection_test.rb +509 -463
  211. data/test/cases/relation/delegation_test.rb +63 -68
  212. data/test/cases/relation/merging_test.rb +157 -161
  213. data/test/cases/relation/mutation_test.rb +183 -165
  214. data/test/cases/relation/or_test.rb +92 -0
  215. data/test/cases/relation/predicate_builder_test.rb +16 -14
  216. data/test/cases/relation/record_fetch_warning_test.rb +40 -0
  217. data/test/cases/relation/where_chain_test.rb +105 -181
  218. data/test/cases/relation/where_clause_test.rb +182 -0
  219. data/test/cases/relation/where_test.rb +322 -300
  220. data/test/cases/relation_test.rb +328 -319
  221. data/test/cases/relations_test.rb +2026 -1815
  222. data/test/cases/reload_models_test.rb +22 -22
  223. data/test/cases/result_test.rb +90 -80
  224. data/test/cases/sanitize_test.rb +176 -83
  225. data/test/cases/schema_dumper_test.rb +457 -463
  226. data/test/cases/schema_loading_test.rb +52 -0
  227. data/test/cases/scoping/default_scoping_test.rb +528 -454
  228. data/test/cases/scoping/named_scoping_test.rb +561 -524
  229. data/test/cases/scoping/relation_scoping_test.rb +400 -357
  230. data/test/cases/secure_token_test.rb +32 -0
  231. data/test/cases/serialization_test.rb +104 -104
  232. data/test/cases/serialized_attribute_test.rb +364 -277
  233. data/test/cases/statement_cache_test.rb +136 -98
  234. data/test/cases/store_test.rb +195 -194
  235. data/test/cases/suppressor_test.rb +63 -0
  236. data/test/cases/tasks/database_tasks_test.rb +462 -398
  237. data/test/cases/tasks/mysql_rake_test.rb +345 -324
  238. data/test/cases/tasks/postgresql_rake_test.rb +304 -250
  239. data/test/cases/tasks/sqlite_rake_test.rb +220 -193
  240. data/test/cases/test_case.rb +131 -123
  241. data/test/cases/test_fixtures_test.rb +36 -0
  242. data/test/cases/time_precision_test.rb +102 -0
  243. data/test/cases/timestamp_test.rb +501 -467
  244. data/test/cases/touch_later_test.rb +121 -0
  245. data/test/cases/transaction_callbacks_test.rb +518 -452
  246. data/test/cases/transaction_isolation_test.rb +106 -106
  247. data/test/cases/transactions_test.rb +834 -817
  248. data/test/cases/type/adapter_specific_registry_test.rb +133 -0
  249. data/test/cases/type/date_time_test.rb +14 -0
  250. data/test/cases/type/integer_test.rb +27 -121
  251. data/test/cases/type/string_test.rb +22 -36
  252. data/test/cases/type/type_map_test.rb +177 -177
  253. data/test/cases/type_test.rb +39 -0
  254. data/test/cases/types_test.rb +24 -141
  255. data/test/cases/unconnected_test.rb +33 -33
  256. data/test/cases/validations/absence_validation_test.rb +73 -0
  257. data/test/cases/validations/association_validation_test.rb +97 -86
  258. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
  259. data/test/cases/validations/i18n_validation_test.rb +86 -90
  260. data/test/cases/validations/length_validation_test.rb +79 -47
  261. data/test/cases/validations/presence_validation_test.rb +103 -68
  262. data/test/cases/validations/uniqueness_validation_test.rb +548 -457
  263. data/test/cases/validations_repair_helper.rb +19 -23
  264. data/test/cases/validations_test.rb +194 -165
  265. data/test/cases/view_test.rb +216 -119
  266. data/test/cases/yaml_serialization_test.rb +121 -126
  267. data/test/config.example.yml +97 -0
  268. data/test/config.rb +5 -5
  269. data/test/fixtures/accounts.yml +29 -29
  270. data/test/fixtures/admin/accounts.yml +2 -2
  271. data/test/fixtures/admin/users.yml +10 -10
  272. data/test/fixtures/author_addresses.original +11 -0
  273. data/test/fixtures/author_addresses.yml +17 -17
  274. data/test/fixtures/author_favorites.yml +3 -3
  275. data/test/fixtures/authors.original +17 -0
  276. data/test/fixtures/authors.yml +23 -23
  277. data/test/fixtures/bad_posts.yml +9 -0
  278. data/test/fixtures/binaries.yml +133 -133
  279. data/test/fixtures/books.yml +31 -11
  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 -0
  295. data/test/fixtures/content_positions.yml +3 -0
  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 -0
  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 -0
  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 -0
  333. data/test/fixtures/naked/yml/trees.yml +3 -0
  334. data/test/fixtures/nodes.yml +29 -0
  335. data/test/fixtures/organizations.yml +5 -5
  336. data/test/fixtures/other_comments.yml +6 -0
  337. data/test/fixtures/other_dogs.yml +2 -0
  338. data/test/fixtures/other_posts.yml +7 -0
  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 +15 -12
  347. data/test/fixtures/posts.yml +80 -80
  348. data/test/fixtures/price_estimates.yml +16 -7
  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 -0
  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/randomly_named_c1.rb +6 -2
  414. data/test/models/admin/user.rb +40 -40
  415. data/test/models/aircraft.rb +5 -4
  416. data/test/models/arunit2_model.rb +3 -3
  417. data/test/models/author.rb +209 -212
  418. data/test/models/auto_id.rb +4 -4
  419. data/test/models/autoloadable/extra_firm.rb +2 -2
  420. data/test/models/binary.rb +2 -2
  421. data/test/models/bird.rb +12 -12
  422. data/test/models/book.rb +23 -18
  423. data/test/models/boolean.rb +2 -2
  424. data/test/models/bulb.rb +52 -51
  425. data/test/models/cake_designer.rb +3 -3
  426. data/test/models/car.rb +29 -26
  427. data/test/models/carrier.rb +2 -2
  428. data/test/models/cat.rb +10 -0
  429. data/test/models/categorization.rb +19 -19
  430. data/test/models/category.rb +35 -35
  431. data/test/models/chef.rb +8 -7
  432. data/test/models/citation.rb +3 -3
  433. data/test/models/club.rb +25 -23
  434. data/test/models/college.rb +10 -10
  435. data/test/models/column.rb +3 -3
  436. data/test/models/column_name.rb +3 -3
  437. data/test/models/comment.rb +76 -64
  438. data/test/models/company.rb +230 -228
  439. data/test/models/company_in_module.rb +98 -98
  440. data/test/models/computer.rb +3 -3
  441. data/test/models/contact.rb +41 -41
  442. data/test/models/content.rb +40 -0
  443. data/test/models/contract.rb +20 -20
  444. data/test/models/country.rb +7 -7
  445. data/test/models/course.rb +6 -6
  446. data/test/models/customer.rb +83 -77
  447. data/test/models/customer_carrier.rb +14 -14
  448. data/test/models/dashboard.rb +3 -3
  449. data/test/models/default.rb +2 -2
  450. data/test/models/department.rb +4 -4
  451. data/test/models/developer.rb +274 -255
  452. data/test/models/dog.rb +5 -5
  453. data/test/models/dog_lover.rb +5 -5
  454. data/test/models/doubloon.rb +12 -12
  455. data/test/models/drink_designer.rb +3 -3
  456. data/test/models/edge.rb +5 -5
  457. data/test/models/electron.rb +5 -5
  458. data/test/models/engine.rb +4 -4
  459. data/test/models/entrant.rb +3 -3
  460. data/test/models/essay.rb +5 -5
  461. data/test/models/event.rb +3 -3
  462. data/test/models/eye.rb +37 -37
  463. data/test/models/face.rb +9 -9
  464. data/test/models/friendship.rb +6 -6
  465. data/test/models/guid.rb +2 -2
  466. data/test/models/guitar.rb +4 -0
  467. data/test/models/hotel.rb +11 -9
  468. data/test/models/image.rb +3 -3
  469. data/test/models/interest.rb +5 -5
  470. data/test/models/invoice.rb +4 -4
  471. data/test/models/item.rb +7 -7
  472. data/test/models/job.rb +7 -7
  473. data/test/models/joke.rb +7 -7
  474. data/test/models/keyboard.rb +3 -3
  475. data/test/models/legacy_thing.rb +3 -3
  476. data/test/models/lesson.rb +11 -11
  477. data/test/models/line_item.rb +3 -3
  478. data/test/models/liquid.rb +4 -4
  479. data/test/models/man.rb +11 -11
  480. data/test/models/matey.rb +4 -4
  481. data/test/models/member.rb +42 -41
  482. data/test/models/member_detail.rb +8 -7
  483. data/test/models/member_type.rb +3 -3
  484. data/test/models/membership.rb +35 -35
  485. data/test/models/mentor.rb +3 -0
  486. data/test/models/minimalistic.rb +2 -2
  487. data/test/models/minivan.rb +9 -9
  488. data/test/models/mixed_case_monkey.rb +3 -3
  489. data/test/models/mocktail_designer.rb +2 -0
  490. data/test/models/molecule.rb +6 -6
  491. data/test/models/movie.rb +5 -5
  492. data/test/models/node.rb +5 -0
  493. data/test/models/non_primary_key.rb +2 -0
  494. data/test/models/notification.rb +3 -0
  495. data/test/models/order.rb +4 -4
  496. data/test/models/organization.rb +14 -14
  497. data/test/models/other_dog.rb +5 -0
  498. data/test/models/owner.rb +37 -34
  499. data/test/models/parrot.rb +28 -29
  500. data/test/models/person.rb +142 -143
  501. data/test/models/personal_legacy_thing.rb +4 -4
  502. data/test/models/pet.rb +18 -15
  503. data/test/models/pet_treasure.rb +6 -0
  504. data/test/models/pirate.rb +92 -92
  505. data/test/models/possession.rb +3 -3
  506. data/test/models/post.rb +273 -264
  507. data/test/models/price_estimate.rb +4 -4
  508. data/test/models/professor.rb +5 -5
  509. data/test/models/project.rb +40 -31
  510. data/test/models/publisher.rb +2 -2
  511. data/test/models/publisher/article.rb +4 -4
  512. data/test/models/publisher/magazine.rb +3 -3
  513. data/test/models/randomly_named_c1.rb +1 -1
  514. data/test/models/rating.rb +4 -4
  515. data/test/models/reader.rb +23 -23
  516. data/test/models/recipe.rb +3 -0
  517. data/test/models/record.rb +2 -2
  518. data/test/models/reference.rb +22 -22
  519. data/test/models/reply.rb +61 -61
  520. data/test/models/ship.rb +39 -33
  521. data/test/models/ship_part.rb +8 -8
  522. data/test/models/shop.rb +17 -17
  523. data/test/models/shop_account.rb +6 -6
  524. data/test/models/speedometer.rb +6 -6
  525. data/test/models/sponsor.rb +7 -7
  526. data/test/models/string_key_object.rb +3 -3
  527. data/test/models/student.rb +4 -4
  528. data/test/models/subject.rb +16 -16
  529. data/test/models/subscriber.rb +8 -8
  530. data/test/models/subscription.rb +4 -4
  531. data/test/models/tag.rb +13 -7
  532. data/test/models/tagging.rb +13 -13
  533. data/test/models/task.rb +5 -5
  534. data/test/models/topic.rb +118 -124
  535. data/test/models/toy.rb +6 -6
  536. data/test/models/traffic_light.rb +4 -4
  537. data/test/models/treasure.rb +14 -14
  538. data/test/models/treaty.rb +7 -7
  539. data/test/models/tree.rb +3 -0
  540. data/test/models/tuning_peg.rb +4 -0
  541. data/test/models/tyre.rb +11 -11
  542. data/test/models/user.rb +14 -0
  543. data/test/models/uuid_child.rb +3 -3
  544. data/test/models/uuid_item.rb +6 -0
  545. data/test/models/uuid_parent.rb +3 -3
  546. data/test/models/vegetables.rb +24 -24
  547. data/test/models/vehicle.rb +6 -6
  548. data/test/models/vertex.rb +9 -9
  549. data/test/models/warehouse_thing.rb +5 -5
  550. data/test/models/wheel.rb +3 -3
  551. data/test/models/without_table.rb +3 -3
  552. data/test/models/zine.rb +3 -3
  553. data/test/schema/mysql2_specific_schema.rb +68 -58
  554. data/test/schema/oracle_specific_schema.rb +40 -43
  555. data/test/schema/postgresql_specific_schema.rb +114 -202
  556. data/test/schema/schema.rb +1057 -952
  557. data/test/schema/schema.rb.original +1057 -0
  558. data/test/schema/sqlite_specific_schema.rb +18 -22
  559. data/test/support/config.rb +43 -43
  560. data/test/support/connection.rb +23 -22
  561. data/test/support/connection_helper.rb +14 -14
  562. data/test/support/ddl_helper.rb +8 -8
  563. data/test/support/schema_dumping_helper.rb +20 -20
  564. data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
  565. data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
  566. metadata +129 -28
  567. data/lib/mswin32/rb19x/ibm_db.so +0 -0
  568. data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
  569. data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
  570. data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
  571. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
  572. data/test/cases/attribute_methods/serialization_test.rb +0 -29
  573. data/test/cases/migration/change_schema_test - Copy.rb +0 -448
  574. data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
  575. data/test/cases/migration/table_and_index_test.rb +0 -24
  576. data/test/cases/relation/where_test2.rb +0 -36
  577. data/test/cases/type/decimal_test.rb +0 -56
  578. data/test/cases/type/unsigned_integer_test.rb +0 -18
  579. data/test/cases/xml_serialization_test.rb +0 -457
  580. data/test/connections/native_ibm_db/connection.rb +0 -44
  581. data/test/fixtures/naked/csv/accounts.csv +0 -1
  582. data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
  583. data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
  584. data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
  585. data/test/schema/mysql_specific_schema.rb +0 -70
  586. data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -1,52 +1,44 @@
1
- # encoding: utf-8
2
- require "cases/helper"
3
-
4
- # Without using prepared statements, it makes no sense to test
5
- # BLOB data with DB2, because the length of a statement
6
- # is limited to 32KB.
7
- unless current_adapter?(:DB2Adapter)
8
- require 'models/binary'
9
-
10
- class BinaryTest < ActiveRecord::TestCase
11
- FIXTURES = %w(flowers.jpg example.log test.txt)
12
-
13
- def test_mixed_encoding
14
- str = "\x80"
15
- str.force_encoding('ASCII-8BIT')
16
-
17
- binary = Binary.new :name => 'いただきます!', :data => str
18
- binary.save!
19
- binary.reload
20
- assert_equal str, binary.data
21
-
22
- name = binary.name
23
-
24
- # MySQL adapter doesn't properly encode things, so we have to do it
25
- if current_adapter?(:MysqlAdapter, :DB2Adapter)
26
- name.force_encoding(Encoding::UTF_8)
27
- end
28
- assert_equal 'いただきます!', name
29
- end
30
-
31
- def test_load_save
32
- Binary.delete_all
33
-
34
- FIXTURES.each do |filename|
35
- data = File.read(ASSETS_ROOT + "/#{filename}")
36
- data.force_encoding('ASCII-8BIT')
37
- if current_adapter?(:DB2Adapter)
38
- data.force_encoding(Encoding::UTF_8)
39
- end
40
- data.freeze
41
-
42
- bin = Binary.new(:data => data)
43
- assert_equal data, bin.data, 'Newly assigned data differs from original'
44
-
45
- bin.save!
46
- assert_equal data, bin.data, 'Data differs from original after save'
47
-
48
- assert_equal data, bin.reload.data, 'Reloaded data differs from original'
49
- end
50
- end
51
- end
52
- end
1
+ require "cases/helper"
2
+
3
+ # Without using prepared statements, it makes no sense to test
4
+ # BLOB data with DB2, because the length of a statement
5
+ # is limited to 32KB.
6
+ unless current_adapter?(:DB2Adapter)
7
+ require 'models/binary'
8
+
9
+ class BinaryTest < ActiveRecord::TestCase
10
+ FIXTURES = %w(flowers.jpg example.log test.txt)
11
+
12
+ def test_mixed_encoding
13
+ str = "\x80"
14
+ str.force_encoding('ASCII-8BIT')
15
+
16
+ binary = Binary.new :name => 'いただきます!', :data => str
17
+ binary.save!
18
+ binary.reload
19
+ assert_equal str, binary.data
20
+
21
+ name = binary.name
22
+
23
+ assert_equal 'いただきます!', name
24
+ end
25
+
26
+ def test_load_save
27
+ Binary.delete_all
28
+
29
+ FIXTURES.each do |filename|
30
+ data = File.read(ASSETS_ROOT + "/#{filename}")
31
+ data.force_encoding('ASCII-8BIT')
32
+ data.freeze
33
+
34
+ bin = Binary.new(:data => data)
35
+ assert_equal data, bin.data, 'Newly assigned data differs from original'
36
+
37
+ bin.save!
38
+ assert_equal data, bin.data, 'Data differs from original after save'
39
+
40
+ assert_equal data, bin.reload.data, 'Reloaded data differs from original'
41
+ end
42
+ end
43
+ end
44
+ end
@@ -1,100 +1,110 @@
1
- require 'cases/helper'
2
- require 'models/topic'
3
- require 'models/author'
4
- require 'models/post'
5
-
6
- module ActiveRecord
7
- class BindParameterTest < ActiveRecord::TestCase
8
- fixtures :topics, :authors, :posts
9
-
10
- class LogListener
11
- attr_accessor :calls
12
-
13
- def initialize
14
- @calls = []
15
- end
16
-
17
- def call(*args)
18
- calls << args
19
- end
20
- end
21
-
22
- def setup
23
- super
24
- @connection = ActiveRecord::Base.connection
25
- @subscriber = LogListener.new
26
- @pk = Topic.columns_hash[Topic.primary_key]
27
- @subscription = ActiveSupport::Notifications.subscribe('sql.active_record', @subscriber)
28
- end
29
-
30
- teardown do
31
- ActiveSupport::Notifications.unsubscribe(@subscription)
32
- end
33
-
34
- if ActiveRecord::Base.connection.supports_statement_cache?
35
- def test_bind_from_join_in_subquery
36
- subquery = Author.joins(:thinking_posts).where(name: 'David')
37
- scope = Author.from(subquery, 'authors').where(id: 1)
38
- assert_equal 1, scope.count
39
- end
40
-
41
- def test_binds_are_logged
42
- sub = @connection.substitute_at(@pk)
43
- binds = [[@pk, 1]]
44
- sql = "select * from topics where id = #{sub.to_sql}"
45
-
46
- @connection.exec_query(sql, 'SQL', binds)
47
-
48
- message = @subscriber.calls.find { |args| args[4][:sql] == sql }
49
- assert_equal binds, message[4][:binds]
50
- end
51
-
52
- def test_binds_are_logged_after_type_cast
53
- sub = @connection.substitute_at(@pk)
54
- binds = [[@pk, "3"]]
55
- sql = "select * from topics where id = #{sub.to_sql}"
56
-
57
- @connection.exec_query(sql, 'SQL', binds)
58
-
59
- message = @subscriber.calls.find { |args| args[4][:sql] == sql }
60
- assert_equal [[@pk, 3]], message[4][:binds]
61
- end
62
-
63
- def test_find_one_uses_binds
64
- Topic.find(1)
65
- binds = [[@pk, 1]]
66
- message = @subscriber.calls.find { |args| args[4][:binds] == binds }
67
- assert message, 'expected a message with binds'
68
- end
69
-
70
- def test_logs_bind_vars
71
- payload = {
72
- :name => 'SQL',
73
- :sql => 'select * from topics where id = ?',
74
- :binds => [[@pk, 10]]
75
- }
76
- event = ActiveSupport::Notifications::Event.new(
77
- 'foo',
78
- Time.now,
79
- Time.now,
80
- 123,
81
- payload)
82
-
83
- logger = Class.new(ActiveRecord::LogSubscriber) {
84
- attr_reader :debugs
85
- def initialize
86
- super
87
- @debugs = []
88
- end
89
-
90
- def debug str
91
- @debugs << str
92
- end
93
- }.new
94
-
95
- logger.sql event
96
- assert_match([[@pk.name, 10]].inspect, logger.debugs.first)
97
- end
98
- end
99
- end
100
- end
1
+ require 'cases/helper'
2
+ require 'models/topic'
3
+ require 'models/author'
4
+ require 'models/post'
5
+
6
+ if ActiveRecord::Base.connection.supports_statement_cache? &&
7
+ ActiveRecord::Base.connection.prepared_statements
8
+ module ActiveRecord
9
+ class BindParameterTest < ActiveRecord::TestCase
10
+ fixtures :topics, :authors, :posts
11
+
12
+ class LogListener
13
+ attr_accessor :calls
14
+
15
+ def initialize
16
+ @calls = []
17
+ end
18
+
19
+ def call(*args)
20
+ calls << args
21
+ end
22
+ end
23
+
24
+ def setup
25
+ super
26
+ puts "BindParameterTest - setup"
27
+ @connection = ActiveRecord::Base.connection
28
+ @subscriber = LogListener.new
29
+ @pk = Topic.columns_hash[Topic.primary_key]
30
+ @subscription = ActiveSupport::Notifications.subscribe("sql.active_record", @subscriber)
31
+ end
32
+
33
+ def teardown
34
+ puts "BindParameterTest - teardown"
35
+ ActiveSupport::Notifications.unsubscribe(@subscription)
36
+ end
37
+
38
+ def test_bind_from_join_in_subquery
39
+ puts "BindParameterTest - test_bind_from_join_in_subquery"
40
+ subquery = Author.joins(:thinking_posts).where(name: 'David')
41
+ scope = Author.from(subquery, 'authors').where(id: 1)
42
+ assert_equal 1, scope.count
43
+ end
44
+
45
+ def test_binds_are_logged
46
+ puts "BindParameterTest - test_binds_are_logged"
47
+ sub = Arel::Nodes::BindParam.new
48
+ binds = [Relation::QueryAttribute.new("id", 1, Type::Value.new)]
49
+ sql = "select * from topics where id = #{sub.to_sql}"
50
+
51
+ @connection.exec_query(sql, 'SQL', binds)
52
+
53
+ message = @subscriber.calls.find { |args| args[4][:sql] == sql }
54
+ assert_equal binds, message[4][:binds]
55
+ end
56
+
57
+ def test_find_one_uses_binds
58
+ puts "BindParameterTest - test_find_one_uses_binds"
59
+ Topic.find(1)
60
+ message = @subscriber.calls.find { |args| args[4][:binds].any? { |attr| attr.value == 1 } }
61
+ assert message, 'expected a message with binds'
62
+ end
63
+
64
+ def test_logs_binds_after_type_cast
65
+ puts "BindParameterTest - test_logs_binds_after_type_cast"
66
+ binds = [Relation::QueryAttribute.new("id", "10", Type::Integer.new)]
67
+ assert_logs_binds(binds)
68
+ end
69
+
70
+ def test_logs_legacy_binds_after_type_cast
71
+ puts "BindParameterTest - test_logs_legacy_binds_after_type_cast"
72
+ binds = [[@pk, "10"]]
73
+ assert_logs_binds(binds)
74
+ end
75
+
76
+ private
77
+ def assert_logs_binds(binds)
78
+ payload = {
79
+ name: "SQL",
80
+ sql: "select * from topics where id = ?",
81
+ binds: binds,
82
+ type_casted_binds: @connection.type_casted_binds(binds)
83
+ }
84
+
85
+ event = ActiveSupport::Notifications::Event.new(
86
+ "foo",
87
+ Time.now,
88
+ Time.now,
89
+ 123,
90
+ payload)
91
+
92
+ logger = Class.new(ActiveRecord::LogSubscriber) {
93
+ attr_reader :debugs
94
+
95
+ def initialize
96
+ super
97
+ @debugs = []
98
+ end
99
+
100
+ def debug(str)
101
+ @debugs << str
102
+ end
103
+ }.new
104
+
105
+ logger.sql(event)
106
+ assert_match([[@pk.name, 10]].inspect, logger.debugs.first)
107
+ end
108
+ end
109
+ end
110
+ end
@@ -0,0 +1,25 @@
1
+ require "cases/helper"
2
+
3
+ module ActiveRecord
4
+ class CacheKeyTest < ActiveRecord::TestCase
5
+ self.use_transactional_tests = false
6
+
7
+ class CacheMe < ActiveRecord::Base; end
8
+
9
+ setup do
10
+ @connection = ActiveRecord::Base.connection
11
+ @connection.create_table(:cache_mes) { |t| t.timestamps }
12
+ end
13
+
14
+ teardown do
15
+ @connection.drop_table :cache_mes, if_exists: true
16
+ end
17
+
18
+ test "test_cache_key_format_is_not_too_precise" do
19
+ record = CacheMe.create
20
+ key = record.cache_key
21
+
22
+ assert_equal key, record.reload.cache_key
23
+ end
24
+ end
25
+ end
@@ -1,646 +1,798 @@
1
- require "cases/helper"
2
- require 'models/club'
3
- require 'models/company'
4
- require "models/contract"
5
- require 'models/edge'
6
- require 'models/organization'
7
- require 'models/possession'
8
- require 'models/topic'
9
- require 'models/reply'
10
- require 'models/minivan'
11
- require 'models/speedometer'
12
- require 'models/ship_part'
13
- require 'models/treasure'
14
- require 'models/developer'
15
- require 'models/comment'
16
- require 'models/rating'
17
- require 'models/post'
18
-
19
- class NumericData < ActiveRecord::Base
20
- self.table_name = 'numeric_data'
21
-
22
- attribute :world_population, Type::Integer.new
23
- attribute :my_house_population, Type::Integer.new
24
- attribute :atoms_in_universe, Type::Integer.new
25
- end
26
-
27
- class CalculationsTest < ActiveRecord::TestCase
28
- fixtures :companies, :accounts, :topics, :speedometers, :minivans
29
-
30
- def test_should_sum_field
31
- assert_equal 318, Account.sum(:credit_limit)
32
- end
33
-
34
- def test_should_average_field
35
- value = Account.average(:credit_limit)
36
- assert_equal 53.0, value
37
- end
38
-
39
- def test_should_resolve_aliased_attributes
40
- assert_equal 318, Account.sum(:available_credit)
41
- end
42
-
43
- def test_should_return_decimal_average_of_integer_field
44
- return if current_adapter?(:IBM_DBAdapter) #average cannot be a decimal value when applied on integer field
45
- value = Account.average(:id)
46
- assert_equal 3.5, value
47
- end
48
-
49
- def test_should_return_integer_average_if_db_returns_such
50
- ShipPart.delete_all
51
- ShipPart.create!(:id => 3, :name => 'foo')
52
- value = ShipPart.average(:id)
53
- assert_equal 3, value
54
- end
55
-
56
- def test_should_return_nil_as_average
57
- assert_nil NumericData.average(:bank_balance)
58
- end
59
-
60
- def test_should_get_maximum_of_field
61
- assert_equal 60, Account.maximum(:credit_limit)
62
- end
63
-
64
- def test_should_get_maximum_of_field_with_include
65
- assert_equal 55, Account.where("companies.name != 'Summit'").references(:companies).includes(:firm).maximum(:credit_limit)
66
- end
67
-
68
- def test_should_get_minimum_of_field
69
- assert_equal 50, Account.minimum(:credit_limit)
70
- end
71
-
72
- def test_should_group_by_field
73
- c = Account.group(:firm_id).sum(:credit_limit)
74
- [1,6,2].each do |firm_id|
75
- assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
76
- end
77
- end
78
-
79
- def test_should_group_by_arel_attribute
80
- c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit)
81
- [1,6,2].each do |firm_id|
82
- assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
83
- end
84
- end
85
-
86
- def test_should_group_by_multiple_fields
87
- c = Account.group('firm_id', :credit_limit).count(:all)
88
- [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert c.keys.include?(firm_and_limit) }
89
- end
90
-
91
- def test_should_group_by_multiple_fields_having_functions
92
- c = Topic.group(:author_name, 'COALESCE(type, title)').count(:all)
93
- assert_equal 1, c[["Carl", "The Third Topic of the day"]]
94
- assert_equal 1, c[["Mary", "Reply"]]
95
- assert_equal 1, c[["David", "The First Topic"]]
96
- assert_equal 1, c[["Carl", "Reply"]]
97
- end
98
-
99
- def test_should_group_by_summed_field
100
- c = Account.group(:firm_id).sum(:credit_limit)
101
- assert_equal 50, c[1]
102
- assert_equal 105, c[6]
103
- assert_equal 60, c[2]
104
- end
105
-
106
- def test_should_order_by_grouped_field
107
- c = Account.group(:firm_id).order("firm_id").sum(:credit_limit)
108
- assert_equal [1, 2, 6, 9], c.keys.compact
109
- end
110
-
111
- def test_should_order_by_calculation
112
- c = Account.group(:firm_id).order("sum_credit_limit desc, firm_id").sum(:credit_limit)
113
- assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
114
- assert_equal [6, 2, 9, 1], c.keys.compact
115
- end
116
-
117
- def test_should_limit_calculation
118
- c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").limit(2).sum(:credit_limit)
119
- assert_equal [1, 2], c.keys.compact
120
- end
121
-
122
- def test_should_limit_calculation_with_offset
123
- c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").
124
- limit(2).offset(1).sum(:credit_limit)
125
- assert_equal [2, 6], c.keys.compact
126
- end
127
-
128
- def test_limit_should_apply_before_count
129
- accounts = Account.limit(3).where('firm_id IS NOT NULL')
130
-
131
- assert_equal 3, accounts.count(:firm_id)
132
- assert_equal 3, accounts.select(:firm_id).count
133
- end
134
-
135
- def test_count_should_shortcut_with_limit_zero
136
- accounts = Account.limit(0)
137
-
138
- assert_no_queries { assert_equal 0, accounts.count }
139
- end
140
-
141
- def test_limit_is_kept
142
- return if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
143
-
144
- queries = assert_sql { Account.limit(1).count }
145
- assert_equal 1, queries.length
146
- assert_match(/LIMIT/, queries.first)
147
- end
148
-
149
- def test_offset_is_kept
150
- return if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
151
-
152
- queries = assert_sql { Account.offset(1).count }
153
- assert_equal 1, queries.length
154
- assert_match(/OFFSET/, queries.first)
155
- end
156
-
157
- def test_limit_with_offset_is_kept
158
- return if current_adapter?(:OracleAdapter) || current_adapter?(:IBM_DBAdapter)
159
-
160
- queries = assert_sql { Account.limit(1).offset(1).count }
161
- assert_equal 1, queries.length
162
- assert_match(/LIMIT/, queries.first)
163
- assert_match(/OFFSET/, queries.first)
164
- end
165
-
166
- def test_no_limit_no_offset
167
- queries = assert_sql { Account.count }
168
- assert_equal 1, queries.length
169
- assert_no_match(/LIMIT/, queries.first)
170
- assert_no_match(/OFFSET/, queries.first)
171
- end
172
-
173
- def test_count_on_invalid_columns_raises
174
- e = assert_raises(ActiveRecord::StatementInvalid) {
175
- Account.select("credit_limit, firm_name").count
176
- }
177
-
178
- assert_match %r{accounts}i, e.message
179
- assert_match "credit_limit, firm_name", e.message
180
- end
181
-
182
- def test_should_group_by_summed_field_having_condition
183
- c = Account.group(:firm_id).having('sum(credit_limit) > 50').sum(:credit_limit)
184
- assert_nil c[1]
185
- assert_equal 105, c[6]
186
- assert_equal 60, c[2]
187
- end
188
-
189
- def test_should_group_by_summed_field_having_condition_from_select
190
- c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("MIN(credit_limit) > 50").sum(:credit_limit)
191
- assert_nil c[1]
192
- assert_equal 60, c[2]
193
- assert_equal 53, c[9]
194
- end
195
-
196
- def test_should_group_by_summed_association
197
- c = Account.group(:firm).sum(:credit_limit)
198
- assert_equal 50, c[companies(:first_firm)]
199
- assert_equal 105, c[companies(:rails_core)]
200
- assert_equal 60, c[companies(:first_client)]
201
- end
202
-
203
- def test_should_sum_field_with_conditions
204
- assert_equal 105, Account.where('firm_id = 6').sum(:credit_limit)
205
- end
206
-
207
- def test_should_return_zero_if_sum_conditions_return_nothing
208
- assert_equal 0, Account.where('1 = 2').sum(:credit_limit)
209
- assert_equal 0, companies(:rails_core).companies.where('1 = 2').sum(:id)
210
- end
211
-
212
- def test_sum_should_return_valid_values_for_decimals
213
- NumericData.create(:bank_balance => 19.83)
214
- assert_equal 19.83, NumericData.sum(:bank_balance)
215
- end
216
-
217
- def test_should_return_type_casted_values_with_group_and_expression
218
- assert_equal 0.5, Account.group(:firm_name).sum('0.01 * credit_limit')['37signals']
219
- end
220
-
221
- def test_should_group_by_summed_field_with_conditions
222
- c = Account.where('firm_id > 1').group(:firm_id).sum(:credit_limit)
223
- assert_nil c[1]
224
- assert_equal 105, c[6]
225
- assert_equal 60, c[2]
226
- end
227
-
228
- def test_should_group_by_summed_field_with_conditions_and_having
229
- c = Account.where('firm_id > 1').group(:firm_id).
230
- having('sum(credit_limit) > 60').sum(:credit_limit)
231
- assert_nil c[1]
232
- assert_equal 105, c[6]
233
- assert_nil c[2]
234
- end
235
-
236
- def test_should_group_by_fields_with_table_alias
237
- c = Account.group('accounts.firm_id').sum(:credit_limit)
238
- assert_equal 50, c[1]
239
- assert_equal 105, c[6]
240
- assert_equal 60, c[2]
241
- end
242
-
243
- def test_should_calculate_with_invalid_field
244
- assert_equal 6, Account.calculate(:count, '*')
245
- assert_equal 6, Account.calculate(:count, :all)
246
- end
247
-
248
- def test_should_calculate_grouped_with_invalid_field
249
- c = Account.group('accounts.firm_id').count(:all)
250
- assert_equal 1, c[1]
251
- assert_equal 2, c[6]
252
- assert_equal 1, c[2]
253
- end
254
-
255
- def test_should_calculate_grouped_association_with_invalid_field
256
- c = Account.group(:firm).count(:all)
257
- assert_equal 1, c[companies(:first_firm)]
258
- assert_equal 2, c[companies(:rails_core)]
259
- assert_equal 1, c[companies(:first_client)]
260
- end
261
-
262
- def test_should_group_by_association_with_non_numeric_foreign_key
263
- Speedometer.create! id: 'ABC'
264
- Minivan.create! id: 'OMG', speedometer_id: 'ABC'
265
-
266
- c = Minivan.group(:speedometer).count(:all)
267
- first_key = c.keys.first
268
- assert_equal Speedometer, first_key.class
269
- assert_equal 1, c[first_key]
270
- end
271
-
272
- def test_should_calculate_grouped_association_with_foreign_key_option
273
- Account.belongs_to :another_firm, :class_name => 'Firm', :foreign_key => 'firm_id'
274
- c = Account.group(:another_firm).count(:all)
275
- assert_equal 1, c[companies(:first_firm)]
276
- assert_equal 2, c[companies(:rails_core)]
277
- assert_equal 1, c[companies(:first_client)]
278
- end
279
-
280
- def test_should_calculate_grouped_by_function
281
- c = Company.group("UPPER(#{QUOTED_TYPE})").count(:all)
282
- assert_equal 2, c[nil]
283
- assert_equal 1, c['DEPENDENTFIRM']
284
- assert_equal 5, c['CLIENT']
285
- assert_equal 2, c['FIRM']
286
- end
287
-
288
- def test_should_calculate_grouped_by_function_with_table_alias
289
- c = Company.group("UPPER(companies.#{QUOTED_TYPE})").count(:all)
290
- assert_equal 2, c[nil]
291
- assert_equal 1, c['DEPENDENTFIRM']
292
- assert_equal 5, c['CLIENT']
293
- assert_equal 2, c['FIRM']
294
- end
295
-
296
- def test_should_not_overshadow_enumerable_sum
297
- assert_equal 6, [1, 2, 3].sum(&:abs)
298
- end
299
-
300
- def test_should_sum_scoped_field
301
- assert_equal 15, companies(:rails_core).companies.sum(:id)
302
- end
303
-
304
- def test_should_sum_scoped_field_with_from
305
- assert_equal Club.count, Organization.clubs.count
306
- end
307
-
308
- def test_should_sum_scoped_field_with_conditions
309
- assert_equal 8, companies(:rails_core).companies.where('id > 7').sum(:id)
310
- end
311
-
312
- def test_should_group_by_scoped_field
313
- c = companies(:rails_core).companies.group(:name).sum(:id)
314
- assert_equal 7, c['Leetsoft']
315
- assert_equal 8, c['Jadedpixel']
316
- end
317
-
318
- def test_should_group_by_summed_field_through_association_and_having
319
- c = companies(:rails_core).companies.group(:name).having('sum(id) > 7').sum(:id)
320
- assert_nil c['Leetsoft']
321
- assert_equal 8, c['Jadedpixel']
322
- end
323
-
324
- def test_should_count_selected_field_with_include
325
- assert_equal 6, Account.includes(:firm).distinct.count
326
- assert_equal 4, Account.includes(:firm).distinct.select(:credit_limit).count
327
- end
328
-
329
- def test_should_not_perform_joined_include_by_default
330
- assert_equal Account.count, Account.includes(:firm).count
331
- queries = assert_sql { Account.includes(:firm).count }
332
- assert_no_match(/join/i, queries.last)
333
- end
334
-
335
- def test_should_perform_joined_include_when_referencing_included_tables
336
- joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count
337
- assert_equal 1, joined_count
338
- end
339
-
340
- def test_should_count_scoped_select
341
- Account.update_all("credit_limit = NULL")
342
- assert_equal 0, Account.select("credit_limit").count
343
- end
344
-
345
- def test_should_count_scoped_select_with_options
346
- Account.update_all("credit_limit = NULL")
347
- Account.last.update_columns('credit_limit' => 49)
348
- Account.first.update_columns('credit_limit' => 51)
349
-
350
- assert_equal 1, Account.select("credit_limit").where('credit_limit >= 50').count
351
- end
352
-
353
- def test_should_count_manual_select_with_include
354
- assert_equal 6, Account.select("DISTINCT accounts.id").includes(:firm).count
355
- end
356
-
357
- def test_count_with_column_parameter
358
- assert_equal 5, Account.count(:firm_id)
359
- end
360
-
361
- def test_count_with_distinct
362
- assert_equal 4, Account.select(:credit_limit).distinct.count
363
- assert_equal 4, Account.select(:credit_limit).uniq.count
364
- end
365
-
366
- def test_count_with_aliased_attribute
367
- assert_equal 6, Account.count(:available_credit)
368
- end
369
-
370
- def test_count_with_column_and_options_parameter
371
- assert_equal 2, Account.where("credit_limit = 50 AND firm_id IS NOT NULL").count(:firm_id)
372
- end
373
-
374
- def test_should_count_field_in_joined_table
375
- assert_equal 5, Account.joins(:firm).count('companies.id')
376
- assert_equal 4, Account.joins(:firm).distinct.count('companies.id')
377
- end
378
-
379
- def test_should_count_field_in_joined_table_with_group_by
380
- c = Account.group('accounts.firm_id').joins(:firm).count('companies.id')
381
-
382
- [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) }
383
- end
384
-
385
- def test_count_with_no_parameters_isnt_deprecated
386
- assert_not_deprecated { Account.count }
387
- end
388
-
389
- def test_count_with_too_many_parameters_raises
390
- assert_raise(ArgumentError) { Account.count(1, 2, 3) }
391
- end
392
-
393
- def test_count_with_order
394
- assert_equal 6, Account.order(:credit_limit).count
395
- end
396
-
397
- def test_count_with_reverse_order
398
- assert_equal 6, Account.order(:credit_limit).reverse_order.count
399
- end
400
-
401
- def test_count_with_where_and_order
402
- assert_equal 1, Account.where(firm_name: '37signals').count
403
- assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).count
404
- assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).reverse_order.count
405
- end
406
-
407
- def test_should_sum_expression
408
- # Oracle adapter returns floating point value 636.0 after SUM
409
- if current_adapter?(:OracleAdapter)
410
- assert_equal 636, Account.sum("2 * credit_limit")
411
- else
412
- assert_equal 636, Account.sum("2 * credit_limit").to_i
413
- end
414
- end
415
-
416
- def test_sum_expression_returns_zero_when_no_records_to_sum
417
- assert_equal 0, Account.where('1 = 2').sum("2 * credit_limit")
418
- end
419
-
420
- def test_count_with_from_option
421
- assert_equal Company.count(:all), Company.from('companies').count(:all)
422
- assert_equal Account.where("credit_limit = 50").count(:all),
423
- Account.from('accounts').where("credit_limit = 50").count(:all)
424
- assert_equal Company.where(:type => "Firm").count(:type),
425
- Company.where(:type => "Firm").from('companies').count(:type)
426
- end
427
-
428
- def test_sum_with_from_option
429
- assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit)
430
- assert_equal Account.where("credit_limit > 50").sum(:credit_limit),
431
- Account.where("credit_limit > 50").from('accounts').sum(:credit_limit)
432
- end
433
-
434
- def test_average_with_from_option
435
- assert_equal Account.average(:credit_limit), Account.from('accounts').average(:credit_limit)
436
- assert_equal Account.where("credit_limit > 50").average(:credit_limit),
437
- Account.where("credit_limit > 50").from('accounts').average(:credit_limit)
438
- end
439
-
440
- def test_minimum_with_from_option
441
- assert_equal Account.minimum(:credit_limit), Account.from('accounts').minimum(:credit_limit)
442
- assert_equal Account.where("credit_limit > 50").minimum(:credit_limit),
443
- Account.where("credit_limit > 50").from('accounts').minimum(:credit_limit)
444
- end
445
-
446
- def test_maximum_with_from_option
447
- assert_equal Account.maximum(:credit_limit), Account.from('accounts').maximum(:credit_limit)
448
- assert_equal Account.where("credit_limit > 50").maximum(:credit_limit),
449
- Account.where("credit_limit > 50").from('accounts').maximum(:credit_limit)
450
- end
451
-
452
- def test_maximum_with_not_auto_table_name_prefix_if_column_included
453
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
454
-
455
- assert_equal 7, Company.includes(:contracts).maximum(:developer_id)
456
- end
457
-
458
- def test_minimum_with_not_auto_table_name_prefix_if_column_included
459
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
460
-
461
- assert_equal 7, Company.includes(:contracts).minimum(:developer_id)
462
- end
463
-
464
- def test_sum_with_not_auto_table_name_prefix_if_column_included
465
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
466
-
467
- assert_equal 7, Company.includes(:contracts).sum(:developer_id)
468
- end
469
-
470
- def test_from_option_with_specified_index
471
- if Edge.connection.adapter_name == 'MySQL' or Edge.connection.adapter_name == 'Mysql2'
472
- assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
473
- assert_equal Edge.where('sink_id < 5').count(:all),
474
- Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
475
- end
476
- end
477
-
478
- def test_from_option_with_table_different_than_class
479
- assert_equal Account.count(:all), Company.from('accounts').count(:all)
480
- end
481
-
482
- def test_distinct_is_honored_when_used_with_count_operation_after_group
483
- # Count the number of authors for approved topics
484
- approved_topics_count = Topic.group(:approved).count(:author_name)[true]
485
- assert_equal approved_topics_count, 4
486
- # Count the number of distinct authors for approved Topics
487
- distinct_authors_for_approved_count = Topic.group(:approved).distinct.count(:author_name)[true]
488
- assert_equal distinct_authors_for_approved_count, 3
489
- end
490
-
491
- def test_pluck
492
- assert_equal [1,2,3,4,5], Topic.order(:id).pluck(:id)
493
- end
494
-
495
- def test_pluck_without_column_names
496
- assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, ""]],
497
- Company.order(:id).limit(1).pluck
498
- end
499
-
500
- def test_pluck_type_cast
501
- topic = topics(:first)
502
- relation = Topic.where(:id => topic.id)
503
- assert_equal [ topic.approved ], relation.pluck(:approved)
504
- assert_equal [ topic.last_read ], relation.pluck(:last_read)
505
- assert_equal [ topic.written_on ], relation.pluck(:written_on)
506
- end
507
-
508
- def test_pluck_and_uniq
509
- assert_equal [50, 53, 55, 60], Account.order(:credit_limit).uniq.pluck(:credit_limit)
510
- end
511
-
512
- def test_pluck_in_relation
513
- company = Company.first
514
- contract = company.contracts.create!
515
- assert_equal [contract.id], company.contracts.pluck(:id)
516
- end
517
-
518
- def test_pluck_on_aliased_attribute
519
- assert_equal 'The First Topic', Topic.order(:id).pluck(:heading).first
520
- end
521
-
522
- def test_pluck_with_serialization
523
- t = Topic.create!(:content => { :foo => :bar })
524
- assert_equal [{:foo => :bar}], Topic.where(:id => t.id).pluck(:content)
525
- end
526
-
527
- def test_pluck_with_qualified_column_name
528
- assert_equal [1,2,3,4,5], Topic.order(:id).pluck("topics.id")
529
- end
530
-
531
- def test_pluck_auto_table_name_prefix
532
- c = Company.create!(:name => "test", :contracts => [Contract.new])
533
- assert_equal [c.id], Company.joins(:contracts).pluck(:id)
534
- end
535
-
536
- def test_pluck_if_table_included
537
- c = Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
538
- assert_equal [c.id], Company.includes(:contracts).where("contracts.id" => c.contracts.first).pluck(:id)
539
- end
540
-
541
- def test_pluck_not_auto_table_name_prefix_if_column_joined
542
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
543
- assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
544
- end
545
-
546
- def test_pluck_with_selection_clause
547
- assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT credit_limit').sort
548
- assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT accounts.credit_limit').sort
549
- assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT(credit_limit)').sort
550
-
551
- # MySQL returns "SUM(DISTINCT(credit_limit))" as the column name unless
552
- # an alias is provided. Without the alias, the column cannot be found
553
- # and properly typecast.
554
- assert_equal [50 + 53 + 55 + 60], Account.pluck('SUM(DISTINCT(credit_limit)) as credit_limit')
555
- end
556
-
557
- def test_plucks_with_ids
558
- assert_equal Company.all.map(&:id).sort, Company.ids.sort
559
- end
560
-
561
- def test_pluck_with_includes_limit_and_empty_result
562
- assert_equal [], Topic.includes(:replies).limit(0).pluck(:id)
563
- assert_equal [], Topic.includes(:replies).limit(1).where('0 = 1').pluck(:id)
564
- end
565
-
566
- def test_pluck_not_auto_table_name_prefix_if_column_included
567
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
568
- ids = Company.includes(:contracts).pluck(:developer_id)
569
- assert_equal Company.count, ids.length
570
- assert_equal [7], ids.compact
571
- end
572
-
573
- def test_pluck_multiple_columns
574
- assert_equal [
575
- [1, "The First Topic"], [2, "The Second Topic of the day"],
576
- [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
577
- [5, "The Fifth Topic of the day"]
578
- ], Topic.order(:id).pluck(:id, :title)
579
- assert_equal [
580
- [1, "The First Topic", "David"], [2, "The Second Topic of the day", "Mary"],
581
- [3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"],
582
- [5, "The Fifth Topic of the day", "Jason"]
583
- ], Topic.order(:id).pluck(:id, :title, :author_name)
584
- end
585
-
586
- def test_pluck_with_multiple_columns_and_selection_clause
587
- assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
588
- Account.pluck('id, credit_limit')
589
- end
590
-
591
- def test_pluck_with_multiple_columns_and_includes
592
- Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
593
- companies_and_developers = Company.order('companies.id').includes(:contracts).pluck(:name, :developer_id)
594
-
595
- assert_equal Company.count, companies_and_developers.length
596
- assert_equal ["37signals", nil], companies_and_developers.first
597
- assert_equal ["test", 7], companies_and_developers.last
598
- end
599
-
600
- def test_pluck_with_reserved_words
601
- Possession.create!(:where => "Over There")
602
-
603
- assert_equal ["Over There"], Possession.pluck(:where)
604
- end
605
-
606
- def test_pluck_replaces_select_clause
607
- taks_relation = Topic.select(:approved, :id).order(:id)
608
- assert_equal [1,2,3,4,5], taks_relation.pluck(:id)
609
- assert_equal [false, true, true, true, true], taks_relation.pluck(:approved)
610
- end
611
-
612
- def test_pluck_columns_with_same_name
613
- expected = [["The First Topic", "The Second Topic of the day"], ["The Third Topic of the day", "The Fourth Topic of the day"]]
614
- actual = Topic.joins(:replies)
615
- .pluck('topics.title', 'replies_topics.title')
616
- assert_equal expected, actual
617
- end
618
-
619
- def test_calculation_with_polymorphic_relation
620
- part = ShipPart.create!(name: "has trinket")
621
- part.trinkets.create!
622
-
623
- assert_equal part.id, ShipPart.joins(:trinkets).sum(:id)
624
- end
625
-
626
- def test_pluck_joined_with_polymorphic_relation
627
- part = ShipPart.create!(name: "has trinket")
628
- part.trinkets.create!
629
-
630
- assert_equal [part.id], ShipPart.joins(:trinkets).pluck(:id)
631
- end
632
-
633
- def test_grouped_calculation_with_polymorphic_relation
634
- part = ShipPart.create!(name: "has trinket")
635
- part.trinkets.create!
636
-
637
- assert_equal({ "has trinket" => part.id }, ShipPart.joins(:trinkets).group("ship_parts.name").sum(:id))
638
- end
639
-
640
- def test_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
641
- assert_nothing_raised ActiveRecord::StatementInvalid do
642
- developer = Developer.create!(name: 'developer')
643
- developer.ratings.includes(comment: :post).where(posts: { id: 1 }).count
644
- end
645
- end
646
- end
1
+ require "cases/helper"
2
+ require "models/book"
3
+ require 'models/club'
4
+ require 'models/company'
5
+ require "models/contract"
6
+ require 'models/edge'
7
+ require 'models/organization'
8
+ require 'models/possession'
9
+ require 'models/topic'
10
+ require 'models/reply'
11
+ require 'models/minivan'
12
+ require 'models/speedometer'
13
+ require 'models/ship_part'
14
+ require 'models/treasure'
15
+ require 'models/developer'
16
+ require 'models/comment'
17
+ require 'models/rating'
18
+ require 'models/post'
19
+
20
+ class NumericData < ActiveRecord::Base
21
+ self.table_name = 'numeric_data'
22
+
23
+ attribute :world_population, :integer
24
+ attribute :my_house_population, :integer
25
+ attribute :atoms_in_universe, :integer
26
+ end
27
+
28
+ class CalculationsTest < ActiveRecord::TestCase
29
+ fixtures :companies, :accounts, :topics, :speedometers, :minivans, :books
30
+
31
+ def test_should_sum_field
32
+ assert_equal 318, Account.sum(:credit_limit)
33
+ end
34
+
35
+ def test_should_sum_arel_attribute
36
+ assert_equal 318, Account.sum(Account.arel_table[:credit_limit])
37
+ end
38
+
39
+ def test_should_average_field
40
+ value = Account.average(:credit_limit)
41
+ assert_equal 53.0, value
42
+ end
43
+
44
+ def test_should_average_arel_attribute
45
+ value = Account.average(Account.arel_table[:credit_limit])
46
+ assert_equal 53.0, value
47
+ end
48
+
49
+ def test_should_resolve_aliased_attributes
50
+ assert_equal 318, Account.sum(:available_credit)
51
+ end
52
+
53
+ def test_should_return_decimal_average_of_integer_field
54
+ value = Account.average(:id)
55
+ assert_equal 3.5, value
56
+ end
57
+
58
+ def test_should_return_integer_average_if_db_returns_such
59
+ ShipPart.delete_all
60
+ ShipPart.create!(:id => 3, :name => 'foo')
61
+ value = ShipPart.average(:id)
62
+ assert_equal 3, value
63
+ end
64
+
65
+ def test_should_return_nil_as_average
66
+ assert_nil NumericData.average(:bank_balance)
67
+ end
68
+
69
+ def test_should_get_maximum_of_field
70
+ assert_equal 60, Account.maximum(:credit_limit)
71
+ end
72
+
73
+ def test_should_get_maximum_of_arel_attribute
74
+ assert_equal 60, Account.maximum(Account.arel_table[:credit_limit])
75
+ end
76
+
77
+ def test_should_get_maximum_of_field_with_include
78
+ assert_equal 55, Account.where("companies.name != 'Summit'").references(:companies).includes(:firm).maximum(:credit_limit)
79
+ end
80
+
81
+ def test_should_get_maximum_of_arel_attribute_with_include
82
+ assert_equal 55, Account.where("companies.name != 'Summit'").references(:companies).includes(:firm).maximum(Account.arel_table[:credit_limit])
83
+ end
84
+
85
+ def test_should_get_minimum_of_field
86
+ assert_equal 50, Account.minimum(:credit_limit)
87
+ end
88
+
89
+ def test_should_get_minimum_of_arel_attribute
90
+ assert_equal 50, Account.minimum(Account.arel_table[:credit_limit])
91
+ end
92
+
93
+ def test_should_group_by_field
94
+ c = Account.group(:firm_id).sum(:credit_limit)
95
+ [1,6,2].each do |firm_id|
96
+ assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
97
+ end
98
+ end
99
+
100
+ def test_should_group_by_arel_attribute
101
+ c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit)
102
+ [1,6,2].each do |firm_id|
103
+ assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}"
104
+ end
105
+ end
106
+
107
+ def test_should_group_by_multiple_fields
108
+ c = Account.group('firm_id', :credit_limit).count(:all)
109
+ [ [nil, 50], [1, 50], [6, 50], [6, 55], [9, 53], [2, 60] ].each { |firm_and_limit| assert c.keys.include?(firm_and_limit) }
110
+ end
111
+
112
+ def test_should_group_by_multiple_fields_having_functions
113
+ c = Topic.group(:author_name, 'COALESCE(type, title)').count(:all)
114
+ assert_equal 1, c[["Carl", "The Third Topic of the day"]]
115
+ assert_equal 1, c[["Mary", "Reply"]]
116
+ assert_equal 1, c[["David", "The First Topic"]]
117
+ assert_equal 1, c[["Carl", "Reply"]]
118
+ end
119
+
120
+ def test_should_group_by_summed_field
121
+ c = Account.group(:firm_id).sum(:credit_limit)
122
+ assert_equal 50, c[1]
123
+ assert_equal 105, c[6]
124
+ assert_equal 60, c[2]
125
+ end
126
+
127
+ def test_should_generate_valid_sql_with_joins_and_group
128
+ assert_nothing_raised do
129
+ AuditLog.joins(:developer).group(:id).count
130
+ end
131
+ end
132
+
133
+ def test_should_calculate_against_given_relation
134
+ developer = Developer.create!(name: "developer")
135
+ developer.audit_logs.create!(message: "first log")
136
+ developer.audit_logs.create!(message: "second log")
137
+
138
+ c = developer.audit_logs.joins(:developer).group(:id).count
139
+
140
+ assert_equal developer.audit_logs.count, c.size
141
+ developer.audit_logs.each do |log|
142
+ assert_equal 1, c[log.id]
143
+ end
144
+ end
145
+
146
+ def test_should_order_by_grouped_field
147
+ c = Account.group(:firm_id).order("firm_id").sum(:credit_limit)
148
+ assert_equal [1, 2, 6, 9], c.keys.compact
149
+ end
150
+
151
+ def test_should_order_by_calculation
152
+ c = Account.group(:firm_id).order("sum_credit_limit desc, firm_id").sum(:credit_limit)
153
+ assert_equal [105, 60, 53, 50, 50], c.keys.collect { |k| c[k] }
154
+ assert_equal [6, 2, 9, 1], c.keys.compact
155
+ end
156
+
157
+ def test_should_limit_calculation
158
+ c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").limit(2).sum(:credit_limit)
159
+ assert_equal [1, 2], c.keys.compact
160
+ end
161
+
162
+ def test_should_limit_calculation_with_offset
163
+ c = Account.where("firm_id IS NOT NULL").group(:firm_id).order("firm_id").
164
+ limit(2).offset(1).sum(:credit_limit)
165
+ assert_equal [2, 6], c.keys.compact
166
+ end
167
+
168
+ def test_limit_should_apply_before_count
169
+ accounts = Account.limit(3).where('firm_id IS NOT NULL')
170
+
171
+ assert_equal 3, accounts.count(:firm_id)
172
+ assert_equal 3, accounts.select(:firm_id).count
173
+ end
174
+
175
+ def test_limit_should_apply_before_count_arel_attribute
176
+ accounts = Account.limit(3).where('firm_id IS NOT NULL')
177
+
178
+ firm_id_attribute = Account.arel_table[:firm_id]
179
+ assert_equal 3, accounts.count(firm_id_attribute)
180
+ assert_equal 3, accounts.select(firm_id_attribute).count
181
+ end
182
+
183
+ def test_count_should_shortcut_with_limit_zero
184
+ accounts = Account.limit(0)
185
+
186
+ assert_no_queries { assert_equal 0, accounts.count }
187
+ end
188
+
189
+ def test_limit_is_kept
190
+ return if current_adapter?(:OracleAdapter)
191
+
192
+ queries = assert_sql { Account.limit(1).count }
193
+ assert_equal 1, queries.length
194
+ assert_match(/LIMIT/, queries.first)
195
+ end
196
+
197
+ def test_offset_is_kept
198
+ return if current_adapter?(:OracleAdapter)
199
+
200
+ queries = assert_sql { Account.offset(1).count }
201
+ assert_equal 1, queries.length
202
+ assert_match(/OFFSET/, queries.first)
203
+ end
204
+
205
+ def test_limit_with_offset_is_kept
206
+ return if current_adapter?(:OracleAdapter)
207
+
208
+ queries = assert_sql { Account.limit(1).offset(1).count }
209
+ assert_equal 1, queries.length
210
+ assert_match(/LIMIT/, queries.first)
211
+ assert_match(/OFFSET/, queries.first)
212
+ end
213
+
214
+ def test_no_limit_no_offset
215
+ queries = assert_sql { Account.count }
216
+ assert_equal 1, queries.length
217
+ assert_no_match(/LIMIT/, queries.first)
218
+ assert_no_match(/OFFSET/, queries.first)
219
+ end
220
+
221
+ def test_count_on_invalid_columns_raises
222
+ e = assert_raises(ActiveRecord::StatementInvalid) {
223
+ Account.select("credit_limit, firm_name").count
224
+ }
225
+
226
+ assert_match %r{accounts}i, e.message
227
+ assert_match "credit_limit, firm_name", e.message
228
+ end
229
+
230
+ def test_should_group_by_summed_field_having_condition
231
+ c = Account.group(:firm_id).having('sum(credit_limit) > 50').sum(:credit_limit)
232
+ assert_nil c[1]
233
+ assert_equal 105, c[6]
234
+ assert_equal 60, c[2]
235
+ end
236
+
237
+ def test_should_group_by_summed_field_having_condition_from_select
238
+ skip unless current_adapter?(:Mysql2Adapter, :SQLite3Adapter)
239
+ c = Account.select("MIN(credit_limit) AS min_credit_limit").group(:firm_id).having("min_credit_limit > 50").sum(:credit_limit)
240
+ assert_nil c[1]
241
+ assert_equal 60, c[2]
242
+ assert_equal 53, c[9]
243
+ end
244
+
245
+ def test_should_group_by_summed_association
246
+ c = Account.group(:firm).sum(:credit_limit)
247
+ assert_equal 50, c[companies(:first_firm)]
248
+ assert_equal 105, c[companies(:rails_core)]
249
+ assert_equal 60, c[companies(:first_client)]
250
+ end
251
+
252
+ def test_should_sum_field_with_conditions
253
+ assert_equal 105, Account.where('firm_id = 6').sum(:credit_limit)
254
+ end
255
+
256
+ def test_should_return_zero_if_sum_conditions_return_nothing
257
+ assert_equal 0, Account.where('1 = 2').sum(:credit_limit)
258
+ assert_equal 0, companies(:rails_core).companies.where('1 = 2').sum(:id)
259
+ end
260
+
261
+ def test_sum_should_return_valid_values_for_decimals
262
+ NumericData.create(:bank_balance => 19.83)
263
+ assert_equal 19.83, NumericData.sum(:bank_balance)
264
+ end
265
+
266
+ def test_should_return_type_casted_values_with_group_and_expression
267
+ assert_equal 0.5, Account.group(:firm_name).sum('0.01 * credit_limit')['37signals']
268
+ end
269
+
270
+ def test_should_group_by_summed_field_with_conditions
271
+ c = Account.where('firm_id > 1').group(:firm_id).sum(:credit_limit)
272
+ assert_nil c[1]
273
+ assert_equal 105, c[6]
274
+ assert_equal 60, c[2]
275
+ end
276
+
277
+ def test_should_group_by_summed_field_with_conditions_and_having
278
+ c = Account.where('firm_id > 1').group(:firm_id).
279
+ having('sum(credit_limit) > 60').sum(:credit_limit)
280
+ assert_nil c[1]
281
+ assert_equal 105, c[6]
282
+ assert_nil c[2]
283
+ end
284
+
285
+ def test_should_group_by_fields_with_table_alias
286
+ c = Account.group('accounts.firm_id').sum(:credit_limit)
287
+ assert_equal 50, c[1]
288
+ assert_equal 105, c[6]
289
+ assert_equal 60, c[2]
290
+ end
291
+
292
+ def test_should_calculate_with_invalid_field
293
+ assert_equal 6, Account.calculate(:count, '*')
294
+ assert_equal 6, Account.calculate(:count, :all)
295
+ end
296
+
297
+ def test_should_calculate_grouped_with_invalid_field
298
+ c = Account.group('accounts.firm_id').count(:all)
299
+ assert_equal 1, c[1]
300
+ assert_equal 2, c[6]
301
+ assert_equal 1, c[2]
302
+ end
303
+
304
+ def test_should_calculate_grouped_association_with_invalid_field
305
+ c = Account.group(:firm).count(:all)
306
+ assert_equal 1, c[companies(:first_firm)]
307
+ assert_equal 2, c[companies(:rails_core)]
308
+ assert_equal 1, c[companies(:first_client)]
309
+ end
310
+
311
+ def test_should_group_by_association_with_non_numeric_foreign_key
312
+ Speedometer.create! id: 'ABC'
313
+ Minivan.create! id: 'OMG', speedometer_id: 'ABC'
314
+
315
+ c = Minivan.group(:speedometer).count(:all)
316
+ first_key = c.keys.first
317
+ assert_equal Speedometer, first_key.class
318
+ assert_equal 1, c[first_key]
319
+ end
320
+
321
+ def test_should_calculate_grouped_association_with_foreign_key_option
322
+ Account.belongs_to :another_firm, :class_name => 'Firm', :foreign_key => 'firm_id'
323
+ c = Account.group(:another_firm).count(:all)
324
+ assert_equal 1, c[companies(:first_firm)]
325
+ assert_equal 2, c[companies(:rails_core)]
326
+ assert_equal 1, c[companies(:first_client)]
327
+ end
328
+
329
+ def test_should_calculate_grouped_by_function
330
+ c = Company.group("UPPER(#{QUOTED_TYPE})").count(:all)
331
+ assert_equal 2, c[nil]
332
+ assert_equal 1, c['DEPENDENTFIRM']
333
+ assert_equal 5, c['CLIENT']
334
+ assert_equal 2, c['FIRM']
335
+ end
336
+
337
+ def test_should_calculate_grouped_by_function_with_table_alias
338
+ c = Company.group("UPPER(companies.#{QUOTED_TYPE})").count(:all)
339
+ assert_equal 2, c[nil]
340
+ assert_equal 1, c['DEPENDENTFIRM']
341
+ assert_equal 5, c['CLIENT']
342
+ assert_equal 2, c['FIRM']
343
+ end
344
+
345
+ def test_should_not_overshadow_enumerable_sum
346
+ assert_equal 6, [1, 2, 3].sum(&:abs)
347
+ end
348
+
349
+ def test_should_sum_scoped_field
350
+ assert_equal 15, companies(:rails_core).companies.sum(:id)
351
+ end
352
+
353
+ def test_should_sum_scoped_field_with_from
354
+ assert_equal Club.count, Organization.clubs.count
355
+ end
356
+
357
+ def test_should_sum_scoped_field_with_conditions
358
+ assert_equal 8, companies(:rails_core).companies.where('id > 7').sum(:id)
359
+ end
360
+
361
+ def test_should_group_by_scoped_field
362
+ c = companies(:rails_core).companies.group(:name).sum(:id)
363
+ assert_equal 7, c['Leetsoft']
364
+ assert_equal 8, c['Jadedpixel']
365
+ end
366
+
367
+ def test_should_group_by_summed_field_through_association_and_having
368
+ c = companies(:rails_core).companies.group(:name).having('sum(id) > 7').sum(:id)
369
+ assert_nil c['Leetsoft']
370
+ assert_equal 8, c['Jadedpixel']
371
+ end
372
+
373
+ def test_should_count_selected_field_with_include
374
+ assert_equal 6, Account.includes(:firm).distinct.count
375
+ assert_equal 4, Account.includes(:firm).distinct.select(:credit_limit).count
376
+ end
377
+
378
+ def test_should_not_perform_joined_include_by_default
379
+ assert_equal Account.count, Account.includes(:firm).count
380
+ queries = assert_sql { Account.includes(:firm).count }
381
+ assert_no_match(/join/i, queries.last)
382
+ end
383
+
384
+ def test_should_perform_joined_include_when_referencing_included_tables
385
+ joined_count = Account.includes(:firm).where(:companies => {:name => '37signals'}).count
386
+ assert_equal 1, joined_count
387
+ end
388
+
389
+ def test_should_count_scoped_select
390
+ Account.update_all("credit_limit = NULL")
391
+ assert_equal 0, Account.select("credit_limit").count
392
+ end
393
+
394
+ def test_should_count_scoped_select_with_options
395
+ Account.update_all("credit_limit = NULL")
396
+ Account.last.update_columns('credit_limit' => 49)
397
+ Account.first.update_columns('credit_limit' => 51)
398
+
399
+ assert_equal 1, Account.select("credit_limit").where('credit_limit >= 50').count
400
+ end
401
+
402
+ def test_should_count_manual_select_with_include
403
+ assert_equal 6, Account.select("DISTINCT accounts.id").includes(:firm).count
404
+ end
405
+
406
+ def test_count_selected_arel_attribute
407
+ assert_equal 5, Account.select(Account.arel_table[:firm_id]).count
408
+ assert_equal 4, Account.distinct.select(Account.arel_table[:firm_id]).count
409
+ end
410
+
411
+ def test_count_with_column_parameter
412
+ assert_equal 5, Account.count(:firm_id)
413
+ end
414
+
415
+ def test_count_with_arel_attribute
416
+ assert_equal 5, Account.count(Account.arel_table[:firm_id])
417
+ end
418
+
419
+ def test_count_with_arel_star
420
+ assert_equal 6, Account.count(Arel.star)
421
+ end
422
+
423
+ def test_count_with_distinct
424
+ assert_equal 4, Account.select(:credit_limit).distinct.count
425
+
426
+ assert_deprecated do
427
+ assert_equal 4, Account.select(:credit_limit).uniq.count
428
+ end
429
+ end
430
+
431
+ def test_count_with_aliased_attribute
432
+ assert_equal 6, Account.count(:available_credit)
433
+ end
434
+
435
+ def test_count_with_column_and_options_parameter
436
+ assert_equal 2, Account.where("credit_limit = 50 AND firm_id IS NOT NULL").count(:firm_id)
437
+ end
438
+
439
+ def test_should_count_field_in_joined_table
440
+ assert_equal 5, Account.joins(:firm).count('companies.id')
441
+ assert_equal 4, Account.joins(:firm).distinct.count('companies.id')
442
+ end
443
+
444
+ def test_count_arel_attribute_in_joined_table_with
445
+ assert_equal 5, Account.joins(:firm).count(Company.arel_table[:id])
446
+ assert_equal 4, Account.joins(:firm).distinct.count(Company.arel_table[:id])
447
+ end
448
+
449
+ def test_count_selected_arel_attribute_in_joined_table
450
+ assert_equal 5, Account.joins(:firm).select(Company.arel_table[:id]).count
451
+ assert_equal 4, Account.joins(:firm).distinct.select(Company.arel_table[:id]).count
452
+ end
453
+
454
+ def test_should_count_field_in_joined_table_with_group_by
455
+ c = Account.group('accounts.firm_id').joins(:firm).count('companies.id')
456
+
457
+ [1,6,2,9].each { |firm_id| assert c.keys.include?(firm_id) }
458
+ end
459
+
460
+ def test_should_count_field_of_root_table_with_conflicting_group_by_column
461
+ assert_equal({ 1 => 1 }, Firm.joins(:accounts).group(:firm_id).count)
462
+ assert_equal({ 1 => 1 }, Firm.joins(:accounts).group('accounts.firm_id').count)
463
+ end
464
+
465
+ def test_count_with_no_parameters_isnt_deprecated
466
+ assert_not_deprecated { Account.count }
467
+ end
468
+
469
+ def test_count_with_too_many_parameters_raises
470
+ assert_raise(ArgumentError) { Account.count(1, 2, 3) }
471
+ end
472
+
473
+ def test_count_with_order
474
+ assert_equal 6, Account.order(:credit_limit).count
475
+ end
476
+
477
+ def test_count_with_reverse_order
478
+ assert_equal 6, Account.order(:credit_limit).reverse_order.count
479
+ end
480
+
481
+ def test_count_with_where_and_order
482
+ assert_equal 1, Account.where(firm_name: '37signals').count
483
+ assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).count
484
+ assert_equal 1, Account.where(firm_name: '37signals').order(:firm_name).reverse_order.count
485
+ end
486
+
487
+ def test_should_sum_expression
488
+ # Oracle adapter returns floating point value 636.0 after SUM
489
+ if current_adapter?(:OracleAdapter)
490
+ assert_equal 636, Account.sum("2 * credit_limit")
491
+ else
492
+ assert_equal 636, Account.sum("2 * credit_limit").to_i
493
+ end
494
+ end
495
+
496
+ def test_sum_expression_returns_zero_when_no_records_to_sum
497
+ assert_equal 0, Account.where('1 = 2').sum("2 * credit_limit")
498
+ end
499
+
500
+ def test_count_with_from_option
501
+ assert_equal Company.count(:all), Company.from('companies').count(:all)
502
+ assert_equal Account.where("credit_limit = 50").count(:all),
503
+ Account.from('accounts').where("credit_limit = 50").count(:all)
504
+ assert_equal Company.where(:type => "Firm").count(:type),
505
+ Company.where(:type => "Firm").from('companies').count(:type)
506
+ end
507
+
508
+ def test_sum_with_from_option
509
+ assert_equal Account.sum(:credit_limit), Account.from('accounts').sum(:credit_limit)
510
+ assert_equal Account.where("credit_limit > 50").sum(:credit_limit),
511
+ Account.where("credit_limit > 50").from('accounts').sum(:credit_limit)
512
+ end
513
+
514
+ def test_average_with_from_option
515
+ assert_equal Account.average(:credit_limit), Account.from('accounts').average(:credit_limit)
516
+ assert_equal Account.where("credit_limit > 50").average(:credit_limit),
517
+ Account.where("credit_limit > 50").from('accounts').average(:credit_limit)
518
+ end
519
+
520
+ def test_minimum_with_from_option
521
+ assert_equal Account.minimum(:credit_limit), Account.from('accounts').minimum(:credit_limit)
522
+ assert_equal Account.where("credit_limit > 50").minimum(:credit_limit),
523
+ Account.where("credit_limit > 50").from('accounts').minimum(:credit_limit)
524
+ end
525
+
526
+ def test_maximum_with_from_option
527
+ assert_equal Account.maximum(:credit_limit), Account.from('accounts').maximum(:credit_limit)
528
+ assert_equal Account.where("credit_limit > 50").maximum(:credit_limit),
529
+ Account.where("credit_limit > 50").from('accounts').maximum(:credit_limit)
530
+ end
531
+
532
+ def test_maximum_with_not_auto_table_name_prefix_if_column_included
533
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
534
+
535
+ assert_equal 7, Company.includes(:contracts).maximum(:developer_id)
536
+ end
537
+
538
+ def test_minimum_with_not_auto_table_name_prefix_if_column_included
539
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
540
+
541
+ assert_equal 7, Company.includes(:contracts).minimum(:developer_id)
542
+ end
543
+
544
+ def test_sum_with_not_auto_table_name_prefix_if_column_included
545
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
546
+
547
+ assert_equal 7, Company.includes(:contracts).sum(:developer_id)
548
+ end
549
+
550
+ if current_adapter?(:Mysql2Adapter)
551
+ def test_from_option_with_specified_index
552
+ assert_equal Edge.count(:all), Edge.from('edges USE INDEX(unique_edge_index)').count(:all)
553
+ assert_equal Edge.where('sink_id < 5').count(:all),
554
+ Edge.from('edges USE INDEX(unique_edge_index)').where('sink_id < 5').count(:all)
555
+ end
556
+ end
557
+
558
+ def test_from_option_with_table_different_than_class
559
+ assert_equal Account.count(:all), Company.from('accounts').count(:all)
560
+ end
561
+
562
+ def test_distinct_is_honored_when_used_with_count_operation_after_group
563
+ # Count the number of authors for approved topics
564
+ approved_topics_count = Topic.group(:approved).count(:author_name)[true]
565
+ assert_equal approved_topics_count, 4
566
+ # Count the number of distinct authors for approved Topics
567
+ distinct_authors_for_approved_count = Topic.group(:approved).distinct.count(:author_name)[true]
568
+ assert_equal distinct_authors_for_approved_count, 3
569
+ end
570
+
571
+ def test_pluck
572
+ assert_equal [1,2,3,4,5], Topic.order(:id).pluck(:id)
573
+ end
574
+
575
+ def test_pluck_without_column_names
576
+ assert_equal [[1, "Firm", 1, nil, "37signals", nil, 1, nil, ""]],
577
+ Company.order(:id).limit(1).pluck
578
+ end
579
+
580
+ def test_pluck_type_cast
581
+ topic = topics(:first)
582
+ relation = Topic.where(:id => topic.id)
583
+ assert_equal [ topic.approved ], relation.pluck(:approved)
584
+ assert_equal [ topic.last_read ], relation.pluck(:last_read)
585
+ assert_equal [ topic.written_on ], relation.pluck(:written_on)
586
+ end
587
+
588
+ def test_pluck_and_distinct
589
+ assert_equal [50, 53, 55, 60], Account.order(:credit_limit).distinct.pluck(:credit_limit)
590
+ end
591
+
592
+ def test_pluck_in_relation
593
+ company = Company.first
594
+ contract = company.contracts.create!
595
+ assert_equal [contract.id], company.contracts.pluck(:id)
596
+ end
597
+
598
+ def test_pluck_on_aliased_attribute
599
+ assert_equal 'The First Topic', Topic.order(:id).pluck(:heading).first
600
+ end
601
+
602
+ def test_pluck_with_serialization
603
+ t = Topic.create!(:content => { :foo => :bar })
604
+ assert_equal [{:foo => :bar}], Topic.where(:id => t.id).pluck(:content)
605
+ end
606
+
607
+ def test_pluck_with_qualified_column_name
608
+ assert_equal [1,2,3,4,5], Topic.order(:id).pluck("topics.id")
609
+ end
610
+
611
+ def test_pluck_auto_table_name_prefix
612
+ c = Company.create!(:name => "test", :contracts => [Contract.new])
613
+ assert_equal [c.id], Company.joins(:contracts).pluck(:id)
614
+ end
615
+
616
+ def test_pluck_if_table_included
617
+ c = Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
618
+ assert_equal [c.id], Company.includes(:contracts).where("contracts.id" => c.contracts.first).pluck(:id)
619
+ end
620
+
621
+ def test_pluck_not_auto_table_name_prefix_if_column_joined
622
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
623
+ assert_equal [7], Company.joins(:contracts).pluck(:developer_id)
624
+ end
625
+
626
+ def test_pluck_with_selection_clause
627
+ assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT credit_limit').sort
628
+ assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT accounts.credit_limit').sort
629
+ assert_equal [50, 53, 55, 60], Account.pluck('DISTINCT(credit_limit)').sort
630
+
631
+ # MySQL returns "SUM(DISTINCT(credit_limit))" as the column name unless
632
+ # an alias is provided. Without the alias, the column cannot be found
633
+ # and properly typecast.
634
+ assert_equal [50 + 53 + 55 + 60], Account.pluck('SUM(DISTINCT(credit_limit)) as credit_limit')
635
+ end
636
+
637
+ def test_plucks_with_ids
638
+ assert_equal Company.all.map(&:id).sort, Company.ids.sort
639
+ end
640
+
641
+ def test_pluck_with_includes_limit_and_empty_result
642
+ assert_equal [], Topic.includes(:replies).limit(0).pluck(:id)
643
+ assert_equal [], Topic.includes(:replies).limit(1).where('0 = 1').pluck(:id)
644
+ end
645
+
646
+ def test_pluck_not_auto_table_name_prefix_if_column_included
647
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
648
+ ids = Company.includes(:contracts).pluck(:developer_id)
649
+ assert_equal Company.count, ids.length
650
+ assert_equal [7], ids.compact
651
+ end
652
+
653
+ def test_pluck_multiple_columns
654
+ assert_equal [
655
+ [1, "The First Topic"], [2, "The Second Topic of the day"],
656
+ [3, "The Third Topic of the day"], [4, "The Fourth Topic of the day"],
657
+ [5, "The Fifth Topic of the day"]
658
+ ], Topic.order(:id).pluck(:id, :title)
659
+ assert_equal [
660
+ [1, "The First Topic", "David"], [2, "The Second Topic of the day", "Mary"],
661
+ [3, "The Third Topic of the day", "Carl"], [4, "The Fourth Topic of the day", "Carl"],
662
+ [5, "The Fifth Topic of the day", "Jason"]
663
+ ], Topic.order(:id).pluck(:id, :title, :author_name)
664
+ end
665
+
666
+ def test_pluck_with_multiple_columns_and_selection_clause
667
+ assert_equal [[1, 50], [2, 50], [3, 50], [4, 60], [5, 55], [6, 53]],
668
+ Account.pluck('id, credit_limit')
669
+ end
670
+
671
+ def test_pluck_with_multiple_columns_and_includes
672
+ Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)])
673
+ companies_and_developers = Company.order('companies.id').includes(:contracts).pluck(:name, :developer_id)
674
+
675
+ assert_equal Company.count, companies_and_developers.length
676
+ assert_equal ["37signals", nil], companies_and_developers.first
677
+ assert_equal ["test", 7], companies_and_developers.last
678
+ end
679
+
680
+ def test_pluck_with_reserved_words
681
+ Possession.create!(:where => "Over There")
682
+
683
+ assert_equal ["Over There"], Possession.pluck(:where)
684
+ end
685
+
686
+ def test_pluck_replaces_select_clause
687
+ taks_relation = Topic.select(:approved, :id).order(:id)
688
+ assert_equal [1,2,3,4,5], taks_relation.pluck(:id)
689
+ assert_equal [false, true, true, true, true], taks_relation.pluck(:approved)
690
+ end
691
+
692
+ def test_pluck_columns_with_same_name
693
+ expected = [["The First Topic", "The Second Topic of the day"], ["The Third Topic of the day", "The Fourth Topic of the day"]]
694
+ actual = Topic.joins(:replies)
695
+ .pluck('topics.title', 'replies_topics.title')
696
+ assert_equal expected, actual
697
+ end
698
+
699
+ def test_calculation_with_polymorphic_relation
700
+ part = ShipPart.create!(name: "has trinket")
701
+ part.trinkets.create!
702
+
703
+ assert_equal part.id, ShipPart.joins(:trinkets).sum(:id)
704
+ end
705
+
706
+ def test_pluck_joined_with_polymorphic_relation
707
+ part = ShipPart.create!(name: "has trinket")
708
+ part.trinkets.create!
709
+
710
+ assert_equal [part.id], ShipPart.joins(:trinkets).pluck(:id)
711
+ end
712
+
713
+ def test_pluck_loaded_relation
714
+ companies = Company.order(:id).limit(3).load
715
+ assert_no_queries do
716
+ assert_equal ['37signals', 'Summit', 'Microsoft'], companies.pluck(:name)
717
+ end
718
+ end
719
+
720
+ def test_pluck_loaded_relation_multiple_columns
721
+ companies = Company.order(:id).limit(3).load
722
+ assert_no_queries do
723
+ assert_equal [[1, '37signals'], [2, 'Summit'], [3, 'Microsoft']], companies.pluck(:id, :name)
724
+ end
725
+ end
726
+
727
+ def test_pluck_loaded_relation_sql_fragment
728
+ companies = Company.order(:name).limit(3).load
729
+ assert_queries 1 do
730
+ assert_equal ['37signals', 'Apex', 'Ex Nihilo'], companies.pluck('DISTINCT name')
731
+ end
732
+ end
733
+
734
+ def test_grouped_calculation_with_polymorphic_relation
735
+ part = ShipPart.create!(name: "has trinket")
736
+ part.trinkets.create!
737
+
738
+ assert_equal({ "has trinket" => part.id }, ShipPart.joins(:trinkets).group("ship_parts.name").sum(:id))
739
+ end
740
+
741
+ def test_calculation_grouped_by_association_doesnt_error_when_no_records_have_association
742
+ Client.update_all(client_of: nil)
743
+ assert_equal({ nil => Client.count }, Client.group(:firm).count)
744
+ end
745
+
746
+ def test_should_reference_correct_aliases_while_joining_tables_of_has_many_through_association
747
+ assert_nothing_raised do
748
+ developer = Developer.create!(name: 'developer')
749
+ developer.ratings.includes(comment: :post).where(posts: { id: 1 }).count
750
+ end
751
+ end
752
+
753
+ def test_sum_uses_enumerable_version_when_block_is_given
754
+ block_called = false
755
+ relation = Client.all.load
756
+
757
+ assert_no_queries do
758
+ assert_equal 0, relation.sum { block_called = true; 0 }
759
+ end
760
+ assert block_called
761
+ end
762
+
763
+ def test_having_with_strong_parameters
764
+ protected_params = Class.new do
765
+ attr_reader :permitted
766
+ alias :permitted? :permitted
767
+
768
+ def initialize(parameters)
769
+ @parameters = parameters
770
+ @permitted = false
771
+ end
772
+
773
+ def to_h
774
+ @parameters
775
+ end
776
+
777
+ def permit!
778
+ @permitted = true
779
+ self
780
+ end
781
+ end
782
+
783
+ params = protected_params.new(credit_limit: '50')
784
+
785
+ assert_raises(ActiveModel::ForbiddenAttributesError) do
786
+ Account.group(:id).having(params)
787
+ end
788
+
789
+ result = Account.group(:id).having(params.permit!)
790
+ assert_equal 50, result[0].credit_limit
791
+ assert_equal 50, result[1].credit_limit
792
+ assert_equal 50, result[2].credit_limit
793
+ end
794
+
795
+ def test_group_by_attribute_with_custom_type
796
+ assert_equal({ "proposed" => 2, "published" => 2 }, Book.group(:status).count)
797
+ end
798
+ end