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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (465) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +4 -0
  3. data/MANIFEST +14 -14
  4. data/README +225 -225
  5. data/ext/Makefile.nt32 +181 -181
  6. data/ext/Makefile.nt32.191 +212 -212
  7. data/ext/OLD/extconf.rb +264 -0
  8. data/ext/{extconf_MacOS.rb → OLD/extconf_MacOS.rb} +269 -269
  9. data/ext/extconf.rb +291 -264
  10. data/ext/ibm_db.c +2 -2
  11. data/ext/ruby_ibm_db.h +241 -241
  12. data/ext/ruby_ibm_db_cli.h +500 -500
  13. data/init.rb +41 -41
  14. data/lib/IBM_DB.rb +27 -27
  15. data/lib/active_record/connection_adapters/ibm_db_adapter.rb +4 -4
  16. data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
  17. data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
  18. data/lib/mswin32/ibm_db.rb +115 -115
  19. data/test/active_record/connection_adapters/fake_adapter.rb +46 -0
  20. data/test/assets/example.log +1 -0
  21. data/test/assets/flowers.jpg +0 -0
  22. data/test/assets/test.txt +1 -0
  23. data/test/cases/adapter_test.rb +261 -207
  24. data/test/cases/aggregations_test.rb +158 -0
  25. data/test/cases/ar_schema_test.rb +161 -0
  26. data/test/cases/associations/association_scope_test.rb +21 -0
  27. data/test/cases/associations/belongs_to_associations_test.rb +1029 -711
  28. data/test/cases/associations/callbacks_test.rb +192 -0
  29. data/test/cases/associations/cascaded_eager_loading_test.rb +188 -181
  30. data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -0
  31. data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -0
  32. data/test/cases/associations/eager_load_nested_include_test.rb +128 -0
  33. data/test/cases/associations/eager_singularization_test.rb +148 -0
  34. data/test/cases/associations/eager_test.rb +1411 -0
  35. data/test/cases/associations/extension_test.rb +82 -0
  36. data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +932 -851
  37. data/test/cases/associations/has_many_associations_test.rb +2162 -0
  38. data/test/cases/associations/has_many_through_associations_test.rb +1204 -0
  39. data/test/cases/associations/has_one_associations_test.rb +610 -0
  40. data/test/cases/associations/has_one_through_associations_test.rb +380 -0
  41. data/test/cases/associations/inner_join_association_test.rb +139 -0
  42. data/test/cases/associations/inverse_associations_test.rb +693 -0
  43. data/test/cases/associations/join_model_test.rb +754 -743
  44. data/test/cases/associations/nested_through_associations_test.rb +579 -0
  45. data/test/cases/associations/required_test.rb +82 -0
  46. data/test/cases/associations_test.rb +380 -0
  47. data/test/cases/attribute_decorators_test.rb +125 -0
  48. data/test/cases/attribute_methods/read_test.rb +60 -0
  49. data/test/cases/attribute_methods/serialization_test.rb +29 -0
  50. data/test/cases/attribute_methods_test.rb +952 -822
  51. data/test/cases/attribute_set_test.rb +200 -0
  52. data/test/cases/attribute_test.rb +180 -0
  53. data/test/cases/attributes_test.rb +136 -0
  54. data/test/cases/autosave_association_test.rb +1595 -0
  55. data/test/cases/base_test.rb +1638 -2133
  56. data/test/cases/batches_test.rb +212 -0
  57. data/test/cases/binary_test.rb +52 -0
  58. data/test/cases/bind_parameter_test.rb +100 -0
  59. data/test/cases/calculations_test.rb +646 -482
  60. data/test/cases/callbacks_test.rb +543 -0
  61. data/test/cases/clone_test.rb +40 -0
  62. data/test/cases/coders/yaml_column_test.rb +63 -0
  63. data/test/cases/column_alias_test.rb +17 -0
  64. data/test/cases/column_definition_test.rb +123 -0
  65. data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -0
  66. data/test/cases/connection_adapters/connection_handler_test.rb +53 -0
  67. data/test/cases/connection_adapters/connection_specification_test.rb +12 -0
  68. data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +293 -0
  69. data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -0
  70. data/test/cases/connection_adapters/quoting_test.rb +13 -0
  71. data/test/cases/connection_adapters/schema_cache_test.rb +56 -0
  72. data/test/cases/connection_adapters/type_lookup_test.rb +110 -0
  73. data/test/cases/connection_management_test.rb +122 -0
  74. data/test/cases/connection_pool_test.rb +346 -0
  75. data/test/cases/connection_specification/resolver_test.rb +116 -0
  76. data/test/cases/core_test.rb +112 -0
  77. data/test/cases/counter_cache_test.rb +209 -0
  78. data/test/cases/custom_locking_test.rb +17 -0
  79. data/test/cases/database_statements_test.rb +19 -0
  80. data/test/cases/date_time_test.rb +61 -0
  81. data/test/cases/defaults_test.rb +223 -0
  82. data/test/cases/dirty_test.rb +775 -0
  83. data/test/cases/disconnected_test.rb +28 -0
  84. data/test/cases/dup_test.rb +157 -0
  85. data/test/cases/enum_test.rb +290 -0
  86. data/test/cases/explain_subscriber_test.rb +64 -0
  87. data/test/cases/explain_test.rb +76 -0
  88. data/test/cases/finder_respond_to_test.rb +60 -0
  89. data/test/cases/finder_test.rb +1166 -0
  90. data/test/cases/fixture_set/file_test.rb +138 -0
  91. data/test/cases/fixtures_test.rb +897 -0
  92. data/test/cases/forbidden_attributes_protection_test.rb +99 -0
  93. data/test/cases/habtm_destroy_order_test.rb +61 -0
  94. data/test/cases/helper.rb +210 -0
  95. data/test/cases/hot_compatibility_test.rb +54 -0
  96. data/test/cases/i18n_test.rb +45 -0
  97. data/test/cases/inheritance_test.rb +375 -0
  98. data/test/cases/integration_test.rb +139 -0
  99. data/test/cases/invalid_connection_test.rb +22 -0
  100. data/test/cases/invalid_date_test.rb +32 -0
  101. data/test/cases/invertible_migration_test.rb +295 -0
  102. data/test/cases/json_serialization_test.rb +302 -0
  103. data/test/cases/locking_test.rb +477 -0
  104. data/test/cases/log_subscriber_test.rb +136 -0
  105. data/test/cases/migration/change_schema_test - Copy.rb +448 -0
  106. data/test/cases/migration/change_schema_test.rb +472 -0
  107. data/test/cases/migration/change_table_test.rb +224 -0
  108. data/test/cases/migration/column_attributes_test.rb +192 -0
  109. data/test/cases/migration/column_positioning_test.rb +56 -0
  110. data/test/cases/migration/columns_test.rb +304 -0
  111. data/test/cases/migration/command_recorder_test.rb +305 -0
  112. data/test/cases/migration/create_join_table_test.rb +148 -0
  113. data/test/cases/migration/foreign_key_test - Changed.rb +325 -0
  114. data/test/cases/migration/foreign_key_test.rb +360 -0
  115. data/test/cases/migration/helper.rb +39 -0
  116. data/test/cases/migration/index_test.rb +216 -0
  117. data/test/cases/migration/logger_test.rb +36 -0
  118. data/test/cases/migration/pending_migrations_test.rb +53 -0
  119. data/test/cases/migration/references_foreign_key_test.rb +214 -0
  120. data/test/cases/migration/references_index_test.rb +101 -0
  121. data/test/cases/migration/references_statements_test.rb +116 -0
  122. data/test/cases/migration/rename_table_test.rb +93 -0
  123. data/test/cases/migration/table_and_index_test.rb +24 -0
  124. data/test/cases/migration_test.rb +959 -2408
  125. data/test/cases/migrator_test.rb +388 -0
  126. data/test/cases/mixin_test.rb +70 -0
  127. data/test/cases/modules_test.rb +173 -0
  128. data/test/cases/multiparameter_attributes_test.rb +350 -0
  129. data/test/cases/multiple_db_test.rb +115 -0
  130. data/test/cases/nested_attributes_test.rb +1057 -0
  131. data/test/cases/nested_attributes_with_callbacks_test.rb +144 -0
  132. data/test/cases/persistence_test.rb +909 -642
  133. data/test/cases/pooled_connections_test.rb +81 -0
  134. data/test/cases/primary_keys_test.rb +237 -0
  135. data/test/cases/query_cache_test.rb +326 -257
  136. data/test/cases/quoting_test.rb +156 -0
  137. data/test/cases/readonly_test.rb +118 -0
  138. data/test/cases/reaper_test.rb +85 -0
  139. data/test/cases/reflection_test.rb +454 -0
  140. data/test/cases/relation/delegation_test.rb +68 -0
  141. data/test/cases/relation/merging_test.rb +161 -0
  142. data/test/cases/relation/mutation_test.rb +165 -0
  143. data/test/cases/relation/predicate_builder_test.rb +14 -0
  144. data/test/cases/relation/where_chain_test.rb +181 -0
  145. data/test/cases/relation/where_test.rb +300 -0
  146. data/test/cases/relation/where_test2.rb +36 -0
  147. data/test/cases/relation_test.rb +297 -0
  148. data/test/cases/relations_test.rb +1815 -1182
  149. data/test/cases/reload_models_test.rb +22 -0
  150. data/test/cases/result_test.rb +80 -0
  151. data/test/cases/sanitize_test.rb +83 -0
  152. data/test/cases/schema_dumper_test.rb +463 -256
  153. data/test/cases/scoping/default_scoping_test.rb +454 -0
  154. data/test/cases/scoping/named_scoping_test.rb +524 -0
  155. data/test/cases/scoping/relation_scoping_test.rb +357 -0
  156. data/test/cases/serialization_test.rb +104 -0
  157. data/test/cases/serialized_attribute_test.rb +277 -0
  158. data/test/cases/statement_cache_test.rb +98 -0
  159. data/test/cases/store_test.rb +194 -0
  160. data/test/cases/tasks/database_tasks_test.rb +396 -0
  161. data/test/cases/tasks/mysql_rake_test.rb +311 -0
  162. data/test/cases/tasks/postgresql_rake_test.rb +245 -0
  163. data/test/cases/tasks/sqlite_rake_test.rb +193 -0
  164. data/test/cases/test_case.rb +123 -0
  165. data/test/cases/timestamp_test.rb +468 -0
  166. data/test/cases/transaction_callbacks_test.rb +452 -300
  167. data/test/cases/transaction_isolation_test.rb +106 -0
  168. data/test/cases/transactions_test.rb +817 -0
  169. data/test/cases/type/decimal_test.rb +51 -0
  170. data/test/cases/type/integer_test.rb +121 -0
  171. data/test/cases/type/string_test.rb +36 -0
  172. data/test/cases/type/type_map_test.rb +177 -0
  173. data/test/cases/type/unsigned_integer_test.rb +18 -0
  174. data/test/cases/types_test.rb +141 -0
  175. data/test/cases/unconnected_test.rb +33 -0
  176. data/test/cases/validations/association_validation_test.rb +86 -0
  177. data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -0
  178. data/test/cases/validations/i18n_validation_test.rb +90 -0
  179. data/test/cases/validations/length_validation_test.rb +47 -0
  180. data/test/cases/validations/presence_validation_test.rb +68 -0
  181. data/test/cases/validations/uniqueness_validation_test.rb +434 -299
  182. data/test/cases/validations_repair_helper.rb +23 -0
  183. data/test/cases/validations_test.rb +165 -0
  184. data/test/cases/view_test.rb +113 -0
  185. data/test/cases/xml_serialization_test.rb +457 -408
  186. data/test/cases/yaml_serialization_test.rb +86 -0
  187. data/test/config.rb +5 -0
  188. data/test/config.yml +154 -154
  189. data/test/connections/native_ibm_db/connection.rb +43 -43
  190. data/test/fixtures/accounts.yml +29 -0
  191. data/test/fixtures/admin/accounts.yml +2 -0
  192. data/test/fixtures/admin/randomly_named_a9.yml +7 -0
  193. data/test/fixtures/admin/randomly_named_b0.yml +7 -0
  194. data/test/fixtures/admin/users.yml +10 -0
  195. data/test/fixtures/all/admin +1 -0
  196. data/test/fixtures/all/developers.yml +0 -0
  197. data/test/fixtures/all/people.yml +0 -0
  198. data/test/fixtures/all/tasks.yml +0 -0
  199. data/test/fixtures/author_addresses.yml +18 -0
  200. data/test/fixtures/author_favorites.yml +4 -0
  201. data/test/fixtures/authors.yml +23 -0
  202. data/test/fixtures/binaries.yml +133 -0
  203. data/test/fixtures/books.yml +11 -0
  204. data/test/fixtures/bulbs.yml +5 -0
  205. data/test/fixtures/cars.yml +9 -0
  206. data/test/fixtures/categories.yml +19 -0
  207. data/test/fixtures/categories/special_categories.yml +9 -0
  208. data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -0
  209. data/test/fixtures/categories_ordered.yml +7 -0
  210. data/test/fixtures/categories_posts.yml +31 -0
  211. data/test/fixtures/categorizations.yml +23 -0
  212. data/test/fixtures/clubs.yml +8 -0
  213. data/test/fixtures/collections.yml +3 -0
  214. data/test/fixtures/colleges.yml +3 -0
  215. data/test/fixtures/comments.yml +65 -0
  216. data/test/fixtures/companies.yml +67 -0
  217. data/test/fixtures/computers.yml +10 -0
  218. data/test/fixtures/courses.yml +8 -0
  219. data/test/fixtures/customers.yml +26 -0
  220. data/test/fixtures/dashboards.yml +6 -0
  221. data/test/fixtures/developers.yml +22 -0
  222. data/test/fixtures/developers_projects.yml +17 -0
  223. data/test/fixtures/dog_lovers.yml +7 -0
  224. data/test/fixtures/dogs.yml +4 -0
  225. data/test/fixtures/doubloons.yml +3 -0
  226. data/test/fixtures/edges.yml +5 -0
  227. data/test/fixtures/entrants.yml +14 -0
  228. data/test/fixtures/essays.yml +6 -0
  229. data/test/fixtures/faces.yml +11 -0
  230. data/test/fixtures/fk_test_has_fk.yml +3 -0
  231. data/test/fixtures/fk_test_has_pk.yml +2 -0
  232. data/test/fixtures/friendships.yml +4 -0
  233. data/test/fixtures/funny_jokes.yml +10 -0
  234. data/test/fixtures/interests.yml +33 -0
  235. data/test/fixtures/items.yml +3 -0
  236. data/test/fixtures/jobs.yml +7 -0
  237. data/test/fixtures/legacy_things.yml +3 -0
  238. data/test/fixtures/mateys.yml +4 -0
  239. data/test/fixtures/member_details.yml +8 -0
  240. data/test/fixtures/member_types.yml +6 -0
  241. data/test/fixtures/members.yml +11 -0
  242. data/test/fixtures/memberships.yml +34 -0
  243. data/test/fixtures/men.yml +5 -0
  244. data/test/fixtures/minimalistics.yml +2 -0
  245. data/test/fixtures/minivans.yml +5 -0
  246. data/test/fixtures/mixed_case_monkeys.yml +6 -0
  247. data/test/fixtures/mixins.yml +29 -0
  248. data/test/fixtures/movies.yml +7 -0
  249. data/test/fixtures/naked/csv/accounts.csv +1 -0
  250. data/test/fixtures/naked/yml/accounts.yml +1 -0
  251. data/test/fixtures/naked/yml/companies.yml +1 -0
  252. data/test/fixtures/naked/yml/courses.yml +1 -0
  253. data/test/fixtures/organizations.yml +5 -0
  254. data/test/fixtures/other_topics.yml +42 -0
  255. data/test/fixtures/owners.yml +9 -0
  256. data/test/fixtures/parrots.yml +27 -0
  257. data/test/fixtures/parrots_pirates.yml +7 -0
  258. data/test/fixtures/people.yml +24 -0
  259. data/test/fixtures/peoples_treasures.yml +3 -0
  260. data/test/fixtures/pets.yml +19 -0
  261. data/test/fixtures/pirates.yml +12 -0
  262. data/test/fixtures/posts.yml +80 -0
  263. data/test/fixtures/price_estimates.yml +7 -0
  264. data/test/fixtures/products.yml +4 -0
  265. data/test/fixtures/projects.yml +7 -0
  266. data/test/fixtures/randomly_named_a9.yml +7 -0
  267. data/test/fixtures/ratings.yml +14 -0
  268. data/test/fixtures/readers.yml +11 -0
  269. data/test/fixtures/references.yml +17 -0
  270. data/test/fixtures/reserved_words/distinct.yml +5 -0
  271. data/test/fixtures/reserved_words/distinct_select.yml +11 -0
  272. data/test/fixtures/reserved_words/group.yml +14 -0
  273. data/test/fixtures/reserved_words/select.yml +8 -0
  274. data/test/fixtures/reserved_words/values.yml +7 -0
  275. data/test/fixtures/ships.yml +6 -0
  276. data/test/fixtures/speedometers.yml +8 -0
  277. data/test/fixtures/sponsors.yml +12 -0
  278. data/test/fixtures/string_key_objects.yml +7 -0
  279. data/test/fixtures/subscribers.yml +11 -0
  280. data/test/fixtures/subscriptions.yml +12 -0
  281. data/test/fixtures/taggings.yml +78 -0
  282. data/test/fixtures/tags.yml +11 -0
  283. data/test/fixtures/tasks.yml +7 -0
  284. data/test/fixtures/teapots.yml +3 -0
  285. data/test/fixtures/to_be_linked/accounts.yml +2 -0
  286. data/test/fixtures/to_be_linked/users.yml +10 -0
  287. data/test/fixtures/topics.yml +49 -0
  288. data/test/fixtures/toys.yml +14 -0
  289. data/test/fixtures/traffic_lights.yml +10 -0
  290. data/test/fixtures/treasures.yml +10 -0
  291. data/test/fixtures/uuid_children.yml +3 -0
  292. data/test/fixtures/uuid_parents.yml +2 -0
  293. data/test/fixtures/variants.yml +4 -0
  294. data/test/fixtures/vegetables.yml +20 -0
  295. data/test/fixtures/vertices.yml +4 -0
  296. data/test/fixtures/warehouse_things.yml +3 -0
  297. data/test/fixtures/zines.yml +5 -0
  298. data/test/ibm_db_test.rb +24 -24
  299. data/test/migrations/10_urban/9_add_expressions.rb +11 -0
  300. data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -0
  301. data/test/migrations/magic/1_currencies_have_symbols.rb +12 -0
  302. data/test/migrations/missing/1000_people_have_middle_names.rb +9 -0
  303. data/test/migrations/missing/1_people_have_last_names.rb +9 -0
  304. data/test/migrations/missing/3_we_need_reminders.rb +12 -0
  305. data/test/migrations/missing/4_innocent_jointable.rb +12 -0
  306. data/test/migrations/rename/1_we_need_things.rb +11 -0
  307. data/test/migrations/rename/2_rename_things.rb +9 -0
  308. data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -0
  309. data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -0
  310. data/test/migrations/to_copy2/1_create_articles.rb +7 -0
  311. data/test/migrations/to_copy2/2_create_comments.rb +7 -0
  312. data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -0
  313. data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -0
  314. data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -0
  315. data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -0
  316. data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -0
  317. data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -0
  318. data/test/migrations/valid/2_we_need_reminders.rb +12 -0
  319. data/test/migrations/valid/3_innocent_jointable.rb +12 -0
  320. data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -0
  321. data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -0
  322. data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -0
  323. data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -0
  324. data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -0
  325. data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -0
  326. data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -0
  327. data/test/models/admin.rb +5 -0
  328. data/test/models/admin/account.rb +3 -0
  329. data/test/models/admin/randomly_named_c1.rb +3 -0
  330. data/test/models/admin/user.rb +40 -0
  331. data/test/models/aircraft.rb +4 -0
  332. data/test/models/arunit2_model.rb +3 -0
  333. data/test/models/author.rb +212 -0
  334. data/test/models/auto_id.rb +4 -0
  335. data/test/models/autoloadable/extra_firm.rb +2 -0
  336. data/test/models/binary.rb +2 -0
  337. data/test/models/bird.rb +12 -0
  338. data/test/models/book.rb +18 -0
  339. data/test/models/boolean.rb +2 -0
  340. data/test/models/bulb.rb +51 -0
  341. data/test/models/cake_designer.rb +3 -0
  342. data/test/models/car.rb +26 -0
  343. data/test/models/carrier.rb +2 -0
  344. data/test/models/categorization.rb +19 -0
  345. data/test/models/category.rb +35 -0
  346. data/test/models/chef.rb +3 -0
  347. data/test/models/citation.rb +3 -0
  348. data/test/models/club.rb +23 -0
  349. data/test/models/college.rb +10 -0
  350. data/test/models/column.rb +3 -0
  351. data/test/models/column_name.rb +3 -0
  352. data/test/models/comment.rb +64 -0
  353. data/test/models/company.rb +225 -0
  354. data/test/models/company_in_module.rb +98 -0
  355. data/test/models/computer.rb +3 -0
  356. data/test/models/contact.rb +41 -0
  357. data/test/models/contract.rb +20 -0
  358. data/test/models/country.rb +7 -0
  359. data/test/models/course.rb +6 -0
  360. data/test/models/customer.rb +77 -0
  361. data/test/models/customer_carrier.rb +14 -0
  362. data/test/models/dashboard.rb +3 -0
  363. data/test/models/default.rb +2 -0
  364. data/test/models/department.rb +4 -0
  365. data/test/models/developer.rb +252 -0
  366. data/test/models/dog.rb +5 -0
  367. data/test/models/dog_lover.rb +5 -0
  368. data/test/models/doubloon.rb +12 -0
  369. data/test/models/drink_designer.rb +3 -0
  370. data/test/models/edge.rb +5 -0
  371. data/test/models/electron.rb +5 -0
  372. data/test/models/engine.rb +4 -0
  373. data/test/models/entrant.rb +3 -0
  374. data/test/models/essay.rb +5 -0
  375. data/test/models/event.rb +3 -0
  376. data/test/models/eye.rb +37 -0
  377. data/test/models/face.rb +9 -0
  378. data/test/models/friendship.rb +6 -0
  379. data/test/models/guid.rb +2 -0
  380. data/test/models/hotel.rb +6 -0
  381. data/test/models/image.rb +3 -0
  382. data/test/models/interest.rb +5 -0
  383. data/test/models/invoice.rb +4 -0
  384. data/test/models/item.rb +7 -0
  385. data/test/models/job.rb +7 -0
  386. data/test/models/joke.rb +7 -0
  387. data/test/models/keyboard.rb +3 -0
  388. data/test/models/legacy_thing.rb +3 -0
  389. data/test/models/lesson.rb +11 -0
  390. data/test/models/line_item.rb +3 -0
  391. data/test/models/liquid.rb +4 -0
  392. data/test/models/man.rb +11 -0
  393. data/test/models/matey.rb +4 -0
  394. data/test/models/member.rb +41 -0
  395. data/test/models/member_detail.rb +7 -0
  396. data/test/models/member_type.rb +3 -0
  397. data/test/models/membership.rb +35 -0
  398. data/test/models/minimalistic.rb +2 -0
  399. data/test/models/minivan.rb +9 -0
  400. data/test/models/mixed_case_monkey.rb +3 -0
  401. data/test/models/molecule.rb +6 -0
  402. data/test/models/movie.rb +5 -0
  403. data/test/models/order.rb +4 -0
  404. data/test/models/organization.rb +14 -0
  405. data/test/models/owner.rb +34 -0
  406. data/test/models/parrot.rb +29 -0
  407. data/test/models/person.rb +143 -0
  408. data/test/models/personal_legacy_thing.rb +4 -0
  409. data/test/models/pet.rb +15 -0
  410. data/test/models/pirate.rb +92 -0
  411. data/test/models/possession.rb +3 -0
  412. data/test/models/post.rb +264 -0
  413. data/test/models/price_estimate.rb +4 -0
  414. data/test/models/professor.rb +5 -0
  415. data/test/models/project.rb +29 -0
  416. data/test/models/publisher.rb +2 -0
  417. data/test/models/publisher/article.rb +4 -0
  418. data/test/models/publisher/magazine.rb +3 -0
  419. data/test/models/randomly_named_c1.rb +3 -0
  420. data/test/models/rating.rb +4 -0
  421. data/test/models/reader.rb +23 -0
  422. data/test/models/record.rb +2 -0
  423. data/test/models/reference.rb +22 -0
  424. data/test/models/reply.rb +61 -0
  425. data/test/models/ship.rb +33 -0
  426. data/test/models/ship_part.rb +8 -0
  427. data/test/models/shop.rb +17 -0
  428. data/test/models/shop_account.rb +6 -0
  429. data/test/models/speedometer.rb +6 -0
  430. data/test/models/sponsor.rb +7 -0
  431. data/test/models/string_key_object.rb +3 -0
  432. data/test/models/student.rb +4 -0
  433. data/test/models/subject.rb +16 -0
  434. data/test/models/subscriber.rb +8 -0
  435. data/test/models/subscription.rb +4 -0
  436. data/test/models/tag.rb +7 -0
  437. data/test/models/tagging.rb +13 -0
  438. data/test/models/task.rb +5 -0
  439. data/test/models/topic.rb +124 -0
  440. data/test/models/toy.rb +6 -0
  441. data/test/models/traffic_light.rb +4 -0
  442. data/test/models/treasure.rb +14 -0
  443. data/test/models/treaty.rb +7 -0
  444. data/test/models/tyre.rb +11 -0
  445. data/test/models/uuid_child.rb +3 -0
  446. data/test/models/uuid_parent.rb +3 -0
  447. data/test/models/vegetables.rb +24 -0
  448. data/test/models/vehicle.rb +7 -0
  449. data/test/models/vertex.rb +9 -0
  450. data/test/models/warehouse_thing.rb +5 -5
  451. data/test/models/wheel.rb +3 -0
  452. data/test/models/without_table.rb +3 -0
  453. data/test/models/zine.rb +3 -0
  454. data/test/schema/mysql2_specific_schema.rb +58 -0
  455. data/test/schema/mysql_specific_schema.rb +70 -0
  456. data/test/schema/oracle_specific_schema.rb +43 -0
  457. data/test/schema/postgresql_specific_schema.rb +202 -0
  458. data/test/schema/schema.rb +938 -751
  459. data/test/schema/sqlite_specific_schema.rb +22 -0
  460. data/test/support/config.rb +43 -0
  461. data/test/support/connection.rb +22 -0
  462. data/test/support/connection_helper.rb +14 -0
  463. data/test/support/ddl_helper.rb +8 -0
  464. data/test/support/schema_dumping_helper.rb +20 -0
  465. metadata +444 -18
@@ -0,0 +1,82 @@
1
+ require "cases/helper"
2
+ require 'models/post'
3
+ require 'models/comment'
4
+ require 'models/project'
5
+ require 'models/developer'
6
+ require 'models/computer'
7
+ require 'models/company_in_module'
8
+
9
+ class AssociationsExtensionsTest < ActiveRecord::TestCase
10
+ fixtures :projects, :developers, :developers_projects, :comments, :posts
11
+
12
+ def test_extension_on_has_many
13
+ assert_equal comments(:more_greetings), posts(:welcome).comments.find_most_recent
14
+ end
15
+
16
+ def test_extension_on_habtm
17
+ assert_equal projects(:action_controller), developers(:david).projects.find_most_recent
18
+ end
19
+
20
+ def test_named_extension_on_habtm
21
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name.find_most_recent
22
+ end
23
+
24
+ def test_named_two_extensions_on_habtm
25
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_twice.find_most_recent
26
+ assert_equal projects(:active_record), developers(:david).projects_extended_by_name_twice.find_least_recent
27
+ end
28
+
29
+ def test_named_extension_and_block_on_habtm
30
+ assert_equal projects(:action_controller), developers(:david).projects_extended_by_name_and_block.find_most_recent
31
+ assert_equal projects(:active_record), developers(:david).projects_extended_by_name_and_block.find_least_recent
32
+ end
33
+
34
+ def test_extension_with_scopes
35
+ assert_equal comments(:greetings), posts(:welcome).comments.offset(1).find_most_recent
36
+ assert_equal comments(:greetings), posts(:welcome).comments.not_again.find_most_recent
37
+ end
38
+
39
+ def test_marshalling_extensions
40
+ david = developers(:david)
41
+ assert_equal projects(:action_controller), david.projects.find_most_recent
42
+
43
+ marshalled = Marshal.dump(david)
44
+
45
+ # Marshaling an association shouldn't make it unusable by wiping its reflection.
46
+ assert_not_nil david.association(:projects).reflection
47
+
48
+ david_too = Marshal.load(marshalled)
49
+ assert_equal projects(:action_controller), david_too.projects.find_most_recent
50
+ end
51
+
52
+ def test_marshalling_named_extensions
53
+ david = developers(:david)
54
+ assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
55
+
56
+ marshalled = Marshal.dump(david)
57
+ david = Marshal.load(marshalled)
58
+
59
+ assert_equal projects(:action_controller), david.projects_extended_by_name.find_most_recent
60
+ end
61
+
62
+ def test_extension_name
63
+ extend!(Developer)
64
+ extend!(MyApplication::Business::Developer)
65
+
66
+ assert Object.const_get 'DeveloperAssociationNameAssociationExtension'
67
+ assert MyApplication::Business.const_get 'DeveloperAssociationNameAssociationExtension'
68
+ end
69
+
70
+ def test_proxy_association_after_scoped
71
+ post = posts(:welcome)
72
+ assert_equal post.association(:comments), post.comments.the_association
73
+ assert_equal post.association(:comments), post.comments.where('1=1').the_association
74
+ end
75
+
76
+ private
77
+
78
+ def extend!(model)
79
+ builder = ActiveRecord::Associations::Builder::HasMany.new(model, :association_name, nil, {}) { }
80
+ builder.define_extensions(model)
81
+ end
82
+ end
@@ -1,851 +1,932 @@
1
- require "cases/helper"
2
- require 'models/developer'
3
- require 'models/project'
4
- require 'models/company'
5
- require 'models/customer'
6
- require 'models/order'
7
- require 'models/categorization'
8
- require 'models/category'
9
- require 'models/post'
10
- require 'models/author'
11
- require 'models/tag'
12
- require 'models/tagging'
13
- require 'models/parrot'
14
- require 'models/pirate'
15
- require 'models/treasure'
16
- require 'models/price_estimate'
17
- require 'models/club'
18
- require 'models/member'
19
- require 'models/membership'
20
- require 'models/sponsor'
21
- require 'models/country'
22
- require 'models/treaty'
23
- require 'active_support/core_ext/string/conversions'
24
-
25
- class ProjectWithAfterCreateHook < ActiveRecord::Base
26
- self.table_name = 'projects'
27
- has_and_belongs_to_many :developers,
28
- :class_name => "DeveloperForProjectWithAfterCreateHook",
29
- :join_table => "developers_projects",
30
- :foreign_key => "project_id",
31
- :association_foreign_key => "developer_id"
32
-
33
- after_create :add_david
34
-
35
- def add_david
36
- david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
37
- david.projects << self
38
- end
39
- end
40
-
41
- class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
42
- self.table_name = 'developers'
43
- has_and_belongs_to_many :projects,
44
- :class_name => "ProjectWithAfterCreateHook",
45
- :join_table => "developers_projects",
46
- :association_foreign_key => "project_id",
47
- :foreign_key => "developer_id"
48
- end
49
-
50
- class ProjectWithSymbolsForKeys < ActiveRecord::Base
51
- self.table_name = 'projects'
52
- has_and_belongs_to_many :developers,
53
- :class_name => "DeveloperWithSymbolsForKeys",
54
- :join_table => :developers_projects,
55
- :foreign_key => :project_id,
56
- :association_foreign_key => "developer_id"
57
- end
58
-
59
- class DeveloperWithSymbolsForKeys < ActiveRecord::Base
60
- self.table_name = 'developers'
61
- has_and_belongs_to_many :projects,
62
- :class_name => "ProjectWithSymbolsForKeys",
63
- :join_table => :developers_projects,
64
- :association_foreign_key => :project_id,
65
- :foreign_key => "developer_id"
66
- end
67
-
68
- class DeveloperWithCounterSQL < ActiveRecord::Base
69
- self.table_name = 'developers'
70
- has_and_belongs_to_many :projects,
71
- :class_name => "DeveloperWithCounterSQL",
72
- :join_table => "developers_projects",
73
- :association_foreign_key => "project_id",
74
- :foreign_key => "developer_id",
75
- :counter_sql => proc { "SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}" }
76
- end
77
-
78
- class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
79
- fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
80
- :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings
81
-
82
- def setup_data_for_habtm_case
83
- ActiveRecord::Base.connection.execute('delete from countries_treaties')
84
-
85
- country = Country.new(:name => 'India')
86
- country.country_id = 'c1'
87
- country.save!
88
-
89
- treaty = Treaty.new(:name => 'peace')
90
- treaty.treaty_id = 't1'
91
- country.treaties << treaty
92
- end
93
-
94
- def test_should_property_quote_string_primary_keys
95
- setup_data_for_habtm_case
96
-
97
- con = ActiveRecord::Base.connection
98
- sql = 'select * from countries_treaties'
99
- record = con.select_rows(sql).last
100
- assert_equal 'c1', record[0]
101
- assert_equal 't1', record[1]
102
- end
103
-
104
- def test_proper_usage_of_primary_keys_and_join_table
105
- setup_data_for_habtm_case
106
-
107
- assert_equal 'country_id', Country.primary_key
108
- assert_equal 'treaty_id', Treaty.primary_key
109
-
110
- country = Country.first
111
- assert_equal 1, country.treaties.count
112
- end
113
-
114
- def test_has_and_belongs_to_many
115
- david = Developer.find(1)
116
-
117
- assert !david.projects.empty?
118
- assert_equal 2, david.projects.size
119
-
120
- active_record = Project.find(1)
121
- assert !active_record.developers.empty?
122
- assert_equal 3, active_record.developers.size
123
- assert active_record.developers.include?(david)
124
- end
125
-
126
- def test_triple_equality
127
- assert !(Array === Developer.find(1).projects)
128
- assert Developer.find(1).projects === Array
129
- end
130
-
131
- def test_adding_single
132
- jamis = Developer.find(2)
133
- jamis.projects.reload # causing the collection to load
134
- action_controller = Project.find(2)
135
- assert_equal 1, jamis.projects.size
136
- assert_equal 1, action_controller.developers.size
137
-
138
- jamis.projects << action_controller
139
-
140
- assert_equal 2, jamis.projects.size
141
- assert_equal 2, jamis.projects(true).size
142
- assert_equal 2, action_controller.developers(true).size
143
- end
144
-
145
- def test_adding_type_mismatch
146
- jamis = Developer.find(2)
147
- assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
148
- assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
149
- end
150
-
151
- def test_adding_from_the_project
152
- jamis = Developer.find(2)
153
- action_controller = Project.find(2)
154
- action_controller.developers.reload
155
- assert_equal 1, jamis.projects.size
156
- assert_equal 1, action_controller.developers.size
157
-
158
- action_controller.developers << jamis
159
-
160
- assert_equal 2, jamis.projects(true).size
161
- assert_equal 2, action_controller.developers.size
162
- assert_equal 2, action_controller.developers(true).size
163
- end
164
-
165
- def test_adding_from_the_project_fixed_timestamp
166
- jamis = Developer.find(2)
167
- action_controller = Project.find(2)
168
- action_controller.developers.reload
169
- assert_equal 1, jamis.projects.size
170
- assert_equal 1, action_controller.developers.size
171
- updated_at = jamis.updated_at
172
-
173
- action_controller.developers << jamis
174
-
175
- assert_equal updated_at, jamis.updated_at
176
- assert_equal 2, jamis.projects(true).size
177
- assert_equal 2, action_controller.developers.size
178
- assert_equal 2, action_controller.developers(true).size
179
- end
180
-
181
- def test_adding_multiple
182
- aredridel = Developer.new("name" => "Aredridel")
183
- aredridel.save
184
- aredridel.projects.reload
185
- aredridel.projects.push(Project.find(1), Project.find(2))
186
- assert_equal 2, aredridel.projects.size
187
- assert_equal 2, aredridel.projects(true).size
188
- end
189
-
190
- def test_adding_a_collection
191
- aredridel = Developer.new("name" => "Aredridel")
192
- aredridel.save
193
- aredridel.projects.reload
194
- aredridel.projects.concat([Project.find(1), Project.find(2)])
195
- assert_equal 2, aredridel.projects.size
196
- assert_equal 2, aredridel.projects(true).size
197
- end
198
-
199
- def test_habtm_adding_before_save
200
- no_of_devels = Developer.count
201
- no_of_projects = Project.count
202
- aredridel = Developer.new("name" => "Aredridel")
203
- aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
204
- assert !aredridel.persisted?
205
- assert !p.persisted?
206
- assert aredridel.save
207
- assert aredridel.persisted?
208
- assert_equal no_of_devels+1, Developer.count
209
- assert_equal no_of_projects+1, Project.count
210
- assert_equal 2, aredridel.projects.size
211
- assert_equal 2, aredridel.projects(true).size
212
- end
213
-
214
- def test_habtm_saving_multiple_relationships
215
- new_project = Project.new("name" => "Grimetime")
216
- amount_of_developers = 4
217
- developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
218
-
219
- new_project.developer_ids = [developers[0].id, developers[1].id]
220
- new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
221
- assert new_project.save
222
-
223
- new_project.reload
224
- assert_equal amount_of_developers, new_project.developers.size
225
- assert_equal developers, new_project.developers
226
- end
227
-
228
- def test_habtm_unique_order_preserved
229
- assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
230
- assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
231
- end
232
-
233
- def test_build
234
- devel = Developer.find(1)
235
- proj = assert_no_queries { devel.projects.build("name" => "Projekt") }
236
- assert !devel.projects.loaded?
237
-
238
- assert_equal devel.projects.last, proj
239
- assert devel.projects.loaded?
240
-
241
- assert !proj.persisted?
242
- devel.save
243
- assert proj.persisted?
244
- assert_equal devel.projects.last, proj
245
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
246
- end
247
-
248
- def test_new_aliased_to_build
249
- devel = Developer.find(1)
250
- proj = assert_no_queries { devel.projects.new("name" => "Projekt") }
251
- assert !devel.projects.loaded?
252
-
253
- assert_equal devel.projects.last, proj
254
- assert devel.projects.loaded?
255
-
256
- assert !proj.persisted?
257
- devel.save
258
- assert proj.persisted?
259
- assert_equal devel.projects.last, proj
260
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
261
- end
262
-
263
- def test_build_by_new_record
264
- devel = Developer.new(:name => "Marcel", :salary => 75000)
265
- devel.projects.build(:name => "Make bed")
266
- proj2 = devel.projects.build(:name => "Lie in it")
267
- assert_equal devel.projects.last, proj2
268
- assert !proj2.persisted?
269
- devel.save
270
- assert devel.persisted?
271
- assert proj2.persisted?
272
- assert_equal devel.projects.last, proj2
273
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
274
- end
275
-
276
- def test_create
277
- devel = Developer.find(1)
278
- proj = devel.projects.create("name" => "Projekt")
279
- assert !devel.projects.loaded?
280
-
281
- assert_equal devel.projects.last, proj
282
- assert !devel.projects.loaded?
283
-
284
- assert proj.persisted?
285
- assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
286
- end
287
-
288
- def test_create_by_new_record
289
- devel = Developer.new(:name => "Marcel", :salary => 75000)
290
- devel.projects.build(:name => "Make bed")
291
- proj2 = devel.projects.build(:name => "Lie in it")
292
- assert_equal devel.projects.last, proj2
293
- assert !proj2.persisted?
294
- devel.save
295
- assert devel.persisted?
296
- assert proj2.persisted?
297
- assert_equal devel.projects.last, proj2
298
- assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
299
- end
300
-
301
- def test_creation_respects_hash_condition
302
- # in Oracle '' is saved as null therefore need to save ' ' in not null column
303
- post = categories(:general).post_with_conditions.build(:body => ' ')
304
-
305
- assert post.save
306
- assert_equal 'Yet Another Testing Title', post.title
307
-
308
- # in Oracle '' is saved as null therefore need to save ' ' in not null column
309
- another_post = categories(:general).post_with_conditions.create(:body => ' ')
310
-
311
- assert another_post.persisted?
312
- assert_equal 'Yet Another Testing Title', another_post.title
313
- end
314
-
315
- def test_uniq_after_the_fact
316
- dev = developers(:jamis)
317
- dev.projects << projects(:active_record)
318
- dev.projects << projects(:active_record)
319
-
320
- assert_equal 3, dev.projects.size
321
- assert_equal 1, dev.projects.uniq.size
322
- end
323
-
324
- def test_uniq_before_the_fact
325
- projects(:active_record).developers << developers(:jamis)
326
- projects(:active_record).developers << developers(:david)
327
- assert_equal 3, projects(:active_record, :reload).developers.size
328
- end
329
-
330
- def test_uniq_option_prevents_duplicate_push
331
- project = projects(:active_record)
332
- project.developers << developers(:jamis)
333
- project.developers << developers(:david)
334
- assert_equal 3, project.developers.size
335
-
336
- project.developers << developers(:david)
337
- project.developers << developers(:jamis)
338
- assert_equal 3, project.developers.size
339
- end
340
-
341
- def test_deleting
342
- david = Developer.find(1)
343
- active_record = Project.find(1)
344
- david.projects.reload
345
- assert_equal 2, david.projects.size
346
- assert_equal 3, active_record.developers.size
347
-
348
- david.projects.delete(active_record)
349
-
350
- assert_equal 1, david.projects.size
351
- assert_equal 1, david.projects(true).size
352
- assert_equal 2, active_record.developers(true).size
353
- end
354
-
355
- def test_deleting_array
356
- david = Developer.find(1)
357
- david.projects.reload
358
- david.projects.delete(Project.find(:all))
359
- assert_equal 0, david.projects.size
360
- assert_equal 0, david.projects(true).size
361
- end
362
-
363
- def test_deleting_with_sql
364
- david = Developer.find(1)
365
- active_record = Project.find(1)
366
- active_record.developers.reload
367
- assert_equal 3, active_record.developers_by_sql.size
368
-
369
- active_record.developers_by_sql.delete(david)
370
- assert_equal 2, active_record.developers_by_sql(true).size
371
- end
372
-
373
- def test_deleting_array_with_sql
374
- active_record = Project.find(1)
375
- active_record.developers.reload
376
- assert_equal 3, active_record.developers_by_sql.size
377
-
378
- active_record.developers_by_sql.delete(Developer.find(:all))
379
- assert_equal 0, active_record.developers_by_sql(true).size
380
- end
381
-
382
- def test_deleting_all
383
- david = Developer.find(1)
384
- david.projects.reload
385
- david.projects.clear
386
- assert_equal 0, david.projects.size
387
- assert_equal 0, david.projects(true).size
388
- end
389
-
390
- def test_removing_associations_on_destroy
391
- david = DeveloperWithBeforeDestroyRaise.find(1)
392
- assert !david.projects.empty?
393
- david.destroy
394
- assert david.projects.empty?
395
- assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
396
- end
397
-
398
- def test_destroying
399
- david = Developer.find(1)
400
- project = Project.find(1)
401
- david.projects.reload
402
- assert_equal 2, david.projects.size
403
- assert_equal 3, project.developers.size
404
-
405
- assert_no_difference "Project.count" do
406
- david.projects.destroy(project)
407
- end
408
-
409
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id} AND project_id = #{project.id}")
410
- assert join_records.empty?
411
-
412
- assert_equal 1, david.reload.projects.size
413
- assert_equal 1, david.projects(true).size
414
- end
415
-
416
- def test_destroying_many
417
- david = Developer.find(1)
418
- david.projects.reload
419
- projects = Project.all
420
-
421
- assert_no_difference "Project.count" do
422
- david.projects.destroy(*projects)
423
- end
424
-
425
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
426
- assert join_records.empty?
427
-
428
- assert_equal 0, david.reload.projects.size
429
- assert_equal 0, david.projects(true).size
430
- end
431
-
432
- def test_destroy_all
433
- david = Developer.find(1)
434
- david.projects.reload
435
- assert !david.projects.empty?
436
-
437
- assert_no_difference "Project.count" do
438
- david.projects.destroy_all
439
- end
440
-
441
- join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
442
- assert join_records.empty?
443
-
444
- assert david.projects.empty?
445
- assert david.projects(true).empty?
446
- end
447
-
448
- def test_destroy_associations_destroys_multiple_associations
449
- george = parrots(:george)
450
- assert !george.pirates.empty?
451
- assert !george.treasures.empty?
452
-
453
- assert_no_difference "Pirate.count" do
454
- assert_no_difference "Treasure.count" do
455
- george.destroy_associations
456
- end
457
- end
458
-
459
- join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
460
- assert join_records.empty?
461
- assert george.pirates(true).empty?
462
-
463
- join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
464
- assert join_records.empty?
465
- assert george.treasures(true).empty?
466
- end
467
-
468
- def test_deprecated_push_with_attributes_was_removed
469
- jamis = developers(:jamis)
470
- assert_raise(NoMethodError) do
471
- jamis.projects.push_with_attributes(projects(:action_controller), :joined_on => Date.today)
472
- end
473
- end
474
-
475
- def test_associations_with_conditions
476
- assert_equal 3, projects(:active_record).developers.size
477
- assert_equal 1, projects(:active_record).developers_named_david.size
478
- assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
479
-
480
- assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
481
- assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
482
- assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
483
-
484
- projects(:active_record).developers_named_david.clear
485
- assert_equal 2, projects(:active_record, :reload).developers.size
486
- end
487
-
488
- def test_find_in_association
489
- # Using sql
490
- assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
491
-
492
- # Using ruby
493
- active_record = projects(:active_record)
494
- active_record.developers.reload
495
- assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
496
- end
497
-
498
- def test_include_uses_array_include_after_loaded
499
- project = projects(:active_record)
500
- project.developers.class # force load target
501
-
502
- developer = project.developers.first
503
-
504
- assert_no_queries do
505
- assert project.developers.loaded?
506
- assert project.developers.include?(developer)
507
- end
508
- end
509
-
510
- def test_include_checks_if_record_exists_if_target_not_loaded
511
- project = projects(:active_record)
512
- developer = project.developers.first
513
-
514
- project.reload
515
- assert ! project.developers.loaded?
516
- assert_queries(1) do
517
- assert project.developers.include?(developer)
518
- end
519
- assert ! project.developers.loaded?
520
- end
521
-
522
- def test_include_returns_false_for_non_matching_record_to_verify_scoping
523
- project = projects(:active_record)
524
- developer = Developer.create :name => "Bryan", :salary => 50_000
525
-
526
- assert ! project.developers.loaded?
527
- assert ! project.developers.include?(developer)
528
- end
529
-
530
- def test_find_in_association_with_custom_finder_sql
531
- assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id), "SQL find"
532
-
533
- active_record = projects(:active_record)
534
- active_record.developers_with_finder_sql.reload
535
- assert_equal developers(:david), active_record.developers_with_finder_sql.find(developers(:david).id), "Ruby find"
536
- end
537
-
538
- def test_find_in_association_with_custom_finder_sql_and_multiple_interpolations
539
- # interpolate once:
540
- assert_equal [developers(:david), developers(:jamis), developers(:poor_jamis)], projects(:active_record).developers_with_finder_sql, "first interpolation"
541
- # interpolate again, for a different project id
542
- assert_equal [developers(:david)], projects(:action_controller).developers_with_finder_sql, "second interpolation"
543
- end
544
-
545
- def test_find_in_association_with_custom_finder_sql_and_string_id
546
- assert_equal developers(:david), projects(:active_record).developers_with_finder_sql.find(developers(:david).id.to_s), "SQL find"
547
- end
548
-
549
- def test_find_with_merged_options
550
- assert_equal 1, projects(:active_record).limited_developers.size
551
- assert_equal 1, projects(:active_record).limited_developers.find(:all).size
552
- assert_equal 3, projects(:active_record).limited_developers.find(:all, :limit => nil).size
553
- end
554
-
555
- def test_dynamic_find_should_respect_association_order
556
- # Developers are ordered 'name DESC, id DESC'
557
- high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
558
-
559
- assert_equal high_id_jamis, projects(:active_record).developers.find(:first, :conditions => "name = 'Jamis'")
560
- assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
561
- end
562
-
563
- def test_dynamic_find_all_should_respect_association_order
564
- # Developers are ordered 'name DESC, id DESC'
565
- low_id_jamis = developers(:jamis)
566
- middle_id_jamis = developers(:poor_jamis)
567
- high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
568
-
569
- assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find(:all, :conditions => "name = 'Jamis'")
570
- assert_equal [high_id_jamis, middle_id_jamis, low_id_jamis], projects(:active_record).developers.find_all_by_name('Jamis')
571
- end
572
-
573
- def test_find_should_append_to_association_order
574
- ordered_developers = projects(:active_record).developers.order('projects.id')
575
- assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
576
- end
577
-
578
- def test_dynamic_find_all_should_respect_association_limit
579
- assert_equal 1, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'").length
580
- assert_equal 1, projects(:active_record).limited_developers.find_all_by_name('Jamis').length
581
- end
582
-
583
- def test_dynamic_find_all_order_should_override_association_limit
584
- assert_equal 2, projects(:active_record).limited_developers.find(:all, :conditions => "name = 'Jamis'", :limit => 9_000).length
585
- assert_equal 2, projects(:active_record).limited_developers.find_all_by_name('Jamis', :limit => 9_000).length
586
- end
587
-
588
- def test_dynamic_find_all_should_respect_readonly_access
589
- projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
590
- projects(:active_record).readonly_developers.each { |d| d.readonly? }
591
- end
592
-
593
- def test_new_with_values_in_collection
594
- jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
595
- david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
596
- project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
597
- project.developers << jamis
598
- project.save!
599
- project.reload
600
-
601
- assert project.developers.include?(jamis)
602
- assert project.developers.include?(david)
603
- end
604
-
605
- def test_find_in_association_with_options
606
- developers = projects(:active_record).developers.all
607
- assert_equal 3, developers.size
608
-
609
- assert_equal developers(:poor_jamis), projects(:active_record).developers.where("salary < 10000").first
610
- end
611
-
612
- def test_replace_with_less
613
- david = developers(:david)
614
- david.projects = [projects(:action_controller)]
615
- assert david.save
616
- assert_equal 1, david.projects.length
617
- end
618
-
619
- def test_replace_with_new
620
- david = developers(:david)
621
- david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
622
- david.save
623
- assert_equal 2, david.projects.length
624
- assert !david.projects.include?(projects(:active_record))
625
- end
626
-
627
- def test_replace_on_new_object
628
- new_developer = Developer.new("name" => "Matz")
629
- new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
630
- new_developer.save
631
- assert_equal 2, new_developer.projects.length
632
- end
633
-
634
- def test_consider_type
635
- developer = Developer.find(:first)
636
- special_project = SpecialProject.create("name" => "Special Project")
637
-
638
- other_project = developer.projects.first
639
- developer.special_projects << special_project
640
- developer.reload
641
-
642
- assert developer.projects.include?(special_project)
643
- assert developer.special_projects.include?(special_project)
644
- assert !developer.special_projects.include?(other_project)
645
- end
646
-
647
- def test_update_attributes_after_push_without_duplicate_join_table_rows
648
- developer = Developer.new("name" => "Kano")
649
- project = SpecialProject.create("name" => "Special Project")
650
- assert developer.save
651
- developer.projects << project
652
- developer.update_column("name", "Bruza")
653
- assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
654
- SELECT count(*) FROM developers_projects
655
- WHERE project_id = #{project.id}
656
- AND developer_id = #{developer.id}
657
- end_sql
658
- end
659
-
660
- def test_updating_attributes_on_non_rich_associations
661
- welcome = categories(:technology).posts.first
662
- welcome.title = "Something else"
663
- assert welcome.save!
664
- end
665
-
666
- def test_habtm_respects_select
667
- categories(:technology).select_testing_posts(true).each do |o|
668
- assert_respond_to o, :correctness_marker
669
- end
670
- assert_respond_to categories(:technology).select_testing_posts.find(:first), :correctness_marker
671
- end
672
-
673
- def test_habtm_selects_all_columns_by_default
674
- assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
675
- end
676
-
677
- def test_habtm_respects_select_query_method
678
- assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
679
- end
680
-
681
- def test_join_table_alias
682
- assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL').size
683
- end
684
-
685
- def test_join_with_group
686
- group = Developer.columns.inject([]) do |g, c|
687
- g << "developers.#{c.name}"
688
- g << "developers_projects_2.#{c.name}"
689
- end
690
- Project.columns.each { |c| group << "projects.#{c.name}" }
691
-
692
- assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
693
- end
694
-
695
- def test_find_grouped
696
- all_posts_from_category1 = Post.find(:all, :conditions => "category_id = 1", :joins => :categories)
697
- grouped_posts_of_category1 = Post.find(:all, :conditions => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories)
698
- assert_equal 5, all_posts_from_category1.size
699
- assert_equal 2, grouped_posts_of_category1.size
700
- end
701
-
702
- def test_find_scoped_grouped
703
- assert_equal 5, categories(:general).posts_grouped_by_title.size
704
- assert_equal 1, categories(:technology).posts_grouped_by_title.size
705
- end
706
-
707
- def test_find_scoped_grouped_having
708
- assert_equal 2, projects(:active_record).well_payed_salary_groups.size
709
- assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
710
- end
711
-
712
- def test_get_ids
713
- assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
714
- assert_equal [projects(:active_record).id], developers(:jamis).project_ids
715
- end
716
-
717
- def test_get_ids_for_loaded_associations
718
- developer = developers(:david)
719
- developer.projects(true)
720
- assert_queries(0) do
721
- developer.project_ids
722
- developer.project_ids
723
- end
724
- end
725
-
726
- def test_get_ids_for_unloaded_associations_does_not_load_them
727
- developer = developers(:david)
728
- assert !developer.projects.loaded?
729
- assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
730
- assert !developer.projects.loaded?
731
- end
732
-
733
- def test_assign_ids
734
- developer = Developer.new("name" => "Joe")
735
- developer.project_ids = projects(:active_record, :action_controller).map(&:id)
736
- developer.save
737
- developer.reload
738
- assert_equal 2, developer.projects.length
739
- assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
740
- end
741
-
742
- def test_assign_ids_ignoring_blanks
743
- developer = Developer.new("name" => "Joe")
744
- developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
745
- developer.save
746
- developer.reload
747
- assert_equal 2, developer.projects.length
748
- assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
749
- end
750
-
751
- def test_scoped_find_on_through_association_doesnt_return_read_only_records
752
- tag = Post.find(1).tags.find_by_name("General")
753
-
754
- assert_nothing_raised do
755
- tag.save!
756
- end
757
- end
758
-
759
- def test_has_many_through_polymorphic_has_manys_works
760
- assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
761
- end
762
-
763
- def test_symbols_as_keys
764
- developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
765
- project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
766
- project.developers << developer
767
- project.save!
768
-
769
- assert_equal 1, project.developers.size
770
- assert_equal 1, developer.projects.size
771
- assert_equal developer, project.developers.find(:first)
772
- assert_equal project, developer.projects.find(:first)
773
- end
774
-
775
- def test_self_referential_habtm_without_foreign_key_set_should_raise_exception
776
- assert_raise(ActiveRecord::HasAndBelongsToManyAssociationForeignKeyNeeded) {
777
- Member.class_eval do
778
- has_and_belongs_to_many :friends, :class_name => "Member", :join_table => "member_friends"
779
- end
780
- }
781
- end
782
-
783
- def test_dynamic_find_should_respect_association_include
784
- # SQL error in sort clause if :include is not included
785
- # due to Unknown column 'authors.id'
786
- assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
787
- end
788
-
789
- def test_counting_on_habtm_association_and_not_array
790
- david = Developer.find(1)
791
- # Extra parameter just to make sure we aren't falling back to
792
- # Array#count in Ruby >=1.8.7, which would raise an ArgumentError
793
- assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
794
- end
795
-
796
- def test_count
797
- david = Developer.find(1)
798
- assert_equal 2, david.projects.count
799
- end
800
-
801
- def test_count_with_counter_sql
802
- developer = DeveloperWithCounterSQL.create(:name => 'tekin')
803
- developer.project_ids = [projects(:active_record).id]
804
- developer.save
805
- developer.reload
806
- assert_equal 1, developer.projects.count
807
- end
808
-
809
- unless current_adapter?(:PostgreSQLAdapter, :IBM_DBAdapter)
810
- def test_count_with_finder_sql
811
- assert_equal 3, projects(:active_record).developers_with_finder_sql.count
812
- assert_equal 3, projects(:active_record).developers_with_multiline_finder_sql.count
813
- end
814
- end
815
-
816
- def test_association_proxy_transaction_method_starts_transaction_in_association_class
817
- Post.expects(:transaction)
818
- Category.find(:first).posts.transaction do
819
- # nothing
820
- end
821
- end
822
-
823
- def test_caching_of_columns
824
- david = Developer.find(1)
825
- # clear cache possibly created by other tests
826
- david.projects.reset_column_information
827
-
828
- assert_queries(1) { david.projects.columns; david.projects.columns }
829
-
830
- ## and again to verify that reset_column_information clears the cache correctly
831
- david.projects.reset_column_information
832
- assert_queries(1) { david.projects.columns; david.projects.columns }
833
- end
834
-
835
- def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause
836
- new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
837
- assert_equal new_developer.name, "Marcelo"
838
- end
839
-
840
- def test_attributes_are_being_set_when_initialized_from_habm_association_with_multiple_where_clauses
841
- new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
842
- assert_equal new_developer.name, "Marcelo"
843
- assert_equal new_developer.salary, 90_000
844
- end
845
-
846
- def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build
847
- project = Project.new
848
- developer = project.developers.build
849
- assert project.developers.include?(developer)
850
- end
851
- end
1
+ require "cases/helper"
2
+ require 'models/developer'
3
+ require 'models/computer'
4
+ require 'models/project'
5
+ require 'models/company'
6
+ require 'models/course'
7
+ require 'models/customer'
8
+ require 'models/order'
9
+ require 'models/categorization'
10
+ require 'models/category'
11
+ require 'models/post'
12
+ require 'models/author'
13
+ require 'models/tag'
14
+ require 'models/tagging'
15
+ require 'models/parrot'
16
+ require 'models/person'
17
+ require 'models/pirate'
18
+ require 'models/professor'
19
+ require 'models/treasure'
20
+ require 'models/price_estimate'
21
+ require 'models/club'
22
+ require 'models/member'
23
+ require 'models/membership'
24
+ require 'models/sponsor'
25
+ require 'models/country'
26
+ require 'models/treaty'
27
+ require 'models/vertex'
28
+ require 'models/publisher'
29
+ require 'models/publisher/article'
30
+ require 'models/publisher/magazine'
31
+ require 'active_support/core_ext/string/conversions'
32
+
33
+ class ProjectWithAfterCreateHook < ActiveRecord::Base
34
+ self.table_name = 'projects'
35
+ has_and_belongs_to_many :developers,
36
+ :class_name => "DeveloperForProjectWithAfterCreateHook",
37
+ :join_table => "developers_projects",
38
+ :foreign_key => "project_id",
39
+ :association_foreign_key => "developer_id"
40
+
41
+ after_create :add_david
42
+
43
+ def add_david
44
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
45
+ david.projects << self
46
+ end
47
+ end
48
+
49
+ class DeveloperForProjectWithAfterCreateHook < ActiveRecord::Base
50
+ self.table_name = 'developers'
51
+ has_and_belongs_to_many :projects,
52
+ :class_name => "ProjectWithAfterCreateHook",
53
+ :join_table => "developers_projects",
54
+ :association_foreign_key => "project_id",
55
+ :foreign_key => "developer_id"
56
+ end
57
+
58
+ class ProjectWithSymbolsForKeys < ActiveRecord::Base
59
+ self.table_name = 'projects'
60
+ has_and_belongs_to_many :developers,
61
+ :class_name => "DeveloperWithSymbolsForKeys",
62
+ :join_table => :developers_projects,
63
+ :foreign_key => :project_id,
64
+ :association_foreign_key => "developer_id"
65
+ end
66
+
67
+ class DeveloperWithSymbolsForKeys < ActiveRecord::Base
68
+ self.table_name = 'developers'
69
+ has_and_belongs_to_many :projects,
70
+ :class_name => "ProjectWithSymbolsForKeys",
71
+ :join_table => :developers_projects,
72
+ :association_foreign_key => :project_id,
73
+ :foreign_key => "developer_id"
74
+ end
75
+
76
+ class SubDeveloper < Developer
77
+ self.table_name = 'developers'
78
+ has_and_belongs_to_many :special_projects,
79
+ :join_table => 'developers_projects',
80
+ :foreign_key => "project_id",
81
+ :association_foreign_key => "developer_id"
82
+ end
83
+
84
+ class DeveloperWithSymbolClassName < Developer
85
+ has_and_belongs_to_many :projects, class_name: :ProjectWithSymbolsForKeys
86
+ end
87
+
88
+ class DeveloperWithExtendOption < Developer
89
+ module NamedExtension
90
+ def category
91
+ 'sns'
92
+ end
93
+ end
94
+
95
+ has_and_belongs_to_many :projects, extend: NamedExtension
96
+ end
97
+
98
+ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
99
+ fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
100
+ :parrots, :pirates, :parrots_pirates, :treasures, :price_estimates, :tags, :taggings, :computers
101
+
102
+ def setup_data_for_habtm_case
103
+ ActiveRecord::Base.connection.execute('delete from countries_treaties')
104
+
105
+ country = Country.new(:name => 'India')
106
+ country.country_id = 'c1'
107
+ country.save!
108
+
109
+ treaty = Treaty.new(:name => 'peace')
110
+ treaty.treaty_id = 't1'
111
+ country.treaties << treaty
112
+ end
113
+
114
+ def test_marshal_dump
115
+ post = posts :welcome
116
+ preloaded = Post.includes(:categories).find post.id
117
+ assert_equal preloaded, Marshal.load(Marshal.dump(preloaded))
118
+ end
119
+
120
+ def test_should_property_quote_string_primary_keys
121
+ setup_data_for_habtm_case
122
+
123
+ con = ActiveRecord::Base.connection
124
+ sql = 'select * from countries_treaties'
125
+ record = con.select_rows(sql).last
126
+ assert_equal 'c1', record[0]
127
+ assert_equal 't1', record[1]
128
+ end
129
+
130
+ def test_proper_usage_of_primary_keys_and_join_table
131
+ setup_data_for_habtm_case
132
+
133
+ assert_equal 'country_id', Country.primary_key
134
+ assert_equal 'treaty_id', Treaty.primary_key
135
+
136
+ country = Country.first
137
+ assert_equal 1, country.treaties.count
138
+ end
139
+
140
+ def test_has_and_belongs_to_many
141
+ david = Developer.find(1)
142
+
143
+ assert !david.projects.empty?
144
+ assert_equal 2, david.projects.size
145
+
146
+ active_record = Project.find(1)
147
+ assert !active_record.developers.empty?
148
+ assert_equal 3, active_record.developers.size
149
+ assert active_record.developers.include?(david)
150
+ end
151
+
152
+ def test_adding_single
153
+ jamis = Developer.find(2)
154
+ jamis.projects.reload # causing the collection to load
155
+ action_controller = Project.find(2)
156
+ assert_equal 1, jamis.projects.size
157
+ assert_equal 1, action_controller.developers.size
158
+
159
+ jamis.projects << action_controller
160
+
161
+ assert_equal 2, jamis.projects.size
162
+ assert_equal 2, jamis.projects(true).size
163
+ assert_equal 2, action_controller.developers(true).size
164
+ end
165
+
166
+ def test_adding_type_mismatch
167
+ jamis = Developer.find(2)
168
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << nil }
169
+ assert_raise(ActiveRecord::AssociationTypeMismatch) { jamis.projects << 1 }
170
+ end
171
+
172
+ def test_adding_from_the_project
173
+ jamis = Developer.find(2)
174
+ action_controller = Project.find(2)
175
+ action_controller.developers.reload
176
+ assert_equal 1, jamis.projects.size
177
+ assert_equal 1, action_controller.developers.size
178
+
179
+ action_controller.developers << jamis
180
+
181
+ assert_equal 2, jamis.projects(true).size
182
+ assert_equal 2, action_controller.developers.size
183
+ assert_equal 2, action_controller.developers(true).size
184
+ end
185
+
186
+ def test_adding_from_the_project_fixed_timestamp
187
+ jamis = Developer.find(2)
188
+ action_controller = Project.find(2)
189
+ action_controller.developers.reload
190
+ assert_equal 1, jamis.projects.size
191
+ assert_equal 1, action_controller.developers.size
192
+ updated_at = jamis.updated_at
193
+
194
+ action_controller.developers << jamis
195
+
196
+ assert_equal updated_at, jamis.updated_at
197
+ assert_equal 2, jamis.projects(true).size
198
+ assert_equal 2, action_controller.developers.size
199
+ assert_equal 2, action_controller.developers(true).size
200
+ end
201
+
202
+ def test_adding_multiple
203
+ aredridel = Developer.new("name" => "Aredridel")
204
+ aredridel.save
205
+ aredridel.projects.reload
206
+ aredridel.projects.push(Project.find(1), Project.find(2))
207
+ assert_equal 2, aredridel.projects.size
208
+ assert_equal 2, aredridel.projects(true).size
209
+ end
210
+
211
+ def test_adding_a_collection
212
+ aredridel = Developer.new("name" => "Aredridel")
213
+ aredridel.save
214
+ aredridel.projects.reload
215
+ aredridel.projects.concat([Project.find(1), Project.find(2)])
216
+ assert_equal 2, aredridel.projects.size
217
+ assert_equal 2, aredridel.projects(true).size
218
+ end
219
+
220
+ def test_habtm_adding_before_save
221
+ no_of_devels = Developer.count
222
+ no_of_projects = Project.count
223
+ aredridel = Developer.new("name" => "Aredridel")
224
+ aredridel.projects.concat([Project.find(1), p = Project.new("name" => "Projekt")])
225
+ assert !aredridel.persisted?
226
+ assert !p.persisted?
227
+ assert aredridel.save
228
+ assert aredridel.persisted?
229
+ assert_equal no_of_devels+1, Developer.count
230
+ assert_equal no_of_projects+1, Project.count
231
+ assert_equal 2, aredridel.projects.size
232
+ assert_equal 2, aredridel.projects(true).size
233
+ end
234
+
235
+ def test_habtm_saving_multiple_relationships
236
+ new_project = Project.new("name" => "Grimetime")
237
+ amount_of_developers = 4
238
+ developers = (0...amount_of_developers).collect {|i| Developer.create(:name => "JME #{i}") }.reverse
239
+
240
+ new_project.developer_ids = [developers[0].id, developers[1].id]
241
+ new_project.developers_with_callback_ids = [developers[2].id, developers[3].id]
242
+ assert new_project.save
243
+
244
+ new_project.reload
245
+ assert_equal amount_of_developers, new_project.developers.size
246
+ assert_equal developers, new_project.developers
247
+ end
248
+
249
+ def test_habtm_unique_order_preserved
250
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).non_unique_developers
251
+ assert_equal developers(:poor_jamis, :jamis, :david), projects(:active_record).developers
252
+ end
253
+
254
+ def test_habtm_collection_size_from_build
255
+ devel = Developer.create("name" => "Fred Wu")
256
+ devel.projects << Project.create("name" => "Grimetime")
257
+ devel.projects.build
258
+
259
+ assert_equal 2, devel.projects.size
260
+ end
261
+
262
+ def test_habtm_collection_size_from_params
263
+ devel = Developer.new({
264
+ projects_attributes: {
265
+ '0' => {}
266
+ }
267
+ })
268
+
269
+ assert_equal 1, devel.projects.size
270
+ end
271
+
272
+ def test_build
273
+ devel = Developer.find(1)
274
+ proj = assert_no_queries(ignore_none: false) { devel.projects.build("name" => "Projekt") }
275
+ assert !devel.projects.loaded?
276
+
277
+ assert_equal devel.projects.last, proj
278
+ assert devel.projects.loaded?
279
+
280
+ assert !proj.persisted?
281
+ devel.save
282
+ assert proj.persisted?
283
+ assert_equal devel.projects.last, proj
284
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
285
+ end
286
+
287
+ def test_new_aliased_to_build
288
+ devel = Developer.find(1)
289
+ proj = assert_no_queries(ignore_none: false) { devel.projects.new("name" => "Projekt") }
290
+ assert !devel.projects.loaded?
291
+
292
+ assert_equal devel.projects.last, proj
293
+ assert devel.projects.loaded?
294
+
295
+ assert !proj.persisted?
296
+ devel.save
297
+ assert proj.persisted?
298
+ assert_equal devel.projects.last, proj
299
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
300
+ end
301
+
302
+ def test_build_by_new_record
303
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
304
+ devel.projects.build(:name => "Make bed")
305
+ proj2 = devel.projects.build(:name => "Lie in it")
306
+ assert_equal devel.projects.last, proj2
307
+ assert !proj2.persisted?
308
+ devel.save
309
+ assert devel.persisted?
310
+ assert proj2.persisted?
311
+ assert_equal devel.projects.last, proj2
312
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
313
+ end
314
+
315
+ def test_create
316
+ devel = Developer.find(1)
317
+ proj = devel.projects.create("name" => "Projekt")
318
+ assert !devel.projects.loaded?
319
+
320
+ assert_equal devel.projects.last, proj
321
+ assert !devel.projects.loaded?
322
+
323
+ assert proj.persisted?
324
+ assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
325
+ end
326
+
327
+ def test_create_by_new_record
328
+ devel = Developer.new(:name => "Marcel", :salary => 75000)
329
+ devel.projects.build(:name => "Make bed")
330
+ proj2 = devel.projects.build(:name => "Lie in it")
331
+ assert_equal devel.projects.last, proj2
332
+ assert !proj2.persisted?
333
+ devel.save
334
+ assert devel.persisted?
335
+ assert proj2.persisted?
336
+ assert_equal devel.projects.last, proj2
337
+ assert_equal Developer.find_by_name("Marcel").projects.last, proj2 # prove join table is updated
338
+ end
339
+
340
+ def test_creation_respects_hash_condition
341
+ # in Oracle '' is saved as null therefore need to save ' ' in not null column
342
+ post = categories(:general).post_with_conditions.build(:body => ' ')
343
+
344
+ assert post.save
345
+ assert_equal 'Yet Another Testing Title', post.title
346
+
347
+ # in Oracle '' is saved as null therefore need to save ' ' in not null column
348
+ another_post = categories(:general).post_with_conditions.create(:body => ' ')
349
+
350
+ assert another_post.persisted?
351
+ assert_equal 'Yet Another Testing Title', another_post.title
352
+ end
353
+
354
+ def test_uniq_after_the_fact
355
+ dev = developers(:jamis)
356
+ dev.projects << projects(:active_record)
357
+ dev.projects << projects(:active_record)
358
+
359
+ assert_equal 3, dev.projects.size
360
+ assert_equal 1, dev.projects.distinct.size
361
+ end
362
+
363
+ def test_uniq_before_the_fact
364
+ projects(:active_record).developers << developers(:jamis)
365
+ projects(:active_record).developers << developers(:david)
366
+ assert_equal 3, projects(:active_record, :reload).developers.size
367
+ end
368
+
369
+ def test_uniq_option_prevents_duplicate_push
370
+ project = projects(:active_record)
371
+ project.developers << developers(:jamis)
372
+ project.developers << developers(:david)
373
+ assert_equal 3, project.developers.size
374
+
375
+ project.developers << developers(:david)
376
+ project.developers << developers(:jamis)
377
+ assert_equal 3, project.developers.size
378
+ end
379
+
380
+ def test_uniq_when_association_already_loaded
381
+ project = projects(:active_record)
382
+ project.developers << [ developers(:jamis), developers(:david), developers(:jamis), developers(:david) ]
383
+ assert_equal 3, Project.includes(:developers).find(project.id).developers.size
384
+ end
385
+
386
+ def test_deleting
387
+ david = Developer.find(1)
388
+ active_record = Project.find(1)
389
+ david.projects.reload
390
+ assert_equal 2, david.projects.size
391
+ assert_equal 3, active_record.developers.size
392
+
393
+ david.projects.delete(active_record)
394
+
395
+ assert_equal 1, david.projects.size
396
+ assert_equal 1, david.projects(true).size
397
+ assert_equal 2, active_record.developers(true).size
398
+ end
399
+
400
+ def test_deleting_array
401
+ david = Developer.find(1)
402
+ david.projects.reload
403
+ david.projects.delete(Project.all.to_a)
404
+ assert_equal 0, david.projects.size
405
+ assert_equal 0, david.projects(true).size
406
+ end
407
+
408
+ def test_deleting_all
409
+ david = Developer.find(1)
410
+ david.projects.reload
411
+ david.projects.clear
412
+ assert_equal 0, david.projects.size
413
+ assert_equal 0, david.projects(true).size
414
+ end
415
+
416
+ def test_removing_associations_on_destroy
417
+ david = DeveloperWithBeforeDestroyRaise.find(1)
418
+ assert !david.projects.empty?
419
+ david.destroy
420
+ assert david.projects.empty?
421
+ assert DeveloperWithBeforeDestroyRaise.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = 1").empty?
422
+ end
423
+
424
+ def test_destroying
425
+ david = Developer.find(1)
426
+ project = Project.find(1)
427
+ david.projects.reload
428
+ assert_equal 2, david.projects.size
429
+ assert_equal 3, project.developers.size
430
+
431
+ assert_no_difference "Project.count" do
432
+ david.projects.destroy(project)
433
+ end
434
+
435
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id} AND project_id = #{project.id}")
436
+ assert join_records.empty?
437
+
438
+ assert_equal 1, david.reload.projects.size
439
+ assert_equal 1, david.projects(true).size
440
+ end
441
+
442
+ def test_destroying_many
443
+ david = Developer.find(1)
444
+ david.projects.reload
445
+ projects = Project.all.to_a
446
+
447
+ assert_no_difference "Project.count" do
448
+ david.projects.destroy(*projects)
449
+ end
450
+
451
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
452
+ assert join_records.empty?
453
+
454
+ assert_equal 0, david.reload.projects.size
455
+ assert_equal 0, david.projects(true).size
456
+ end
457
+
458
+ def test_destroy_all
459
+ david = Developer.find(1)
460
+ david.projects.reload
461
+ assert !david.projects.empty?
462
+
463
+ assert_no_difference "Project.count" do
464
+ david.projects.destroy_all
465
+ end
466
+
467
+ join_records = Developer.connection.select_all("SELECT * FROM developers_projects WHERE developer_id = #{david.id}")
468
+ assert join_records.empty?
469
+
470
+ assert david.projects.empty?
471
+ assert david.projects(true).empty?
472
+ end
473
+
474
+ def test_destroy_associations_destroys_multiple_associations
475
+ george = parrots(:george)
476
+ assert !george.pirates.empty?
477
+ assert !george.treasures.empty?
478
+
479
+ assert_no_difference "Pirate.count" do
480
+ assert_no_difference "Treasure.count" do
481
+ george.destroy_associations
482
+ end
483
+ end
484
+
485
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_pirates WHERE parrot_id = #{george.id}")
486
+ assert join_records.empty?
487
+ assert george.pirates(true).empty?
488
+
489
+ join_records = Parrot.connection.select_all("SELECT * FROM parrots_treasures WHERE parrot_id = #{george.id}")
490
+ assert join_records.empty?
491
+ assert george.treasures(true).empty?
492
+ end
493
+
494
+ def test_associations_with_conditions
495
+ assert_equal 3, projects(:active_record).developers.size
496
+ assert_equal 1, projects(:active_record).developers_named_david.size
497
+ assert_equal 1, projects(:active_record).developers_named_david_with_hash_conditions.size
498
+
499
+ assert_equal developers(:david), projects(:active_record).developers_named_david.find(developers(:david).id)
500
+ assert_equal developers(:david), projects(:active_record).developers_named_david_with_hash_conditions.find(developers(:david).id)
501
+ assert_equal developers(:david), projects(:active_record).salaried_developers.find(developers(:david).id)
502
+
503
+ projects(:active_record).developers_named_david.clear
504
+ assert_equal 2, projects(:active_record, :reload).developers.size
505
+ end
506
+
507
+ def test_find_in_association
508
+ # Using sql
509
+ assert_equal developers(:david), projects(:active_record).developers.find(developers(:david).id), "SQL find"
510
+
511
+ # Using ruby
512
+ active_record = projects(:active_record)
513
+ active_record.developers.reload
514
+ assert_equal developers(:david), active_record.developers.find(developers(:david).id), "Ruby find"
515
+ end
516
+
517
+ def test_include_uses_array_include_after_loaded
518
+ project = projects(:active_record)
519
+ project.developers.load_target
520
+
521
+ developer = project.developers.first
522
+
523
+ assert_no_queries(ignore_none: false) do
524
+ assert project.developers.loaded?
525
+ assert project.developers.include?(developer)
526
+ end
527
+ end
528
+
529
+ def test_include_checks_if_record_exists_if_target_not_loaded
530
+ project = projects(:active_record)
531
+ developer = project.developers.first
532
+
533
+ project.reload
534
+ assert ! project.developers.loaded?
535
+ assert_queries(1) do
536
+ assert project.developers.include?(developer)
537
+ end
538
+ assert ! project.developers.loaded?
539
+ end
540
+
541
+ def test_include_returns_false_for_non_matching_record_to_verify_scoping
542
+ project = projects(:active_record)
543
+ developer = Developer.create :name => "Bryan", :salary => 50_000
544
+
545
+ assert ! project.developers.loaded?
546
+ assert ! project.developers.include?(developer)
547
+ end
548
+
549
+ def test_find_with_merged_options
550
+ assert_equal 1, projects(:active_record).limited_developers.size
551
+ assert_equal 1, projects(:active_record).limited_developers.to_a.size
552
+ assert_equal 3, projects(:active_record).limited_developers.limit(nil).to_a.size
553
+ end
554
+
555
+ def test_dynamic_find_should_respect_association_order
556
+ # Developers are ordered 'name DESC, id DESC'
557
+ high_id_jamis = projects(:active_record).developers.create(:name => 'Jamis')
558
+
559
+ assert_equal high_id_jamis, projects(:active_record).developers.merge(:where => "name = 'Jamis'").first
560
+ assert_equal high_id_jamis, projects(:active_record).developers.find_by_name('Jamis')
561
+ end
562
+
563
+ def test_find_should_append_to_association_order
564
+ ordered_developers = projects(:active_record).developers.order('projects.id')
565
+ assert_equal ['developers.name desc, developers.id desc', 'projects.id'], ordered_developers.order_values
566
+ end
567
+
568
+ def test_dynamic_find_all_should_respect_readonly_access
569
+ projects(:active_record).readonly_developers.each { |d| assert_raise(ActiveRecord::ReadOnlyRecord) { d.save! } if d.valid?}
570
+ projects(:active_record).readonly_developers.each { |d| d.readonly? }
571
+ end
572
+
573
+ def test_new_with_values_in_collection
574
+ jamis = DeveloperForProjectWithAfterCreateHook.find_by_name('Jamis')
575
+ david = DeveloperForProjectWithAfterCreateHook.find_by_name('David')
576
+ project = ProjectWithAfterCreateHook.new(:name => "Cooking with Bertie")
577
+ project.developers << jamis
578
+ project.save!
579
+ project.reload
580
+
581
+ assert project.developers.include?(jamis)
582
+ assert project.developers.include?(david)
583
+ end
584
+
585
+ def test_find_in_association_with_options
586
+ developers = projects(:active_record).developers.to_a
587
+ assert_equal 3, developers.size
588
+
589
+ assert_equal developers(:poor_jamis), projects(:active_record).developers.where("salary < 10000").first
590
+ end
591
+
592
+ def test_association_with_extend_option
593
+ eponine = DeveloperWithExtendOption.create(name: 'Eponine')
594
+ assert_equal 'sns', eponine.projects.category
595
+ end
596
+
597
+ def test_replace_with_less
598
+ david = developers(:david)
599
+ david.projects = [projects(:action_controller)]
600
+ assert david.save
601
+ assert_equal 1, david.projects.length
602
+ end
603
+
604
+ def test_replace_with_new
605
+ david = developers(:david)
606
+ david.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
607
+ david.save
608
+ assert_equal 2, david.projects.length
609
+ assert !david.projects.include?(projects(:active_record))
610
+ end
611
+
612
+ def test_replace_on_new_object
613
+ new_developer = Developer.new("name" => "Matz")
614
+ new_developer.projects = [projects(:action_controller), Project.new("name" => "ActionWebSearch")]
615
+ new_developer.save
616
+ assert_equal 2, new_developer.projects.length
617
+ end
618
+
619
+ def test_consider_type
620
+ developer = Developer.first
621
+ special_project = SpecialProject.create("name" => "Special Project")
622
+
623
+ other_project = developer.projects.first
624
+ developer.special_projects << special_project
625
+ developer.reload
626
+
627
+ assert developer.projects.include?(special_project)
628
+ assert developer.special_projects.include?(special_project)
629
+ assert !developer.special_projects.include?(other_project)
630
+ end
631
+
632
+ def test_symbol_join_table
633
+ developer = Developer.first
634
+ sp = developer.sym_special_projects.create("name" => "omg")
635
+ developer.reload
636
+ assert_includes developer.sym_special_projects, sp
637
+ end
638
+
639
+ def test_update_attributes_after_push_without_duplicate_join_table_rows
640
+ developer = Developer.new("name" => "Kano")
641
+ project = SpecialProject.create("name" => "Special Project")
642
+ assert developer.save
643
+ developer.projects << project
644
+ developer.update_columns("name" => "Bruza")
645
+ assert_equal 1, Developer.connection.select_value(<<-end_sql).to_i
646
+ SELECT count(*) FROM developers_projects
647
+ WHERE project_id = #{project.id}
648
+ AND developer_id = #{developer.id}
649
+ end_sql
650
+ end
651
+
652
+ def test_updating_attributes_on_non_rich_associations
653
+ welcome = categories(:technology).posts.first
654
+ welcome.title = "Something else"
655
+ assert welcome.save!
656
+ end
657
+
658
+ def test_habtm_respects_select
659
+ categories(:technology).select_testing_posts(true).each do |o|
660
+ assert_respond_to o, :correctness_marker
661
+ end
662
+ assert_respond_to categories(:technology).select_testing_posts.first, :correctness_marker
663
+ end
664
+
665
+ def test_habtm_selects_all_columns_by_default
666
+ assert_equal Project.column_names.sort, developers(:david).projects.first.attributes.keys.sort
667
+ end
668
+
669
+ def test_habtm_respects_select_query_method
670
+ assert_equal ['id'], developers(:david).projects.select(:id).first.attributes.keys
671
+ end
672
+
673
+ def test_join_table_alias
674
+ # FIXME: `references` has no impact on the aliases generated for the join
675
+ # query. The fact that we pass `:developers_projects_join` to `references`
676
+ # and that the SQL string contains `developers_projects_join` is merely a
677
+ # coincidence.
678
+ assert_equal(
679
+ 3,
680
+ Developer.references(:developers_projects_join).merge(
681
+ :includes => {:projects => :developers},
682
+ :where => 'projects_developers_projects_join.joined_on IS NOT NULL'
683
+ ).to_a.size
684
+ )
685
+ end
686
+
687
+ def test_join_with_group
688
+ # FIXME: `references` has no impact on the aliases generated for the join
689
+ # query. The fact that we pass `:developers_projects_join` to `references`
690
+ # and that the SQL string contains `developers_projects_join` is merely a
691
+ # coincidence.
692
+ group = Developer.columns.inject([]) do |g, c|
693
+ g << "developers.#{c.name}"
694
+ g << "developers_projects_2.#{c.name}"
695
+ end
696
+ Project.columns.each { |c| group << "projects.#{c.name}" }
697
+
698
+ assert_equal(
699
+ 3,
700
+ Developer.references(:developers_projects_join).merge(
701
+ :includes => {:projects => :developers}, :where => 'projects_developers_projects_join.joined_on IS NOT NULL',
702
+ :group => group.join(",")
703
+ ).to_a.size
704
+ )
705
+ end
706
+
707
+ def test_find_grouped
708
+ all_posts_from_category1 = Post.all.merge!(:where => "category_id = 1", :joins => :categories).to_a
709
+ grouped_posts_of_category1 = Post.all.merge!(:where => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories).to_a
710
+ assert_equal 5, all_posts_from_category1.size
711
+ assert_equal 2, grouped_posts_of_category1.size
712
+ end
713
+
714
+ def test_find_scoped_grouped
715
+ assert_equal 5, categories(:general).posts_grouped_by_title.to_a.size
716
+ assert_equal 1, categories(:technology).posts_grouped_by_title.to_a.size
717
+ end
718
+
719
+ def test_find_scoped_grouped_having
720
+ assert_equal 2, projects(:active_record).well_payed_salary_groups.to_a.size
721
+ assert projects(:active_record).well_payed_salary_groups.all? { |g| g.salary > 10000 }
722
+ end
723
+
724
+ def test_get_ids
725
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
726
+ assert_equal [projects(:active_record).id], developers(:jamis).project_ids
727
+ end
728
+
729
+ def test_get_ids_for_loaded_associations
730
+ developer = developers(:david)
731
+ developer.projects(true)
732
+ assert_queries(0) do
733
+ developer.project_ids
734
+ developer.project_ids
735
+ end
736
+ end
737
+
738
+ def test_get_ids_for_unloaded_associations_does_not_load_them
739
+ developer = developers(:david)
740
+ assert !developer.projects.loaded?
741
+ assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
742
+ assert !developer.projects.loaded?
743
+ end
744
+
745
+ def test_assign_ids
746
+ developer = Developer.new("name" => "Joe")
747
+ developer.project_ids = projects(:active_record, :action_controller).map(&:id)
748
+ developer.save
749
+ developer.reload
750
+ assert_equal 2, developer.projects.length
751
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
752
+ end
753
+
754
+ def test_assign_ids_ignoring_blanks
755
+ developer = Developer.new("name" => "Joe")
756
+ developer.project_ids = [projects(:active_record).id, nil, projects(:action_controller).id, '']
757
+ developer.save
758
+ developer.reload
759
+ assert_equal 2, developer.projects.length
760
+ assert_equal [projects(:active_record), projects(:action_controller)].map(&:id).sort, developer.project_ids.sort
761
+ end
762
+
763
+ def test_scoped_find_on_through_association_doesnt_return_read_only_records
764
+ tag = Post.find(1).tags.find_by_name("General")
765
+
766
+ assert_nothing_raised do
767
+ tag.save!
768
+ end
769
+ end
770
+
771
+ def test_has_many_through_polymorphic_has_manys_works
772
+ assert_equal [10, 20].to_set, pirates(:redbeard).treasure_estimates.map(&:price).to_set
773
+ end
774
+
775
+ def test_symbols_as_keys
776
+ developer = DeveloperWithSymbolsForKeys.new(:name => 'David')
777
+ project = ProjectWithSymbolsForKeys.new(:name => 'Rails Testing')
778
+ project.developers << developer
779
+ project.save!
780
+
781
+ assert_equal 1, project.developers.size
782
+ assert_equal 1, developer.projects.size
783
+ assert_equal developer, project.developers.first
784
+ assert_equal project, developer.projects.first
785
+ end
786
+
787
+ def test_dynamic_find_should_respect_association_include
788
+ # SQL error in sort clause if :include is not included
789
+ # due to Unknown column 'authors.id'
790
+ assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
791
+ end
792
+
793
+ def test_count
794
+ david = Developer.find(1)
795
+ assert_equal 2, david.projects.count
796
+ end
797
+
798
+ def test_association_proxy_transaction_method_starts_transaction_in_association_class
799
+ Post.expects(:transaction)
800
+ Category.first.posts.transaction do
801
+ # nothing
802
+ end
803
+ end
804
+
805
+ def test_caching_of_columns
806
+ david = Developer.find(1)
807
+ # clear cache possibly created by other tests
808
+ david.projects.reset_column_information
809
+
810
+ assert_queries(:any) { david.projects.columns }
811
+ assert_no_queries { david.projects.columns }
812
+
813
+ ## and again to verify that reset_column_information clears the cache correctly
814
+ david.projects.reset_column_information
815
+
816
+ assert_queries(:any) { david.projects.columns }
817
+ assert_no_queries { david.projects.columns }
818
+ end
819
+
820
+ def test_attributes_are_being_set_when_initialized_from_habm_association_with_where_clause
821
+ new_developer = projects(:action_controller).developers.where(:name => "Marcelo").build
822
+ assert_equal new_developer.name, "Marcelo"
823
+ end
824
+
825
+ def test_attributes_are_being_set_when_initialized_from_habm_association_with_multiple_where_clauses
826
+ new_developer = projects(:action_controller).developers.where(:name => "Marcelo").where(:salary => 90_000).build
827
+ assert_equal new_developer.name, "Marcelo"
828
+ assert_equal new_developer.salary, 90_000
829
+ end
830
+
831
+ def test_include_method_in_has_and_belongs_to_many_association_should_return_true_for_instance_added_with_build
832
+ project = Project.new
833
+ developer = project.developers.build
834
+ assert project.developers.include?(developer)
835
+ end
836
+
837
+ def test_destruction_does_not_error_without_primary_key
838
+ redbeard = pirates(:redbeard)
839
+ george = parrots(:george)
840
+ redbeard.parrots << george
841
+ assert_equal 2, george.pirates.count
842
+ Pirate.includes(:parrots).where(parrot: redbeard.parrot).find(redbeard.id).destroy
843
+ assert_equal 1, george.pirates.count
844
+ assert_equal [], Pirate.where(id: redbeard.id)
845
+ end
846
+
847
+ def test_has_and_belongs_to_many_associations_on_new_records_use_null_relations
848
+ projects = Developer.new.projects
849
+ assert_no_queries(ignore_none: false) do
850
+ assert_equal [], projects
851
+ assert_equal [], projects.where(title: 'omg')
852
+ assert_equal [], projects.pluck(:title)
853
+ assert_equal 0, projects.count
854
+ end
855
+ end
856
+
857
+ def test_association_with_validate_false_does_not_run_associated_validation_callbacks_on_create
858
+ rich_person = RichPerson.new
859
+
860
+ treasure = Treasure.new
861
+ treasure.rich_people << rich_person
862
+ treasure.valid?
863
+
864
+ assert_equal 1, treasure.rich_people.size
865
+ assert_nil rich_person.first_name, 'should not run associated person validation on create when validate: false'
866
+ end
867
+
868
+ def test_association_with_validate_false_does_not_run_associated_validation_callbacks_on_update
869
+ rich_person = RichPerson.create!
870
+ person_first_name = rich_person.first_name
871
+ assert_not_nil person_first_name
872
+
873
+ treasure = Treasure.new
874
+ treasure.rich_people << rich_person
875
+ treasure.valid?
876
+
877
+ assert_equal 1, treasure.rich_people.size
878
+ assert_equal person_first_name, rich_person.first_name, 'should not run associated person validation on update when validate: false'
879
+ end
880
+
881
+ def test_custom_join_table
882
+ assert_equal 'edges', Vertex.reflect_on_association(:sources).join_table
883
+ end
884
+
885
+ def test_has_and_belongs_to_many_in_a_namespaced_model_pointing_to_a_namespaced_model
886
+ magazine = Publisher::Magazine.create
887
+ article = Publisher::Article.create
888
+ magazine.articles << article
889
+ magazine.save
890
+
891
+ assert_includes magazine.articles, article
892
+ end
893
+
894
+ def test_has_and_belongs_to_many_in_a_namespaced_model_pointing_to_a_non_namespaced_model
895
+ article = Publisher::Article.create
896
+ tag = Tag.create
897
+ article.tags << tag
898
+ article.save
899
+
900
+ assert_includes article.tags, tag
901
+ end
902
+
903
+ def test_redefine_habtm
904
+ child = SubDeveloper.new("name" => "Aredridel")
905
+ child.special_projects << SpecialProject.new("name" => "Special Project")
906
+ assert child.save, 'child object should be saved'
907
+ end
908
+
909
+ def test_habtm_with_reflection_using_class_name_and_fixtures
910
+ assert_not_nil Developer._reflections['shared_computers']
911
+ # Checking the fixture for named association is important here, because it's the only way
912
+ # we've been able to reproduce this bug
913
+ assert_not_nil File.read(File.expand_path("../../../fixtures/developers.yml", __FILE__)).index("shared_computers")
914
+ assert_equal developers(:david).shared_computers.first, computers(:laptop)
915
+ end
916
+
917
+ def test_with_symbol_class_name
918
+ assert_nothing_raised NoMethodError do
919
+ DeveloperWithSymbolClassName.new
920
+ end
921
+ end
922
+
923
+ def test_alternate_database
924
+ professor = Professor.create(name: "Plum")
925
+ course = Course.create(name: "Forensics")
926
+ assert_equal 0, professor.courses.count
927
+ assert_nothing_raised do
928
+ professor.courses << course
929
+ end
930
+ assert_equal 1, professor.courses.count
931
+ end
932
+ end