activerecord 4.2.0 → 6.1.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1221 -796
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +267 -249
  8. data/lib/active_record/association_relation.rb +45 -7
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +172 -67
  11. data/lib/active_record/associations/association_scope.rb +105 -129
  12. data/lib/active_record/associations/belongs_to_association.rb +85 -59
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -33
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +168 -279
  22. data/lib/active_record/associations/collection_proxy.rb +263 -155
  23. data/lib/active_record/associations/foreign_association.rb +33 -0
  24. data/lib/active_record/associations/has_many_association.rb +57 -84
  25. data/lib/active_record/associations/has_many_through_association.rb +70 -82
  26. data/lib/active_record/associations/has_one_association.rb +74 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +175 -164
  32. data/lib/active_record/associations/preloader/association.rb +107 -112
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +99 -96
  35. data/lib/active_record/associations/singular_association.rb +18 -45
  36. data/lib/active_record/associations/through_association.rb +49 -24
  37. data/lib/active_record/associations.rb +1845 -1597
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -138
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +59 -36
  46. data/lib/active_record/attribute_methods/write.rb +25 -56
  47. data/lib/active_record/attribute_methods.rb +153 -162
  48. data/lib/active_record/attributes.rb +234 -70
  49. data/lib/active_record/autosave_association.rb +157 -69
  50. data/lib/active_record/base.rb +49 -50
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +46 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +271 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +78 -161
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +171 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +499 -293
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +595 -382
  119. data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -389
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +488 -243
  133. data/lib/active_record/counter_cache.rb +71 -50
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +273 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +212 -94
  143. data/lib/active_record/errors.rb +225 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +11 -6
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +273 -496
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +64 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +52 -0
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +103 -95
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +298 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +685 -309
  170. data/lib/active_record/model_schema.rb +420 -113
  171. data/lib/active_record/nested_attributes.rb +265 -216
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +574 -135
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +175 -54
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +533 -216
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +485 -310
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +326 -244
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +318 -256
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +99 -84
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +139 -96
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -409
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +23 -21
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -342
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -26
  209. data/lib/active_record/scoping/default.rb +96 -82
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +133 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +366 -129
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +291 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +181 -152
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -41
  231. data/lib/active_record/type/date_time.rb +4 -38
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +33 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +65 -48
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +44 -28
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -10
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record.rb +7 -5
  339. metadata +175 -65
  340. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  341. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  342. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  343. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  344. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  345. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  346. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  347. data/lib/active_record/attribute.rb +0 -149
  348. data/lib/active_record/attribute_decorators.rb +0 -66
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  352. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  353. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  354. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  355. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  356. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  357. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  358. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  359. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  360. data/lib/active_record/type/big_integer.rb +0 -13
  361. data/lib/active_record/type/binary.rb +0 -50
  362. data/lib/active_record/type/boolean.rb +0 -30
  363. data/lib/active_record/type/decimal.rb +0 -40
  364. data/lib/active_record/type/decorator.rb +0 -14
  365. data/lib/active_record/type/float.rb +0 -19
  366. data/lib/active_record/type/integer.rb +0 -55
  367. data/lib/active_record/type/mutable.rb +0 -16
  368. data/lib/active_record/type/numeric.rb +0 -36
  369. data/lib/active_record/type/string.rb +0 -36
  370. data/lib/active_record/type/time_value.rb +0 -38
  371. data/lib/active_record/type/value.rb +0 -101
  372. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  373. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  374. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,99 +1,249 @@
1
- require 'active_support/core_ext/enumerable'
2
- require 'active_support/core_ext/string/conversions'
3
- require 'active_support/core_ext/module/remove_method'
4
- require 'active_record/errors'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/enumerable"
4
+ require "active_support/core_ext/string/conversions"
5
5
 
6
6
  module ActiveRecord
7
7
  class AssociationNotFoundError < ConfigurationError #:nodoc:
8
- def initialize(record, association_name)
9
- super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
8
+ attr_reader :record, :association_name
9
+ def initialize(record = nil, association_name = nil)
10
+ @record = record
11
+ @association_name = association_name
12
+ if record && association_name
13
+ super("Association named '#{association_name}' was not found on #{record.class.name}; perhaps you misspelled it?")
14
+ else
15
+ super("Association was not found.")
16
+ end
17
+ end
18
+
19
+ class Correction
20
+ def initialize(error)
21
+ @error = error
22
+ end
23
+
24
+ def corrections
25
+ if @error.association_name
26
+ maybe_these = @error.record.class.reflections.keys
27
+
28
+ maybe_these.sort_by { |n|
29
+ DidYouMean::Jaro.distance(@error.association_name.to_s, n)
30
+ }.reverse.first(4)
31
+ else
32
+ []
33
+ end
34
+ end
35
+ end
36
+
37
+ # We may not have DYM, and DYM might not let us register error handlers
38
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
39
+ DidYouMean.correct_error(self, Correction)
10
40
  end
11
41
  end
12
42
 
13
43
  class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
14
- def initialize(reflection, associated_class = nil)
15
- super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
44
+ attr_reader :reflection, :associated_class
45
+ def initialize(reflection = nil, associated_class = nil)
46
+ if reflection
47
+ @reflection = reflection
48
+ @associated_class = associated_class.nil? ? reflection.klass : associated_class
49
+ super("Could not find the inverse association for #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{associated_class.nil? ? reflection.class_name : associated_class.name})")
50
+ else
51
+ super("Could not find the inverse association.")
52
+ end
53
+ end
54
+
55
+ class Correction
56
+ def initialize(error)
57
+ @error = error
58
+ end
59
+
60
+ def corrections
61
+ if @error.reflection && @error.associated_class
62
+ maybe_these = @error.associated_class.reflections.keys
63
+
64
+ maybe_these.sort_by { |n|
65
+ DidYouMean::Jaro.distance(@error.reflection.options[:inverse_of].to_s, n)
66
+ }.reverse.first(4)
67
+ else
68
+ []
69
+ end
70
+ end
71
+ end
72
+
73
+ # We may not have DYM, and DYM might not let us register error handlers
74
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
75
+ DidYouMean.correct_error(self, Correction)
16
76
  end
17
77
  end
18
78
 
19
79
  class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
20
- def initialize(owner_class_name, reflection)
21
- super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class_name}")
80
+ attr_reader :owner_class, :reflection
81
+
82
+ def initialize(owner_class = nil, reflection = nil)
83
+ if owner_class && reflection
84
+ @owner_class = owner_class
85
+ @reflection = reflection
86
+ super("Could not find the association #{reflection.options[:through].inspect} in model #{owner_class.name}")
87
+ else
88
+ super("Could not find the association.")
89
+ end
90
+ end
91
+
92
+ class Correction
93
+ def initialize(error)
94
+ @error = error
95
+ end
96
+
97
+ def corrections
98
+ if @error.reflection && @error.owner_class
99
+ maybe_these = @error.owner_class.reflections.keys
100
+ maybe_these -= [@error.reflection.name.to_s] # remove failing reflection
101
+
102
+ maybe_these.sort_by { |n|
103
+ DidYouMean::Jaro.distance(@error.reflection.options[:through].to_s, n)
104
+ }.reverse.first(4)
105
+ else
106
+ []
107
+ end
108
+ end
109
+ end
110
+
111
+ # We may not have DYM, and DYM might not let us register error handlers
112
+ if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
113
+ DidYouMean.correct_error(self, Correction)
22
114
  end
23
115
  end
24
116
 
25
117
  class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError #:nodoc:
26
- def initialize(owner_class_name, reflection, source_reflection)
27
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
118
+ def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
119
+ if owner_class_name && reflection && source_reflection
120
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
121
+ else
122
+ super("Cannot have a has_many :through association.")
123
+ end
28
124
  end
29
125
  end
30
126
 
31
127
  class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
32
- def initialize(owner_class_name, reflection)
33
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
128
+ def initialize(owner_class_name = nil, reflection = nil)
129
+ if owner_class_name && reflection
130
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
131
+ else
132
+ super("Cannot have a has_many :through association.")
133
+ end
34
134
  end
35
135
  end
36
136
 
37
137
  class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
38
- def initialize(owner_class_name, reflection, source_reflection)
39
- super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
138
+ def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
139
+ if owner_class_name && reflection && source_reflection
140
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
141
+ else
142
+ super("Cannot have a has_many :through association.")
143
+ end
40
144
  end
41
145
  end
42
146
 
43
147
  class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc:
44
- def initialize(owner_class_name, reflection, through_reflection)
45
- super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
148
+ def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
149
+ if owner_class_name && reflection && through_reflection
150
+ super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
151
+ else
152
+ super("Cannot have a has_one :through association.")
153
+ end
46
154
  end
47
155
  end
48
156
 
49
157
  class HasOneAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
50
- def initialize(owner_class_name, reflection)
51
- super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
158
+ def initialize(owner_class_name = nil, reflection = nil)
159
+ if owner_class_name && reflection
160
+ super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
161
+ else
162
+ super("Cannot have a has_one :through association.")
163
+ end
52
164
  end
53
165
  end
54
166
 
55
167
  class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
56
- def initialize(reflection)
57
- through_reflection = reflection.through_reflection
58
- source_reflection_names = reflection.source_reflection_names
59
- source_associations = reflection.through_reflection.klass._reflections.keys
60
- super("Could not find the source association(s) #{source_reflection_names.collect{ |a| a.inspect }.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(:two_words_connector => ' or ', :last_word_connector => ', or ', :locale => :en)}?")
168
+ def initialize(reflection = nil)
169
+ if reflection
170
+ through_reflection = reflection.through_reflection
171
+ source_reflection_names = reflection.source_reflection_names
172
+ source_associations = reflection.through_reflection.klass._reflections.keys
173
+ super("Could not find the source association(s) #{source_reflection_names.collect(&:inspect).to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')} in model #{through_reflection.klass}. Try 'has_many #{reflection.name.inspect}, :through => #{through_reflection.name.inspect}, :source => <name>'. Is it one of #{source_associations.to_sentence(two_words_connector: ' or ', last_word_connector: ', or ')}?")
174
+ else
175
+ super("Could not find the source association(s).")
176
+ end
61
177
  end
62
178
  end
63
179
 
64
- class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
65
- def initialize(owner, reflection)
66
- super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
180
+ class HasManyThroughOrderError < ActiveRecordError #:nodoc:
181
+ def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
182
+ if owner_class_name && reflection && through_reflection
183
+ super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
184
+ else
185
+ super("Cannot have a has_many :through association before the through association is defined.")
186
+ end
67
187
  end
68
188
  end
69
189
 
70
- class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
71
- def initialize(owner, reflection)
72
- super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
190
+ class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
191
+ def initialize(owner = nil, reflection = nil)
192
+ if owner && reflection
193
+ super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
194
+ else
195
+ super("Cannot modify association.")
196
+ end
73
197
  end
74
198
  end
75
199
 
76
- class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
77
- def initialize(owner, reflection)
78
- super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
200
+ class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
201
+ def initialize(klass, macro, association_name, options, possible_sources)
202
+ example_options = options.dup
203
+ example_options[:source] = possible_sources.first
204
+
205
+ super("Ambiguous source reflection for through association. Please " \
206
+ "specify a :source directive on your declaration like:\n" \
207
+ "\n" \
208
+ " class #{klass} < ActiveRecord::Base\n" \
209
+ " #{macro} :#{association_name}, #{example_options}\n" \
210
+ " end"
211
+ )
79
212
  end
80
213
  end
81
214
 
82
- class HasManyThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
83
- def initialize(owner, reflection)
84
- super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
85
- end
215
+ class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
216
+ end
217
+
218
+ class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
86
219
  end
87
220
 
88
- class EagerLoadPolymorphicError < ActiveRecordError #:nodoc:
89
- def initialize(reflection)
90
- super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
221
+ class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
222
+ def initialize(owner = nil, reflection = nil)
223
+ if owner && reflection
224
+ super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
225
+ else
226
+ super("Through nested associations are read-only.")
227
+ end
91
228
  end
92
229
  end
93
230
 
94
- class ReadOnlyAssociation < ActiveRecordError #:nodoc:
95
- def initialize(reflection)
96
- super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
231
+ class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
232
+ end
233
+
234
+ class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
235
+ end
236
+
237
+ # This error is raised when trying to eager load a polymorphic association using a JOIN.
238
+ # Eager loading polymorphic associations is only possible with
239
+ # {ActiveRecord::Relation#preload}[rdoc-ref:QueryMethods#preload].
240
+ class EagerLoadPolymorphicError < ActiveRecordError
241
+ def initialize(reflection = nil)
242
+ if reflection
243
+ super("Cannot eagerly load the polymorphic association #{reflection.name.inspect}")
244
+ else
245
+ super("Eager load polymorphic error.")
246
+ end
97
247
  end
98
248
  end
99
249
 
@@ -101,8 +251,12 @@ module ActiveRecord
101
251
  # (has_many, has_one) when there is at least 1 child associated instance.
102
252
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
103
253
  class DeleteRestrictionError < ActiveRecordError #:nodoc:
104
- def initialize(name)
105
- super("Cannot delete record because of dependent #{name}")
254
+ def initialize(name = nil)
255
+ if name
256
+ super("Cannot delete record because of dependent #{name}")
257
+ else
258
+ super("Delete restriction error.")
259
+ end
106
260
  end
107
261
  end
108
262
 
@@ -113,51 +267,51 @@ module ActiveRecord
113
267
 
114
268
  # These classes will be loaded when associations are created.
115
269
  # So there is no need to eager load them.
116
- autoload :Association, 'active_record/associations/association'
117
- autoload :SingularAssociation, 'active_record/associations/singular_association'
118
- autoload :CollectionAssociation, 'active_record/associations/collection_association'
119
- autoload :CollectionProxy, 'active_record/associations/collection_proxy'
120
-
121
- autoload :BelongsToAssociation, 'active_record/associations/belongs_to_association'
122
- autoload :BelongsToPolymorphicAssociation, 'active_record/associations/belongs_to_polymorphic_association'
123
- autoload :HasManyAssociation, 'active_record/associations/has_many_association'
124
- autoload :HasManyThroughAssociation, 'active_record/associations/has_many_through_association'
125
- autoload :HasOneAssociation, 'active_record/associations/has_one_association'
126
- autoload :HasOneThroughAssociation, 'active_record/associations/has_one_through_association'
127
- autoload :ThroughAssociation, 'active_record/associations/through_association'
270
+ autoload :Association
271
+ autoload :SingularAssociation
272
+ autoload :CollectionAssociation
273
+ autoload :ForeignAssociation
274
+ autoload :CollectionProxy
275
+ autoload :ThroughAssociation
128
276
 
129
277
  module Builder #:nodoc:
130
- autoload :Association, 'active_record/associations/builder/association'
131
- autoload :SingularAssociation, 'active_record/associations/builder/singular_association'
132
- autoload :CollectionAssociation, 'active_record/associations/builder/collection_association'
133
-
134
- autoload :BelongsTo, 'active_record/associations/builder/belongs_to'
135
- autoload :HasOne, 'active_record/associations/builder/has_one'
136
- autoload :HasMany, 'active_record/associations/builder/has_many'
137
- autoload :HasAndBelongsToMany, 'active_record/associations/builder/has_and_belongs_to_many'
278
+ autoload :Association, "active_record/associations/builder/association"
279
+ autoload :SingularAssociation, "active_record/associations/builder/singular_association"
280
+ autoload :CollectionAssociation, "active_record/associations/builder/collection_association"
281
+
282
+ autoload :BelongsTo, "active_record/associations/builder/belongs_to"
283
+ autoload :HasOne, "active_record/associations/builder/has_one"
284
+ autoload :HasMany, "active_record/associations/builder/has_many"
285
+ autoload :HasAndBelongsToMany, "active_record/associations/builder/has_and_belongs_to_many"
138
286
  end
139
287
 
140
288
  eager_autoload do
141
- autoload :Preloader, 'active_record/associations/preloader'
142
- autoload :JoinDependency, 'active_record/associations/join_dependency'
143
- autoload :AssociationScope, 'active_record/associations/association_scope'
144
- autoload :AliasTracker, 'active_record/associations/alias_tracker'
145
- end
289
+ autoload :BelongsToAssociation
290
+ autoload :BelongsToPolymorphicAssociation
291
+ autoload :HasManyAssociation
292
+ autoload :HasManyThroughAssociation
293
+ autoload :HasOneAssociation
294
+ autoload :HasOneThroughAssociation
146
295
 
147
- # Clears out the association cache.
148
- def clear_association_cache #:nodoc:
149
- @association_cache.clear if persisted?
296
+ autoload :Preloader
297
+ autoload :JoinDependency
298
+ autoload :AssociationScope
299
+ autoload :AliasTracker
150
300
  end
151
301
 
152
- # :nodoc:
153
- attr_reader :association_cache
302
+ def self.eager_load!
303
+ super
304
+ Preloader.eager_load!
305
+ end
154
306
 
155
307
  # Returns the association instance for the given name, instantiating it if it doesn't already exist
156
308
  def association(name) #:nodoc:
157
309
  association = association_instance_get(name)
158
310
 
159
311
  if association.nil?
160
- raise AssociationNotFoundError.new(self, name) unless reflection = self.class._reflect_on_association(name)
312
+ unless reflection = self.class._reflect_on_association(name)
313
+ raise AssociationNotFoundError.new(self, name)
314
+ end
161
315
  association = reflection.association_class.new(self, reflection)
162
316
  association_instance_set(name, association)
163
317
  end
@@ -165,8 +319,32 @@ module ActiveRecord
165
319
  association
166
320
  end
167
321
 
322
+ def association_cached?(name) # :nodoc:
323
+ @association_cache.key?(name)
324
+ end
325
+
326
+ def initialize_dup(*) # :nodoc:
327
+ @association_cache = {}
328
+ super
329
+ end
330
+
331
+ def reload(*) # :nodoc:
332
+ clear_association_cache
333
+ super
334
+ end
335
+
168
336
  private
169
- # Returns the specified association instance if it responds to :loaded?, nil otherwise.
337
+ # Clears out the association cache.
338
+ def clear_association_cache
339
+ @association_cache.clear if persisted?
340
+ end
341
+
342
+ def init_internals
343
+ @association_cache = {}
344
+ super
345
+ end
346
+
347
+ # Returns the specified association instance if it exists, +nil+ otherwise.
170
348
  def association_instance_get(name)
171
349
  @association_cache[name]
172
350
  end
@@ -176,1549 +354,1619 @@ module ActiveRecord
176
354
  @association_cache[name] = association
177
355
  end
178
356
 
179
- # \Associations are a set of macro-like class methods for tying objects together through
180
- # foreign keys. They express relationships like "Project has one Project Manager"
181
- # or "Project belongs to a Portfolio". Each macro adds a number of methods to the
182
- # class which are specialized according to the collection or association symbol and the
183
- # options hash. It works much the same way as Ruby's own <tt>attr*</tt>
184
- # methods.
185
- #
186
- # class Project < ActiveRecord::Base
187
- # belongs_to :portfolio
188
- # has_one :project_manager
189
- # has_many :milestones
190
- # has_and_belongs_to_many :categories
191
- # end
192
- #
193
- # The project class now has the following methods (and more) to ease the traversal and
194
- # manipulation of its relationships:
195
- # * <tt>Project#portfolio, Project#portfolio=(portfolio), Project#portfolio.nil?</tt>
196
- # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt>
197
- # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt>
198
- # <tt>Project#milestones.delete(milestone), Project#milestones.destroy(milestone), Project#milestones.find(milestone_id),</tt>
199
- # <tt>Project#milestones.build, Project#milestones.create</tt>
200
- # * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt>
201
- # <tt>Project#categories.delete(category1), Project#categories.destroy(category1)</tt>
202
- #
203
- # === A word of warning
204
- #
205
- # Don't create associations that have the same name as instance methods of
206
- # <tt>ActiveRecord::Base</tt>. Since the association adds a method with that name to
207
- # its model, it will override the inherited method and break things.
208
- # For instance, +attributes+ and +connection+ would be bad choices for association names.
209
- #
210
- # == Auto-generated methods
211
- # See also Instance Public methods below for more details.
212
- #
213
- # === Singular associations (one-to-one)
214
- # | | belongs_to |
215
- # generated methods | belongs_to | :polymorphic | has_one
216
- # ----------------------------------+------------+--------------+---------
217
- # other(force_reload=false) | X | X | X
218
- # other=(other) | X | X | X
219
- # build_other(attributes={}) | X | | X
220
- # create_other(attributes={}) | X | | X
221
- # create_other!(attributes={}) | X | | X
222
- #
223
- # ===Collection associations (one-to-many / many-to-many)
224
- # | | | has_many
225
- # generated methods | habtm | has_many | :through
226
- # ----------------------------------+-------+----------+----------
227
- # others(force_reload=false) | X | X | X
228
- # others=(other,other,...) | X | X | X
229
- # other_ids | X | X | X
230
- # other_ids=(id,id,...) | X | X | X
231
- # others<< | X | X | X
232
- # others.push | X | X | X
233
- # others.concat | X | X | X
234
- # others.build(attributes={}) | X | X | X
235
- # others.create(attributes={}) | X | X | X
236
- # others.create!(attributes={}) | X | X | X
237
- # others.size | X | X | X
238
- # others.length | X | X | X
239
- # others.count | X | X | X
240
- # others.sum(*args) | X | X | X
241
- # others.empty? | X | X | X
242
- # others.clear | X | X | X
243
- # others.delete(other,other,...) | X | X | X
244
- # others.delete_all | X | X | X
245
- # others.destroy(other,other,...) | X | X | X
246
- # others.destroy_all | X | X | X
247
- # others.find(*args) | X | X | X
248
- # others.exists? | X | X | X
249
- # others.distinct | X | X | X
250
- # others.uniq | X | X | X
251
- # others.reset | X | X | X
252
- #
253
- # === Overriding generated methods
254
- #
255
- # Association methods are generated in a module that is included into the model class,
256
- # which allows you to easily override with your own methods and call the original
257
- # generated method with +super+. For example:
258
- #
259
- # class Car < ActiveRecord::Base
260
- # belongs_to :owner
261
- # belongs_to :old_owner
262
- # def owner=(new_owner)
263
- # self.old_owner = self.owner
264
- # super
265
- # end
266
- # end
267
- #
268
- # If your model class is <tt>Project</tt>, the module is
269
- # named <tt>Project::GeneratedFeatureMethods</tt>. The GeneratedFeatureMethods module is
270
- # included in the model class immediately after the (anonymous) generated attributes methods
271
- # module, meaning an association will override the methods for an attribute with the same name.
272
- #
273
- # == Cardinality and associations
274
- #
275
- # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
276
- # relationships between models. Each model uses an association to describe its role in
277
- # the relation. The +belongs_to+ association is always used in the model that has
278
- # the foreign key.
279
- #
280
- # === One-to-one
281
- #
282
- # Use +has_one+ in the base, and +belongs_to+ in the associated model.
283
- #
284
- # class Employee < ActiveRecord::Base
285
- # has_one :office
286
- # end
287
- # class Office < ActiveRecord::Base
288
- # belongs_to :employee # foreign key - employee_id
289
- # end
290
- #
291
- # === One-to-many
292
- #
293
- # Use +has_many+ in the base, and +belongs_to+ in the associated model.
294
- #
295
- # class Manager < ActiveRecord::Base
296
- # has_many :employees
297
- # end
298
- # class Employee < ActiveRecord::Base
299
- # belongs_to :manager # foreign key - manager_id
300
- # end
301
- #
302
- # === Many-to-many
303
- #
304
- # There are two ways to build a many-to-many relationship.
305
- #
306
- # The first way uses a +has_many+ association with the <tt>:through</tt> option and a join model, so
307
- # there are two stages of associations.
308
- #
309
- # class Assignment < ActiveRecord::Base
310
- # belongs_to :programmer # foreign key - programmer_id
311
- # belongs_to :project # foreign key - project_id
312
- # end
313
- # class Programmer < ActiveRecord::Base
314
- # has_many :assignments
315
- # has_many :projects, through: :assignments
316
- # end
317
- # class Project < ActiveRecord::Base
318
- # has_many :assignments
319
- # has_many :programmers, through: :assignments
320
- # end
321
- #
322
- # For the second way, use +has_and_belongs_to_many+ in both models. This requires a join table
323
- # that has no corresponding model or primary key.
324
- #
325
- # class Programmer < ActiveRecord::Base
326
- # has_and_belongs_to_many :projects # foreign keys in the join table
327
- # end
328
- # class Project < ActiveRecord::Base
329
- # has_and_belongs_to_many :programmers # foreign keys in the join table
330
- # end
331
- #
332
- # Choosing which way to build a many-to-many relationship is not always simple.
333
- # If you need to work with the relationship model as its own entity,
334
- # use <tt>has_many :through</tt>. Use +has_and_belongs_to_many+ when working with legacy schemas or when
335
- # you never work directly with the relationship itself.
336
- #
337
- # == Is it a +belongs_to+ or +has_one+ association?
338
- #
339
- # Both express a 1-1 relationship. The difference is mostly where to place the foreign
340
- # key, which goes on the table for the class declaring the +belongs_to+ relationship.
341
- #
342
- # class User < ActiveRecord::Base
343
- # # I reference an account.
344
- # belongs_to :account
345
- # end
346
- #
347
- # class Account < ActiveRecord::Base
348
- # # One user references me.
349
- # has_one :user
350
- # end
351
- #
352
- # The tables for these classes could look something like:
353
- #
354
- # CREATE TABLE users (
355
- # id int(11) NOT NULL auto_increment,
356
- # account_id int(11) default NULL,
357
- # name varchar default NULL,
358
- # PRIMARY KEY (id)
359
- # )
360
- #
361
- # CREATE TABLE accounts (
362
- # id int(11) NOT NULL auto_increment,
363
- # name varchar default NULL,
364
- # PRIMARY KEY (id)
365
- # )
366
- #
367
- # == Unsaved objects and associations
368
- #
369
- # You can manipulate objects and associations before they are saved to the database, but
370
- # there is some special behavior you should be aware of, mostly involving the saving of
371
- # associated objects.
372
- #
373
- # You can set the <tt>:autosave</tt> option on a <tt>has_one</tt>, <tt>belongs_to</tt>,
374
- # <tt>has_many</tt>, or <tt>has_and_belongs_to_many</tt> association. Setting it
375
- # to +true+ will _always_ save the members, whereas setting it to +false+ will
376
- # _never_ save the members. More details about <tt>:autosave</tt> option is available at
377
- # AutosaveAssociation.
378
- #
379
- # === One-to-one associations
380
- #
381
- # * Assigning an object to a +has_one+ association automatically saves that object and
382
- # the object being replaced (if there is one), in order to update their foreign
383
- # keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
384
- # * If either of these saves fail (due to one of the objects being invalid), an
385
- # <tt>ActiveRecord::RecordNotSaved</tt> exception is raised and the assignment is
386
- # cancelled.
387
- # * If you wish to assign an object to a +has_one+ association without saving it,
388
- # use the <tt>build_association</tt> method (documented below). The object being
389
- # replaced will still be saved to update its foreign key.
390
- # * Assigning an object to a +belongs_to+ association does not save the object, since
391
- # the foreign key field belongs on the parent. It does not save the parent either.
392
- #
393
- # === Collections
394
- #
395
- # * Adding an object to a collection (+has_many+ or +has_and_belongs_to_many+) automatically
396
- # saves that object, except if the parent object (the owner of the collection) is not yet
397
- # stored in the database.
398
- # * If saving any of the objects being added to a collection (via <tt>push</tt> or similar)
399
- # fails, then <tt>push</tt> returns +false+.
400
- # * If saving fails while replacing the collection (via <tt>association=</tt>), an
401
- # <tt>ActiveRecord::RecordNotSaved</tt> exception is raised and the assignment is
402
- # cancelled.
403
- # * You can add an object to a collection without automatically saving it by using the
404
- # <tt>collection.build</tt> method (documented below).
405
- # * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically
406
- # saved when the parent is saved.
407
- #
408
- # == Customizing the query
409
- #
410
- # \Associations are built from <tt>Relation</tt>s, and you can use the <tt>Relation</tt> syntax
411
- # to customize them. For example, to add a condition:
412
- #
413
- # class Blog < ActiveRecord::Base
414
- # has_many :published_posts, -> { where published: true }, class_name: 'Post'
415
- # end
416
- #
417
- # Inside the <tt>-> { ... }</tt> block you can use all of the usual <tt>Relation</tt> methods.
418
- #
419
- # === Accessing the owner object
420
- #
421
- # Sometimes it is useful to have access to the owner object when building the query. The owner
422
- # is passed as a parameter to the block. For example, the following association would find all
423
- # events that occur on the user's birthday:
424
- #
425
- # class User < ActiveRecord::Base
426
- # has_many :birthday_events, ->(user) { where starts_on: user.birthday }, class_name: 'Event'
427
- # end
428
- #
429
- # Note: Joining, eager loading and preloading of these associations is not fully possible.
430
- # These operations happen before instance creation and the scope will be called with a +nil+ argument.
431
- # This can lead to unexpected behavior and is deprecated.
432
- #
433
- # == Association callbacks
434
- #
435
- # Similar to the normal callbacks that hook into the life cycle of an Active Record object,
436
- # you can also define callbacks that get triggered when you add an object to or remove an
437
- # object from an association collection.
438
- #
439
- # class Project
440
- # has_and_belongs_to_many :developers, after_add: :evaluate_velocity
441
- #
442
- # def evaluate_velocity(developer)
443
- # ...
444
- # end
445
- # end
446
- #
447
- # It's possible to stack callbacks by passing them as an array. Example:
448
- #
449
- # class Project
450
- # has_and_belongs_to_many :developers,
451
- # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
452
- # end
453
- #
454
- # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
455
- #
456
- # If any of the +before_add+ callbacks throw an exception, the object will not be
457
- # added to the collection.
458
- #
459
- # Similarly, if any of the +before_remove+ callbacks throw an exception, the object
460
- # will not be removed from the collection.
461
- #
462
- # == Association extensions
463
- #
464
- # The proxy objects that control the access to associations can be extended through anonymous
465
- # modules. This is especially beneficial for adding new finders, creators, and other
466
- # factory-type methods that are only used as part of this association.
467
- #
468
- # class Account < ActiveRecord::Base
469
- # has_many :people do
470
- # def find_or_create_by_name(name)
471
- # first_name, last_name = name.split(" ", 2)
472
- # find_or_create_by(first_name: first_name, last_name: last_name)
473
- # end
474
- # end
475
- # end
476
- #
477
- # person = Account.first.people.find_or_create_by_name("David Heinemeier Hansson")
478
- # person.first_name # => "David"
479
- # person.last_name # => "Heinemeier Hansson"
480
- #
481
- # If you need to share the same extensions between many associations, you can use a named
482
- # extension module.
483
- #
484
- # module FindOrCreateByNameExtension
485
- # def find_or_create_by_name(name)
486
- # first_name, last_name = name.split(" ", 2)
487
- # find_or_create_by(first_name: first_name, last_name: last_name)
488
- # end
489
- # end
490
- #
491
- # class Account < ActiveRecord::Base
492
- # has_many :people, -> { extending FindOrCreateByNameExtension }
493
- # end
494
- #
495
- # class Company < ActiveRecord::Base
496
- # has_many :people, -> { extending FindOrCreateByNameExtension }
497
- # end
498
- #
499
- # Some extensions can only be made to work with knowledge of the association's internals.
500
- # Extensions can access relevant state using the following methods (where +items+ is the
501
- # name of the association):
502
- #
503
- # * <tt>record.association(:items).owner</tt> - Returns the object the association is part of.
504
- # * <tt>record.association(:items).reflection</tt> - Returns the reflection object that describes the association.
505
- # * <tt>record.association(:items).target</tt> - Returns the associated object for +belongs_to+ and +has_one+, or
506
- # the collection of associated objects for +has_many+ and +has_and_belongs_to_many+.
507
- #
508
- # However, inside the actual extension code, you will not have access to the <tt>record</tt> as
509
- # above. In this case, you can access <tt>proxy_association</tt>. For example,
510
- # <tt>record.association(:items)</tt> and <tt>record.items.proxy_association</tt> will return
511
- # the same object, allowing you to make calls like <tt>proxy_association.owner</tt> inside
512
- # association extensions.
513
- #
514
- # == Association Join Models
515
- #
516
- # Has Many associations can be configured with the <tt>:through</tt> option to use an
517
- # explicit join model to retrieve the data. This operates similarly to a
518
- # +has_and_belongs_to_many+ association. The advantage is that you're able to add validations,
519
- # callbacks, and extra attributes on the join model. Consider the following schema:
520
- #
521
- # class Author < ActiveRecord::Base
522
- # has_many :authorships
523
- # has_many :books, through: :authorships
524
- # end
525
- #
526
- # class Authorship < ActiveRecord::Base
527
- # belongs_to :author
528
- # belongs_to :book
529
- # end
530
- #
531
- # @author = Author.first
532
- # @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
533
- # @author.books # selects all books by using the Authorship join model
534
- #
535
- # You can also go through a +has_many+ association on the join model:
536
- #
537
- # class Firm < ActiveRecord::Base
538
- # has_many :clients
539
- # has_many :invoices, through: :clients
540
- # end
541
- #
542
- # class Client < ActiveRecord::Base
543
- # belongs_to :firm
544
- # has_many :invoices
545
- # end
546
- #
547
- # class Invoice < ActiveRecord::Base
548
- # belongs_to :client
549
- # end
550
- #
551
- # @firm = Firm.first
552
- # @firm.clients.flat_map { |c| c.invoices } # select all invoices for all clients of the firm
553
- # @firm.invoices # selects all invoices by going through the Client join model
554
- #
555
- # Similarly you can go through a +has_one+ association on the join model:
556
- #
557
- # class Group < ActiveRecord::Base
558
- # has_many :users
559
- # has_many :avatars, through: :users
560
- # end
561
- #
562
- # class User < ActiveRecord::Base
563
- # belongs_to :group
564
- # has_one :avatar
565
- # end
566
- #
567
- # class Avatar < ActiveRecord::Base
568
- # belongs_to :user
569
- # end
570
- #
571
- # @group = Group.first
572
- # @group.users.collect { |u| u.avatar }.compact # select all avatars for all users in the group
573
- # @group.avatars # selects all avatars by going through the User join model.
574
- #
575
- # An important caveat with going through +has_one+ or +has_many+ associations on the
576
- # join model is that these associations are *read-only*. For example, the following
577
- # would not work following the previous example:
578
- #
579
- # @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
580
- # @group.avatars.delete(@group.avatars.last) # so would this
581
- #
582
- # == Setting Inverses
583
- #
584
- # If you are using a +belongs_to+ on the join model, it is a good idea to set the
585
- # <tt>:inverse_of</tt> option on the +belongs_to+, which will mean that the following example
586
- # works correctly (where <tt>tags</tt> is a +has_many+ <tt>:through</tt> association):
587
- #
588
- # @post = Post.first
589
- # @tag = @post.tags.build name: "ruby"
590
- # @tag.save
591
- #
592
- # The last line ought to save the through record (a <tt>Taggable</tt>). This will only work if the
593
- # <tt>:inverse_of</tt> is set:
594
- #
595
- # class Taggable < ActiveRecord::Base
596
- # belongs_to :post
597
- # belongs_to :tag, inverse_of: :taggings
598
- # end
599
- #
600
- # If you do not set the <tt>:inverse_of</tt> record, the association will
601
- # do its best to match itself up with the correct inverse. Automatic
602
- # inverse detection only works on <tt>has_many</tt>, <tt>has_one</tt>, and
603
- # <tt>belongs_to</tt> associations.
604
- #
605
- # Extra options on the associations, as defined in the
606
- # <tt>AssociationReflection::INVALID_AUTOMATIC_INVERSE_OPTIONS</tt> constant, will
607
- # also prevent the association's inverse from being found automatically.
608
- #
609
- # The automatic guessing of the inverse association uses a heuristic based
610
- # on the name of the class, so it may not work for all associations,
611
- # especially the ones with non-standard names.
612
- #
613
- # You can turn off the automatic detection of inverse associations by setting
614
- # the <tt>:inverse_of</tt> option to <tt>false</tt> like so:
615
- #
616
- # class Taggable < ActiveRecord::Base
617
- # belongs_to :tag, inverse_of: false
618
- # end
619
- #
620
- # == Nested \Associations
621
- #
622
- # You can actually specify *any* association with the <tt>:through</tt> option, including an
623
- # association which has a <tt>:through</tt> option itself. For example:
624
- #
625
- # class Author < ActiveRecord::Base
626
- # has_many :posts
627
- # has_many :comments, through: :posts
628
- # has_many :commenters, through: :comments
629
- # end
630
- #
631
- # class Post < ActiveRecord::Base
632
- # has_many :comments
633
- # end
634
- #
635
- # class Comment < ActiveRecord::Base
636
- # belongs_to :commenter
637
- # end
638
- #
639
- # @author = Author.first
640
- # @author.commenters # => People who commented on posts written by the author
641
- #
642
- # An equivalent way of setting up this association this would be:
643
- #
644
- # class Author < ActiveRecord::Base
645
- # has_many :posts
646
- # has_many :commenters, through: :posts
647
- # end
648
- #
649
- # class Post < ActiveRecord::Base
650
- # has_many :comments
651
- # has_many :commenters, through: :comments
652
- # end
653
- #
654
- # class Comment < ActiveRecord::Base
655
- # belongs_to :commenter
656
- # end
657
- #
658
- # When using a nested association, you will not be able to modify the association because there
659
- # is not enough information to know what modification to make. For example, if you tried to
660
- # add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the
661
- # intermediate <tt>Post</tt> and <tt>Comment</tt> objects.
662
- #
663
- # == Polymorphic \Associations
664
- #
665
- # Polymorphic associations on models are not restricted on what types of models they
666
- # can be associated with. Rather, they specify an interface that a +has_many+ association
667
- # must adhere to.
668
- #
669
- # class Asset < ActiveRecord::Base
670
- # belongs_to :attachable, polymorphic: true
671
- # end
672
- #
673
- # class Post < ActiveRecord::Base
674
- # has_many :assets, as: :attachable # The :as option specifies the polymorphic interface to use.
675
- # end
676
- #
677
- # @asset.attachable = @post
678
- #
679
- # This works by using a type column in addition to a foreign key to specify the associated
680
- # record. In the Asset example, you'd need an +attachable_id+ integer column and an
681
- # +attachable_type+ string column.
682
- #
683
- # Using polymorphic associations in combination with single table inheritance (STI) is
684
- # a little tricky. In order for the associations to work as expected, ensure that you
685
- # store the base model for the STI models in the type column of the polymorphic
686
- # association. To continue with the asset example above, suppose there are guest posts
687
- # and member posts that use the posts table for STI. In this case, there must be a +type+
688
- # column in the posts table.
689
- #
690
- # Note: The <tt>attachable_type=</tt> method is being called when assigning an +attachable+.
691
- # The +class_name+ of the +attachable+ is passed as a String.
692
- #
693
- # class Asset < ActiveRecord::Base
694
- # belongs_to :attachable, polymorphic: true
695
- #
696
- # def attachable_type=(class_name)
697
- # super(class_name.constantize.base_class.to_s)
698
- # end
699
- # end
700
- #
701
- # class Post < ActiveRecord::Base
702
- # # because we store "Post" in attachable_type now dependent: :destroy will work
703
- # has_many :assets, as: :attachable, dependent: :destroy
704
- # end
705
- #
706
- # class GuestPost < Post
707
- # end
708
- #
709
- # class MemberPost < Post
710
- # end
711
- #
712
- # == Caching
713
- #
714
- # All of the methods are built on a simple caching principle that will keep the result
715
- # of the last query around unless specifically instructed not to. The cache is even
716
- # shared across methods to make it even cheaper to use the macro-added methods without
717
- # worrying too much about performance at the first go.
718
- #
719
- # project.milestones # fetches milestones from the database
720
- # project.milestones.size # uses the milestone cache
721
- # project.milestones.empty? # uses the milestone cache
722
- # project.milestones(true).size # fetches milestones from the database
723
- # project.milestones # uses the milestone cache
724
- #
725
- # == Eager loading of associations
726
- #
727
- # Eager loading is a way to find objects of a certain class and a number of named associations.
728
- # It is one of the easiest ways to prevent the dreaded N+1 problem in which fetching 100
729
- # posts that each need to display their author triggers 101 database queries. Through the
730
- # use of eager loading, the number of queries will be reduced from 101 to 2.
731
- #
732
- # class Post < ActiveRecord::Base
733
- # belongs_to :author
734
- # has_many :comments
735
- # end
736
- #
737
- # Consider the following loop using the class above:
738
- #
739
- # Post.all.each do |post|
740
- # puts "Post: " + post.title
741
- # puts "Written by: " + post.author.name
742
- # puts "Last comment on: " + post.comments.first.created_on
743
- # end
744
- #
745
- # To iterate over these one hundred posts, we'll generate 201 database queries. Let's
746
- # first just optimize it for retrieving the author:
747
- #
748
- # Post.includes(:author).each do |post|
749
- #
750
- # This references the name of the +belongs_to+ association that also used the <tt>:author</tt>
751
- # symbol. After loading the posts, find will collect the +author_id+ from each one and load
752
- # all the referenced authors with one query. Doing so will cut down the number of queries
753
- # from 201 to 102.
754
- #
755
- # We can improve upon the situation further by referencing both associations in the finder with:
756
- #
757
- # Post.includes(:author, :comments).each do |post|
758
- #
759
- # This will load all comments with a single query. This reduces the total number of queries
760
- # to 3. In general, the number of queries will be 1 plus the number of associations
761
- # named (except if some of the associations are polymorphic +belongs_to+ - see below).
762
- #
763
- # To include a deep hierarchy of associations, use a hash:
764
- #
765
- # Post.includes(:author, { comments: { author: :gravatar } }).each do |post|
766
- #
767
- # The above code will load all the comments and all of their associated
768
- # authors and gravatars. You can mix and match any combination of symbols,
769
- # arrays, and hashes to retrieve the associations you want to load.
770
- #
771
- # All of this power shouldn't fool you into thinking that you can pull out huge amounts
772
- # of data with no performance penalty just because you've reduced the number of queries.
773
- # The database still needs to send all the data to Active Record and it still needs to
774
- # be processed. So it's no catch-all for performance problems, but it's a great way to
775
- # cut down on the number of queries in a situation as the one described above.
776
- #
777
- # Since only one table is loaded at a time, conditions or orders cannot reference tables
778
- # other than the main one. If this is the case, Active Record falls back to the previously
779
- # used LEFT OUTER JOIN based strategy. For example:
780
- #
781
- # Post.includes([:author, :comments]).where(['comments.approved = ?', true])
782
- #
783
- # This will result in a single SQL query with joins along the lines of:
784
- # <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
785
- # <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Note that using conditions
786
- # like this can have unintended consequences.
787
- # In the above example posts with no approved comments are not returned at all, because
788
- # the conditions apply to the SQL statement as a whole and not just to the association.
789
- #
790
- # You must disambiguate column references for this fallback to happen, for example
791
- # <tt>order: "author.name DESC"</tt> will work but <tt>order: "name DESC"</tt> will not.
792
- #
793
- # If you want to load all posts (including posts with no approved comments) then write
794
- # your own LEFT OUTER JOIN query using ON
795
- #
796
- # Post.joins("LEFT OUTER JOIN comments ON comments.post_id = posts.id AND comments.approved = '1'")
797
- #
798
- # In this case it is usually more natural to include an association which has conditions defined on it:
799
- #
800
- # class Post < ActiveRecord::Base
801
- # has_many :approved_comments, -> { where approved: true }, class_name: 'Comment'
802
- # end
803
- #
804
- # Post.includes(:approved_comments)
805
- #
806
- # This will load posts and eager load the +approved_comments+ association, which contains
807
- # only those comments that have been approved.
808
- #
809
- # If you eager load an association with a specified <tt>:limit</tt> option, it will be ignored,
810
- # returning all the associated objects:
811
- #
812
- # class Picture < ActiveRecord::Base
813
- # has_many :most_recent_comments, -> { order('id DESC').limit(10) }, class_name: 'Comment'
814
- # end
815
- #
816
- # Picture.includes(:most_recent_comments).first.most_recent_comments # => returns all associated comments.
817
- #
818
- # Eager loading is supported with polymorphic associations.
819
- #
820
- # class Address < ActiveRecord::Base
821
- # belongs_to :addressable, polymorphic: true
822
- # end
823
- #
824
- # A call that tries to eager load the addressable model
825
- #
826
- # Address.includes(:addressable)
827
- #
828
- # This will execute one query to load the addresses and load the addressables with one
829
- # query per addressable type.
830
- # For example if all the addressables are either of class Person or Company then a total
831
- # of 3 queries will be executed. The list of addressable types to load is determined on
832
- # the back of the addresses loaded. This is not supported if Active Record has to fallback
833
- # to the previous implementation of eager loading and will raise <tt>ActiveRecord::EagerLoadPolymorphicError</tt>.
834
- # The reason is that the parent model's type is a column value so its corresponding table
835
- # name cannot be put in the +FROM+/+JOIN+ clauses of that query.
836
- #
837
- # == Table Aliasing
838
- #
839
- # Active Record uses table aliasing in the case that a table is referenced multiple times
840
- # in a join. If a table is referenced only once, the standard table name is used. The
841
- # second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>.
842
- # Indexes are appended for any more successive uses of the table name.
843
- #
844
- # Post.joins(:comments)
845
- # # => SELECT ... FROM posts INNER JOIN comments ON ...
846
- # Post.joins(:special_comments) # STI
847
- # # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
848
- # Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
849
- # # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
850
- #
851
- # Acts as tree example:
852
- #
853
- # TreeMixin.joins(:children)
854
- # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
855
- # TreeMixin.joins(children: :parent)
856
- # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
857
- # INNER JOIN parents_mixins ...
858
- # TreeMixin.joins(children: {parent: :children})
859
- # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
860
- # INNER JOIN parents_mixins ...
861
- # INNER JOIN mixins childrens_mixins_2
862
- #
863
- # Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
864
- #
865
- # Post.joins(:categories)
866
- # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
867
- # Post.joins(categories: :posts)
868
- # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
869
- # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
870
- # Post.joins(categories: {posts: :categories})
871
- # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
872
- # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
873
- # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
874
- #
875
- # If you wish to specify your own custom joins using <tt>joins</tt> method, those table
876
- # names will take precedence over the eager associations:
877
- #
878
- # Post.joins(:comments).joins("inner join comments ...")
879
- # # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
880
- # Post.joins(:comments, :special_comments).joins("inner join comments ...")
881
- # # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
882
- # INNER JOIN comments special_comments_posts ...
883
- # INNER JOIN comments ...
884
- #
885
- # Table aliases are automatically truncated according to the maximum length of table identifiers
886
- # according to the specific database.
887
- #
888
- # == Modules
889
- #
890
- # By default, associations will look for objects within the current module scope. Consider:
891
- #
892
- # module MyApplication
893
- # module Business
894
- # class Firm < ActiveRecord::Base
895
- # has_many :clients
896
- # end
897
- #
898
- # class Client < ActiveRecord::Base; end
899
- # end
900
- # end
901
- #
902
- # When <tt>Firm#clients</tt> is called, it will in turn call
903
- # <tt>MyApplication::Business::Client.find_all_by_firm_id(firm.id)</tt>.
904
- # If you want to associate with a class in another module scope, this can be done by
905
- # specifying the complete class name.
906
- #
907
- # module MyApplication
908
- # module Business
909
- # class Firm < ActiveRecord::Base; end
910
- # end
911
- #
912
- # module Billing
913
- # class Account < ActiveRecord::Base
914
- # belongs_to :firm, class_name: "MyApplication::Business::Firm"
915
- # end
916
- # end
917
- # end
918
- #
919
- # == Bi-directional associations
920
- #
921
- # When you specify an association there is usually an association on the associated model
922
- # that specifies the same relationship in reverse. For example, with the following models:
923
- #
924
- # class Dungeon < ActiveRecord::Base
925
- # has_many :traps
926
- # has_one :evil_wizard
927
- # end
928
- #
929
- # class Trap < ActiveRecord::Base
930
- # belongs_to :dungeon
931
- # end
932
- #
933
- # class EvilWizard < ActiveRecord::Base
934
- # belongs_to :dungeon
935
- # end
936
- #
937
- # The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
938
- # the inverse of each other and the inverse of the +dungeon+ association on +EvilWizard+
939
- # is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
940
- # Active Record doesn't know anything about these inverse relationships and so no object
941
- # loading optimization is possible. For example:
942
- #
943
- # d = Dungeon.first
944
- # t = d.traps.first
945
- # d.level == t.dungeon.level # => true
946
- # d.level = 10
947
- # d.level == t.dungeon.level # => false
948
- #
949
- # The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
950
- # the same object data from the database, but are actually different in-memory copies
951
- # of that data. Specifying the <tt>:inverse_of</tt> option on associations lets you tell
952
- # Active Record about inverse relationships and it will optimise object loading. For
953
- # example, if we changed our model definitions to:
954
- #
955
- # class Dungeon < ActiveRecord::Base
956
- # has_many :traps, inverse_of: :dungeon
957
- # has_one :evil_wizard, inverse_of: :dungeon
958
- # end
959
- #
960
- # class Trap < ActiveRecord::Base
961
- # belongs_to :dungeon, inverse_of: :traps
962
- # end
963
- #
964
- # class EvilWizard < ActiveRecord::Base
965
- # belongs_to :dungeon, inverse_of: :evil_wizard
966
- # end
967
- #
968
- # Then, from our code snippet above, +d+ and <tt>t.dungeon</tt> are actually the same
969
- # in-memory instance and our final <tt>d.level == t.dungeon.level</tt> will return +true+.
970
- #
971
- # There are limitations to <tt>:inverse_of</tt> support:
972
- #
973
- # * does not work with <tt>:through</tt> associations.
974
- # * does not work with <tt>:polymorphic</tt> associations.
975
- # * for +belongs_to+ associations +has_many+ inverse associations are ignored.
976
- #
977
- # == Deleting from associations
978
- #
979
- # === Dependent associations
980
- #
981
- # +has_many+, +has_one+ and +belongs_to+ associations support the <tt>:dependent</tt> option.
982
- # This allows you to specify that associated records should be deleted when the owner is
983
- # deleted.
984
- #
985
- # For example:
986
- #
987
- # class Author
988
- # has_many :posts, dependent: :destroy
989
- # end
990
- # Author.find(1).destroy # => Will destroy all of the author's posts, too
991
- #
992
- # The <tt>:dependent</tt> option can have different values which specify how the deletion
993
- # is done. For more information, see the documentation for this option on the different
994
- # specific association types. When no option is given, the behavior is to do nothing
995
- # with the associated records when destroying a record.
996
- #
997
- # Note that <tt>:dependent</tt> is implemented using Rails' callback
998
- # system, which works by processing callbacks in order. Therefore, other
999
- # callbacks declared either before or after the <tt>:dependent</tt> option
1000
- # can affect what it does.
1001
- #
1002
- # === Delete or destroy?
1003
- #
1004
- # +has_many+ and +has_and_belongs_to_many+ associations have the methods <tt>destroy</tt>,
1005
- # <tt>delete</tt>, <tt>destroy_all</tt> and <tt>delete_all</tt>.
1006
- #
1007
- # For +has_and_belongs_to_many+, <tt>delete</tt> and <tt>destroy</tt> are the same: they
1008
- # cause the records in the join table to be removed.
1009
- #
1010
- # For +has_many+, <tt>destroy</tt> and <tt>destroy_all</tt> will always call the <tt>destroy</tt> method of the
1011
- # record(s) being removed so that callbacks are run. However <tt>delete</tt> and <tt>delete_all</tt> will either
1012
- # do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or
1013
- # if no <tt>:dependent</tt> option is given, then it will follow the default strategy.
1014
- # The default strategy is <tt>:nullify</tt> (set the foreign keys to <tt>nil</tt>), except for
1015
- # +has_many+ <tt>:through</tt>, where the default strategy is <tt>delete_all</tt> (delete
1016
- # the join records, without running their callbacks).
1017
- #
1018
- # There is also a <tt>clear</tt> method which is the same as <tt>delete_all</tt>, except that
1019
- # it returns the association rather than the records which have been deleted.
1020
- #
1021
- # === What gets deleted?
1022
- #
1023
- # There is a potential pitfall here: +has_and_belongs_to_many+ and +has_many+ <tt>:through</tt>
1024
- # associations have records in join tables, as well as the associated records. So when we
1025
- # call one of these deletion methods, what exactly should be deleted?
1026
- #
1027
- # The answer is that it is assumed that deletion on an association is about removing the
1028
- # <i>link</i> between the owner and the associated object(s), rather than necessarily the
1029
- # associated objects themselves. So with +has_and_belongs_to_many+ and +has_many+
1030
- # <tt>:through</tt>, the join records will be deleted, but the associated records won't.
1031
- #
1032
- # This makes sense if you think about it: if you were to call <tt>post.tags.delete(Tag.find_by(name: 'food'))</tt>
1033
- # you would want the 'food' tag to be unlinked from the post, rather than for the tag itself
1034
- # to be removed from the database.
1035
- #
1036
- # However, there are examples where this strategy doesn't make sense. For example, suppose
1037
- # a person has many projects, and each project has many tasks. If we deleted one of a person's
1038
- # tasks, we would probably not want the project to be deleted. In this scenario, the delete method
1039
- # won't actually work: it can only be used if the association on the join model is a
1040
- # +belongs_to+. In other situations you are expected to perform operations directly on
1041
- # either the associated records or the <tt>:through</tt> association.
1042
- #
1043
- # With a regular +has_many+ there is no distinction between the "associated records"
1044
- # and the "link", so there is only one choice for what gets deleted.
1045
- #
1046
- # With +has_and_belongs_to_many+ and +has_many+ <tt>:through</tt>, if you want to delete the
1047
- # associated records themselves, you can always do something along the lines of
1048
- # <tt>person.tasks.each(&:destroy)</tt>.
1049
- #
1050
- # == Type safety with <tt>ActiveRecord::AssociationTypeMismatch</tt>
1051
- #
1052
- # If you attempt to assign an object to an association that doesn't match the inferred
1053
- # or specified <tt>:class_name</tt>, you'll get an <tt>ActiveRecord::AssociationTypeMismatch</tt>.
1054
- #
1055
- # == Options
1056
- #
1057
- # All of the association macros can be specialized through options. This makes cases
1058
- # more complex than the simple and guessable ones possible.
1059
- module ClassMethods
1060
- # Specifies a one-to-many association. The following methods for retrieval and query of
1061
- # collections of associated objects will be added:
1062
- #
1063
- # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1064
- # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
1065
- #
1066
- # [collection(force_reload = false)]
1067
- # Returns an array of all the associated objects.
1068
- # An empty array is returned if none are found.
1069
- # [collection<<(object, ...)]
1070
- # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
1071
- # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1072
- # parent object, unless the parent object is a new record.
1073
- # [collection.delete(object, ...)]
1074
- # Removes one or more objects from the collection by setting their foreign keys to +NULL+.
1075
- # Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
1076
- # and deleted if they're associated with <tt>dependent: :delete_all</tt>.
1077
- #
1078
- # If the <tt>:through</tt> option is used, then the join records are deleted (rather than
1079
- # nullified) by default, but you can specify <tt>dependent: :destroy</tt> or
1080
- # <tt>dependent: :nullify</tt> to override this.
1081
- # [collection.destroy(object, ...)]
1082
- # Removes one or more objects from the collection by running <tt>destroy</tt> on
1083
- # each record, regardless of any dependent option, ensuring callbacks are run.
1084
- #
1085
- # If the <tt>:through</tt> option is used, then the join records are destroyed
1086
- # instead, not the objects themselves.
1087
- # [collection=objects]
1088
- # Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
1089
- # option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
1090
- # direct.
1091
- # [collection_singular_ids]
1092
- # Returns an array of the associated objects' ids
1093
- # [collection_singular_ids=ids]
1094
- # Replace the collection with the objects identified by the primary keys in +ids+. This
1095
- # method loads the models and calls <tt>collection=</tt>. See above.
1096
- # [collection.clear]
1097
- # Removes every object from the collection. This destroys the associated objects if they
1098
- # are associated with <tt>dependent: :destroy</tt>, deletes them directly from the
1099
- # database if <tt>dependent: :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
1100
- # If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
1101
- # Join models are directly deleted.
1102
- # [collection.empty?]
1103
- # Returns +true+ if there are no associated objects.
1104
- # [collection.size]
1105
- # Returns the number of associated objects.
1106
- # [collection.find(...)]
1107
- # Finds an associated object according to the same rules as <tt>ActiveRecord::Base.find</tt>.
1108
- # [collection.exists?(...)]
1109
- # Checks whether an associated object with the given conditions exists.
1110
- # Uses the same rules as <tt>ActiveRecord::Base.exists?</tt>.
1111
- # [collection.build(attributes = {}, ...)]
1112
- # Returns one or more new objects of the collection type that have been instantiated
1113
- # with +attributes+ and linked to this object through a foreign key, but have not yet
1114
- # been saved.
1115
- # [collection.create(attributes = {})]
1116
- # Returns a new object of the collection type that has been instantiated
1117
- # with +attributes+, linked to this object through a foreign key, and that has already
1118
- # been saved (if it passed the validation). *Note*: This only works if the base model
1119
- # already exists in the DB, not if it is a new (unsaved) record!
1120
- # [collection.create!(attributes = {})]
1121
- # Does the same as <tt>collection.create</tt>, but raises <tt>ActiveRecord::RecordInvalid</tt>
1122
- # if the record is invalid.
1123
- #
1124
- # === Example
1125
- #
1126
- # A <tt>Firm</tt> class declares <tt>has_many :clients</tt>, which will add:
1127
- # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>)
1128
- # * <tt>Firm#clients<<</tt>
1129
- # * <tt>Firm#clients.delete</tt>
1130
- # * <tt>Firm#clients.destroy</tt>
1131
- # * <tt>Firm#clients=</tt>
1132
- # * <tt>Firm#client_ids</tt>
1133
- # * <tt>Firm#client_ids=</tt>
1134
- # * <tt>Firm#clients.clear</tt>
1135
- # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
1136
- # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
1137
- # * <tt>Firm#clients.find</tt> (similar to <tt>Client.where(firm_id: id).find(id)</tt>)
1138
- # * <tt>Firm#clients.exists?(name: 'ACME')</tt> (similar to <tt>Client.exists?(name: 'ACME', firm_id: firm.id)</tt>)
1139
- # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
1140
- # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
1141
- # * <tt>Firm#clients.create!</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save!</tt>)
1142
- # The declaration can also include an +options+ hash to specialize the behavior of the association.
1143
- #
1144
- # === Scopes
1145
- #
1146
- # You can pass a second argument +scope+ as a callable (i.e. proc or
1147
- # lambda) to retrieve a specific set of records or customize the generated
1148
- # query when you access the associated collection.
1149
- #
1150
- # Scope examples:
1151
- # has_many :comments, -> { where(author_id: 1) }
1152
- # has_many :employees, -> { joins(:address) }
1153
- # has_many :posts, ->(post) { where("max_post_length > ?", post.length) }
1154
- #
1155
- # === Extensions
1156
- #
1157
- # The +extension+ argument allows you to pass a block into a has_many
1158
- # association. This is useful for adding new finders, creators and other
1159
- # factory-type methods to be used as part of the association.
1160
- #
1161
- # Extension examples:
1162
- # has_many :employees do
1163
- # def find_or_create_by_name(name)
1164
- # first_name, last_name = name.split(" ", 2)
1165
- # find_or_create_by(first_name: first_name, last_name: last_name)
357
+ # \Associations are a set of macro-like class methods for tying objects together through
358
+ # foreign keys. They express relationships like "Project has one Project Manager"
359
+ # or "Project belongs to a Portfolio". Each macro adds a number of methods to the
360
+ # class which are specialized according to the collection or association symbol and the
361
+ # options hash. It works much the same way as Ruby's own <tt>attr*</tt>
362
+ # methods.
363
+ #
364
+ # class Project < ActiveRecord::Base
365
+ # belongs_to :portfolio
366
+ # has_one :project_manager
367
+ # has_many :milestones
368
+ # has_and_belongs_to_many :categories
369
+ # end
370
+ #
371
+ # The project class now has the following methods (and more) to ease the traversal and
372
+ # manipulation of its relationships:
373
+ # * <tt>Project#portfolio</tt>, <tt>Project#portfolio=(portfolio)</tt>, <tt>Project#reload_portfolio</tt>
374
+ # * <tt>Project#project_manager</tt>, <tt>Project#project_manager=(project_manager)</tt>, <tt>Project#reload_project_manager</tt>
375
+ # * <tt>Project#milestones.empty?</tt>, <tt>Project#milestones.size</tt>, <tt>Project#milestones</tt>, <tt>Project#milestones<<(milestone)</tt>,
376
+ # <tt>Project#milestones.delete(milestone)</tt>, <tt>Project#milestones.destroy(milestone)</tt>, <tt>Project#milestones.find(milestone_id)</tt>,
377
+ # <tt>Project#milestones.build</tt>, <tt>Project#milestones.create</tt>
378
+ # * <tt>Project#categories.empty?</tt>, <tt>Project#categories.size</tt>, <tt>Project#categories</tt>, <tt>Project#categories<<(category1)</tt>,
379
+ # <tt>Project#categories.delete(category1)</tt>, <tt>Project#categories.destroy(category1)</tt>
380
+ #
381
+ # === A word of warning
382
+ #
383
+ # Don't create associations that have the same name as {instance methods}[rdoc-ref:ActiveRecord::Core] of
384
+ # <tt>ActiveRecord::Base</tt>. Since the association adds a method with that name to
385
+ # its model, using an association with the same name as one provided by <tt>ActiveRecord::Base</tt> will override the method inherited through <tt>ActiveRecord::Base</tt> and will break things.
386
+ # For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of <tt>ActiveRecord::Base</tt> instance methods.
387
+ #
388
+ # == Auto-generated methods
389
+ # See also Instance Public methods below for more details.
390
+ #
391
+ # === Singular associations (one-to-one)
392
+ # | | belongs_to |
393
+ # generated methods | belongs_to | :polymorphic | has_one
394
+ # ----------------------------------+------------+--------------+---------
395
+ # other | X | X | X
396
+ # other=(other) | X | X | X
397
+ # build_other(attributes={}) | X | | X
398
+ # create_other(attributes={}) | X | | X
399
+ # create_other!(attributes={}) | X | | X
400
+ # reload_other | X | X | X
401
+ #
402
+ # === Collection associations (one-to-many / many-to-many)
403
+ # | | | has_many
404
+ # generated methods | habtm | has_many | :through
405
+ # ----------------------------------+-------+----------+----------
406
+ # others | X | X | X
407
+ # others=(other,other,...) | X | X | X
408
+ # other_ids | X | X | X
409
+ # other_ids=(id,id,...) | X | X | X
410
+ # others<< | X | X | X
411
+ # others.push | X | X | X
412
+ # others.concat | X | X | X
413
+ # others.build(attributes={}) | X | X | X
414
+ # others.create(attributes={}) | X | X | X
415
+ # others.create!(attributes={}) | X | X | X
416
+ # others.size | X | X | X
417
+ # others.length | X | X | X
418
+ # others.count | X | X | X
419
+ # others.sum(*args) | X | X | X
420
+ # others.empty? | X | X | X
421
+ # others.clear | X | X | X
422
+ # others.delete(other,other,...) | X | X | X
423
+ # others.delete_all | X | X | X
424
+ # others.destroy(other,other,...) | X | X | X
425
+ # others.destroy_all | X | X | X
426
+ # others.find(*args) | X | X | X
427
+ # others.exists? | X | X | X
428
+ # others.distinct | X | X | X
429
+ # others.reset | X | X | X
430
+ # others.reload | X | X | X
431
+ #
432
+ # === Overriding generated methods
433
+ #
434
+ # Association methods are generated in a module included into the model
435
+ # class, making overrides easy. The original generated method can thus be
436
+ # called with +super+:
437
+ #
438
+ # class Car < ActiveRecord::Base
439
+ # belongs_to :owner
440
+ # belongs_to :old_owner
441
+ #
442
+ # def owner=(new_owner)
443
+ # self.old_owner = self.owner
444
+ # super
1166
445
  # end
1167
446
  # end
1168
447
  #
1169
- # === Options
1170
- # [:class_name]
1171
- # Specify the class name of the association. Use it only if that name can't be inferred
1172
- # from the association name. So <tt>has_many :products</tt> will by default be linked
1173
- # to the Product class, but if the real class name is SpecialProduct, you'll have to
1174
- # specify it with this option.
1175
- # [:foreign_key]
1176
- # Specify the foreign key used for the association. By default this is guessed to be the name
1177
- # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_many+
1178
- # association will use "person_id" as the default <tt>:foreign_key</tt>.
1179
- # [:foreign_type]
1180
- # Specify the column used to store the associated object's type, if this is a polymorphic
1181
- # association. By default this is guessed to be the name of the polymorphic association
1182
- # specified on "as" option with a "_type" suffix. So a class that defines a
1183
- # <tt>has_many :tags, as: :taggable</tt> association will use "taggable_type" as the
1184
- # default <tt>:foreign_type</tt>.
1185
- # [:primary_key]
1186
- # Specify the name of the column to use as the primary key for the association. By default this is +id+.
1187
- # [:dependent]
1188
- # Controls what happens to the associated objects when
1189
- # their owner is destroyed. Note that these are implemented as
1190
- # callbacks, and Rails executes callbacks in order. Therefore, other
1191
- # similar callbacks may affect the <tt>:dependent</tt> behavior, and the
1192
- # <tt>:dependent</tt> behavior may affect other callbacks.
1193
- #
1194
- # * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
1195
- # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
1196
- # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Callbacks are not executed.
1197
- # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there are any associated records.
1198
- # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
1199
- #
1200
- # If using with the <tt>:through</tt> option, the association on the join model must be
1201
- # a +belongs_to+, and the records which get deleted are the join records, rather than
1202
- # the associated records.
1203
- # [:counter_cache]
1204
- # This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
1205
- # when you customized the name of your <tt>:counter_cache</tt> on the <tt>belongs_to</tt> association.
1206
- # [:as]
1207
- # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
1208
- # [:through]
1209
- # Specifies an association through which to perform the query. This can be any other type
1210
- # of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
1211
- # <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
1212
- # source reflection.
1213
- #
1214
- # If the association on the join model is a +belongs_to+, the collection can be modified
1215
- # and the records on the <tt>:through</tt> model will be automatically created and removed
1216
- # as appropriate. Otherwise, the collection is read-only, so you should manipulate the
1217
- # <tt>:through</tt> association directly.
1218
- #
1219
- # If you are going to modify the association (rather than just read from it), then it is
1220
- # a good idea to set the <tt>:inverse_of</tt> option on the source association on the
1221
- # join model. This allows associated records to be built which will automatically create
1222
- # the appropriate join model records when they are saved. (See the 'Association Join Models'
1223
- # section above.)
1224
- # [:source]
1225
- # Specifies the source association name used by <tt>has_many :through</tt> queries.
1226
- # Only use it if the name cannot be inferred from the association.
1227
- # <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
1228
- # <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
1229
- # [:source_type]
1230
- # Specifies type of the source association used by <tt>has_many :through</tt> queries where the source
1231
- # association is a polymorphic +belongs_to+.
1232
- # [:validate]
1233
- # If +false+, don't validate the associated objects when saving the parent object. true by default.
1234
- # [:autosave]
1235
- # If true, always save the associated objects or destroy them if marked for destruction,
1236
- # when saving the parent object. If false, never save or destroy the associated objects.
1237
- # By default, only save associated objects that are new records. This option is implemented as a
1238
- # +before_save+ callback. Because callbacks are run in the order they are defined, associated objects
1239
- # may need to be explicitly saved in any user-defined +before_save+ callbacks.
1240
- #
1241
- # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1242
- # [:inverse_of]
1243
- # Specifies the name of the <tt>belongs_to</tt> association on the associated object
1244
- # that is the inverse of this <tt>has_many</tt> association. Does not work in combination
1245
- # with <tt>:through</tt> or <tt>:as</tt> options.
1246
- # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1247
- #
1248
- # Option examples:
1249
- # has_many :comments, -> { order "posted_on" }
1250
- # has_many :comments, -> { includes :author }
1251
- # has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
1252
- # has_many :tracks, -> { order "position" }, dependent: :destroy
1253
- # has_many :comments, dependent: :nullify
1254
- # has_many :tags, as: :taggable
1255
- # has_many :reports, -> { readonly }
1256
- # has_many :subscribers, through: :subscriptions, source: :user
1257
- def has_many(name, scope = nil, options = {}, &extension)
1258
- reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1259
- Reflection.add_reflection self, name, reflection
1260
- end
1261
-
1262
- # Specifies a one-to-one association with another class. This method should only be used
1263
- # if the other class contains the foreign key. If the current class contains the foreign key,
1264
- # then you should use +belongs_to+ instead. See also ActiveRecord::Associations::ClassMethods's overview
1265
- # on when to use +has_one+ and when to use +belongs_to+.
1266
- #
1267
- # The following methods for retrieval and query of a single associated object will be added:
1268
- #
1269
- # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1270
- # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
1271
- #
1272
- # [association(force_reload = false)]
1273
- # Returns the associated object. +nil+ is returned if none is found.
1274
- # [association=(associate)]
1275
- # Assigns the associate object, extracts the primary key, sets it as the foreign key,
1276
- # and saves the associate object. To avoid database inconsistencies, permanently deletes an existing
1277
- # associated object when assigning a new one, even if the new one isn't saved to database.
1278
- # [build_association(attributes = {})]
1279
- # Returns a new object of the associated type that has been instantiated
1280
- # with +attributes+ and linked to this object through a foreign key, but has not
1281
- # yet been saved.
1282
- # [create_association(attributes = {})]
1283
- # Returns a new object of the associated type that has been instantiated
1284
- # with +attributes+, linked to this object through a foreign key, and that
1285
- # has already been saved (if it passed the validation).
1286
- # [create_association!(attributes = {})]
1287
- # Does the same as <tt>create_association</tt>, but raises <tt>ActiveRecord::RecordInvalid</tt>
1288
- # if the record is invalid.
1289
- #
1290
- # === Example
1291
- #
1292
- # An Account class declares <tt>has_one :beneficiary</tt>, which will add:
1293
- # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.where(account_id: id).first</tt>)
1294
- # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
1295
- # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
1296
- # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
1297
- # * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save!; b</tt>)
1298
- #
1299
- # === Scopes
1300
- #
1301
- # You can pass a second argument +scope+ as a callable (i.e. proc or
1302
- # lambda) to retrieve a specific record or customize the generated query
1303
- # when you access the associated object.
1304
- #
1305
- # Scope examples:
1306
- # has_one :author, -> { where(comment_id: 1) }
1307
- # has_one :employer, -> { joins(:company) }
1308
- # has_one :dob, ->(dob) { where("Date.new(2000, 01, 01) > ?", dob) }
1309
- #
1310
- # === Options
1311
- #
1312
- # The declaration can also include an +options+ hash to specialize the behavior of the association.
1313
- #
1314
- # Options are:
1315
- # [:class_name]
1316
- # Specify the class name of the association. Use it only if that name can't be inferred
1317
- # from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
1318
- # if the real class name is Person, you'll have to specify it with this option.
1319
- # [:dependent]
1320
- # Controls what happens to the associated object when
1321
- # its owner is destroyed:
1322
- #
1323
- # * <tt>:destroy</tt> causes the associated object to also be destroyed
1324
- # * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
1325
- # * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Callbacks are not executed.
1326
- # * <tt>:restrict_with_exception</tt> causes an exception to be raised if there is an associated record
1327
- # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
1328
- # [:foreign_key]
1329
- # Specify the foreign key used for the association. By default this is guessed to be the name
1330
- # of this class in lower-case and "_id" suffixed. So a Person class that makes a +has_one+ association
1331
- # will use "person_id" as the default <tt>:foreign_key</tt>.
1332
- # [:foreign_type]
1333
- # Specify the column used to store the associated object's type, if this is a polymorphic
1334
- # association. By default this is guessed to be the name of the polymorphic association
1335
- # specified on "as" option with a "_type" suffix. So a class that defines a
1336
- # <tt>has_one :tag, as: :taggable</tt> association will use "taggable_type" as the
1337
- # default <tt>:foreign_type</tt>.
1338
- # [:primary_key]
1339
- # Specify the method that returns the primary key used for the association. By default this is +id+.
1340
- # [:as]
1341
- # Specifies a polymorphic interface (See <tt>belongs_to</tt>).
1342
- # [:through]
1343
- # Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
1344
- # <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
1345
- # source reflection. You can only use a <tt>:through</tt> query through a <tt>has_one</tt>
1346
- # or <tt>belongs_to</tt> association on the join model.
1347
- # [:source]
1348
- # Specifies the source association name used by <tt>has_one :through</tt> queries.
1349
- # Only use it if the name cannot be inferred from the association.
1350
- # <tt>has_one :favorite, through: :favorites</tt> will look for a
1351
- # <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
1352
- # [:source_type]
1353
- # Specifies type of the source association used by <tt>has_one :through</tt> queries where the source
1354
- # association is a polymorphic +belongs_to+.
1355
- # [:validate]
1356
- # If +false+, don't validate the associated object when saving the parent object. +false+ by default.
1357
- # [:autosave]
1358
- # If true, always save the associated object or destroy it if marked for destruction,
1359
- # when saving the parent object. If false, never save or destroy the associated object.
1360
- # By default, only save the associated object if it's a new record.
1361
- #
1362
- # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1363
- # [:inverse_of]
1364
- # Specifies the name of the <tt>belongs_to</tt> association on the associated object
1365
- # that is the inverse of this <tt>has_one</tt> association. Does not work in combination
1366
- # with <tt>:through</tt> or <tt>:as</tt> options.
1367
- # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1368
- # [:required]
1369
- # When set to +true+, the association will also have its presence validated.
1370
- # This will validate the association itself, not the id. You can use
1371
- # +:inverse_of+ to avoid an extra query during validation.
1372
- #
1373
- # Option examples:
1374
- # has_one :credit_card, dependent: :destroy # destroys the associated credit card
1375
- # has_one :credit_card, dependent: :nullify # updates the associated records foreign
1376
- # # key value to NULL rather than destroying it
1377
- # has_one :last_comment, -> { order 'posted_on' }, class_name: "Comment"
1378
- # has_one :project_manager, -> { where role: 'project_manager' }, class_name: "Person"
1379
- # has_one :attachment, as: :attachable
1380
- # has_one :boss, readonly: :true
1381
- # has_one :club, through: :membership
1382
- # has_one :primary_address, -> { where primary: true }, through: :addressables, source: :addressable
1383
- # has_one :credit_card, required: true
1384
- def has_one(name, scope = nil, options = {})
1385
- reflection = Builder::HasOne.build(self, name, scope, options)
1386
- Reflection.add_reflection self, name, reflection
1387
- end
1388
-
1389
- # Specifies a one-to-one association with another class. This method should only be used
1390
- # if this class contains the foreign key. If the other class contains the foreign key,
1391
- # then you should use +has_one+ instead. See also ActiveRecord::Associations::ClassMethods's overview
1392
- # on when to use +has_one+ and when to use +belongs_to+.
1393
- #
1394
- # Methods will be added for retrieval and query for a single associated object, for which
1395
- # this object holds an id:
1396
- #
1397
- # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1398
- # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
1399
- #
1400
- # [association(force_reload = false)]
1401
- # Returns the associated object. +nil+ is returned if none is found.
1402
- # [association=(associate)]
1403
- # Assigns the associate object, extracts the primary key, and sets it as the foreign key.
1404
- # [build_association(attributes = {})]
1405
- # Returns a new object of the associated type that has been instantiated
1406
- # with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
1407
- # [create_association(attributes = {})]
1408
- # Returns a new object of the associated type that has been instantiated
1409
- # with +attributes+, linked to this object through a foreign key, and that
1410
- # has already been saved (if it passed the validation).
1411
- # [create_association!(attributes = {})]
1412
- # Does the same as <tt>create_association</tt>, but raises <tt>ActiveRecord::RecordInvalid</tt>
1413
- # if the record is invalid.
1414
- #
1415
- # === Example
1416
- #
1417
- # A Post class declares <tt>belongs_to :author</tt>, which will add:
1418
- # * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
1419
- # * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
1420
- # * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
1421
- # * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
1422
- # * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
1423
- # The declaration can also include an +options+ hash to specialize the behavior of the association.
1424
- #
1425
- # === Scopes
1426
- #
1427
- # You can pass a second argument +scope+ as a callable (i.e. proc or
1428
- # lambda) to retrieve a specific record or customize the generated query
1429
- # when you access the associated object.
1430
- #
1431
- # Scope examples:
1432
- # belongs_to :user, -> { where(id: 2) }
1433
- # belongs_to :user, -> { joins(:friends) }
1434
- # belongs_to :level, ->(level) { where("game_level > ?", level.current) }
1435
- #
1436
- # === Options
1437
- #
1438
- # [:class_name]
1439
- # Specify the class name of the association. Use it only if that name can't be inferred
1440
- # from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
1441
- # if the real class name is Person, you'll have to specify it with this option.
1442
- # [:foreign_key]
1443
- # Specify the foreign key used for the association. By default this is guessed to be the name
1444
- # of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
1445
- # association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
1446
- # <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
1447
- # of "favorite_person_id".
1448
- # [:foreign_type]
1449
- # Specify the column used to store the associated object's type, if this is a polymorphic
1450
- # association. By default this is guessed to be the name of the association with a "_type"
1451
- # suffix. So a class that defines a <tt>belongs_to :taggable, polymorphic: true</tt>
1452
- # association will use "taggable_type" as the default <tt>:foreign_type</tt>.
1453
- # [:primary_key]
1454
- # Specify the method that returns the primary key of associated object used for the association.
1455
- # By default this is id.
1456
- # [:dependent]
1457
- # If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
1458
- # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method.
1459
- # This option should not be specified when <tt>belongs_to</tt> is used in conjunction with
1460
- # a <tt>has_many</tt> relationship on another class because of the potential to leave
1461
- # orphaned records behind.
1462
- # [:counter_cache]
1463
- # Caches the number of belonging objects on the associate class through the use of +increment_counter+
1464
- # and +decrement_counter+. The counter cache is incremented when an object of this
1465
- # class is created and decremented when it's destroyed. This requires that a column
1466
- # named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
1467
- # is used on the associate class (such as a Post class) - that is the migration for
1468
- # <tt>#{table_name}_count</tt> is created on the associate class (such that <tt>Post.comments_count</tt> will
1469
- # return the count cached, see note below). You can also specify a custom counter
1470
- # cache column by providing a column name instead of a +true+/+false+ value to this
1471
- # option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
1472
- # Note: Specifying a counter cache will add it to that model's list of readonly attributes
1473
- # using +attr_readonly+.
1474
- # [:polymorphic]
1475
- # Specify this association is a polymorphic association by passing +true+.
1476
- # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
1477
- # to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
1478
- # [:validate]
1479
- # If +false+, don't validate the associated objects when saving the parent object. +false+ by default.
1480
- # [:autosave]
1481
- # If true, always save the associated object or destroy it if marked for destruction, when
1482
- # saving the parent object.
1483
- # If false, never save or destroy the associated object.
1484
- # By default, only save the associated object if it's a new record.
1485
- #
1486
- # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1487
- # [:touch]
1488
- # If true, the associated object will be touched (the updated_at/on attributes set to current time)
1489
- # when this record is either saved or destroyed. If you specify a symbol, that attribute
1490
- # will be updated with the current time in addition to the updated_at/on attribute.
1491
- # [:inverse_of]
1492
- # Specifies the name of the <tt>has_one</tt> or <tt>has_many</tt> association on the associated
1493
- # object that is the inverse of this <tt>belongs_to</tt> association. Does not work in
1494
- # combination with the <tt>:polymorphic</tt> options.
1495
- # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1496
- # [:required]
1497
- # When set to +true+, the association will also have its presence validated.
1498
- # This will validate the association itself, not the id. You can use
1499
- # +:inverse_of+ to avoid an extra query during validation.
1500
- #
1501
- # Option examples:
1502
- # belongs_to :firm, foreign_key: "client_of"
1503
- # belongs_to :person, primary_key: "name", foreign_key: "person_name"
1504
- # belongs_to :author, class_name: "Person", foreign_key: "author_id"
1505
- # belongs_to :valid_coupon, ->(o) { where "discounts > ?", o.payments_count },
1506
- # class_name: "Coupon", foreign_key: "coupon_id"
1507
- # belongs_to :attachable, polymorphic: true
1508
- # belongs_to :project, readonly: true
1509
- # belongs_to :post, counter_cache: true
1510
- # belongs_to :company, touch: true
1511
- # belongs_to :company, touch: :employees_last_updated_at
1512
- # belongs_to :company, required: true
1513
- def belongs_to(name, scope = nil, options = {})
1514
- reflection = Builder::BelongsTo.build(self, name, scope, options)
1515
- Reflection.add_reflection self, name, reflection
1516
- end
1517
-
1518
- # Specifies a many-to-many relationship with another class. This associates two classes via an
1519
- # intermediate join table. Unless the join table is explicitly specified as an option, it is
1520
- # guessed using the lexical order of the class names. So a join between Developer and Project
1521
- # will give the default join table name of "developers_projects" because "D" precedes "P" alphabetically.
1522
- # Note that this precedence is calculated using the <tt><</tt> operator for String. This
1523
- # means that if the strings are of different lengths, and the strings are equal when compared
1524
- # up to the shortest length, then the longer string is considered of higher
1525
- # lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers"
1526
- # to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes",
1527
- # but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
1528
- # custom <tt>:join_table</tt> option if you need to.
1529
- # If your tables share a common prefix, it will only appear once at the beginning. For example,
1530
- # the tables "catalog_categories" and "catalog_products" generate a join table name of "catalog_categories_products".
1531
- #
1532
- # The join table should not have a primary key or a model associated with it. You must manually generate the
1533
- # join table with a migration such as this:
1534
- #
1535
- # class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
1536
- # def change
1537
- # create_table :developers_projects, id: false do |t|
1538
- # t.integer :developer_id
1539
- # t.integer :project_id
448
+ # The association methods module is included immediately after the
449
+ # generated attributes methods module, meaning an association will
450
+ # override the methods for an attribute with the same name.
451
+ #
452
+ # == Cardinality and associations
453
+ #
454
+ # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
455
+ # relationships between models. Each model uses an association to describe its role in
456
+ # the relation. The #belongs_to association is always used in the model that has
457
+ # the foreign key.
458
+ #
459
+ # === One-to-one
460
+ #
461
+ # Use #has_one in the base, and #belongs_to in the associated model.
462
+ #
463
+ # class Employee < ActiveRecord::Base
464
+ # has_one :office
465
+ # end
466
+ # class Office < ActiveRecord::Base
467
+ # belongs_to :employee # foreign key - employee_id
468
+ # end
469
+ #
470
+ # === One-to-many
471
+ #
472
+ # Use #has_many in the base, and #belongs_to in the associated model.
473
+ #
474
+ # class Manager < ActiveRecord::Base
475
+ # has_many :employees
476
+ # end
477
+ # class Employee < ActiveRecord::Base
478
+ # belongs_to :manager # foreign key - manager_id
479
+ # end
480
+ #
481
+ # === Many-to-many
482
+ #
483
+ # There are two ways to build a many-to-many relationship.
484
+ #
485
+ # The first way uses a #has_many association with the <tt>:through</tt> option and a join model, so
486
+ # there are two stages of associations.
487
+ #
488
+ # class Assignment < ActiveRecord::Base
489
+ # belongs_to :programmer # foreign key - programmer_id
490
+ # belongs_to :project # foreign key - project_id
491
+ # end
492
+ # class Programmer < ActiveRecord::Base
493
+ # has_many :assignments
494
+ # has_many :projects, through: :assignments
495
+ # end
496
+ # class Project < ActiveRecord::Base
497
+ # has_many :assignments
498
+ # has_many :programmers, through: :assignments
499
+ # end
500
+ #
501
+ # For the second way, use #has_and_belongs_to_many in both models. This requires a join table
502
+ # that has no corresponding model or primary key.
503
+ #
504
+ # class Programmer < ActiveRecord::Base
505
+ # has_and_belongs_to_many :projects # foreign keys in the join table
506
+ # end
507
+ # class Project < ActiveRecord::Base
508
+ # has_and_belongs_to_many :programmers # foreign keys in the join table
509
+ # end
510
+ #
511
+ # Choosing which way to build a many-to-many relationship is not always simple.
512
+ # If you need to work with the relationship model as its own entity,
513
+ # use #has_many <tt>:through</tt>. Use #has_and_belongs_to_many when working with legacy schemas or when
514
+ # you never work directly with the relationship itself.
515
+ #
516
+ # == Is it a #belongs_to or #has_one association?
517
+ #
518
+ # Both express a 1-1 relationship. The difference is mostly where to place the foreign
519
+ # key, which goes on the table for the class declaring the #belongs_to relationship.
520
+ #
521
+ # class User < ActiveRecord::Base
522
+ # # I reference an account.
523
+ # belongs_to :account
524
+ # end
525
+ #
526
+ # class Account < ActiveRecord::Base
527
+ # # One user references me.
528
+ # has_one :user
529
+ # end
530
+ #
531
+ # The tables for these classes could look something like:
532
+ #
533
+ # CREATE TABLE users (
534
+ # id bigint NOT NULL auto_increment,
535
+ # account_id bigint default NULL,
536
+ # name varchar default NULL,
537
+ # PRIMARY KEY (id)
538
+ # )
539
+ #
540
+ # CREATE TABLE accounts (
541
+ # id bigint NOT NULL auto_increment,
542
+ # name varchar default NULL,
543
+ # PRIMARY KEY (id)
544
+ # )
545
+ #
546
+ # == Unsaved objects and associations
547
+ #
548
+ # You can manipulate objects and associations before they are saved to the database, but
549
+ # there is some special behavior you should be aware of, mostly involving the saving of
550
+ # associated objects.
551
+ #
552
+ # You can set the <tt>:autosave</tt> option on a #has_one, #belongs_to,
553
+ # #has_many, or #has_and_belongs_to_many association. Setting it
554
+ # to +true+ will _always_ save the members, whereas setting it to +false+ will
555
+ # _never_ save the members. More details about <tt>:autosave</tt> option is available at
556
+ # AutosaveAssociation.
557
+ #
558
+ # === One-to-one associations
559
+ #
560
+ # * Assigning an object to a #has_one association automatically saves that object and
561
+ # the object being replaced (if there is one), in order to update their foreign
562
+ # keys - except if the parent object is unsaved (<tt>new_record? == true</tt>).
563
+ # * If either of these saves fail (due to one of the objects being invalid), an
564
+ # ActiveRecord::RecordNotSaved exception is raised and the assignment is
565
+ # cancelled.
566
+ # * If you wish to assign an object to a #has_one association without saving it,
567
+ # use the <tt>#build_association</tt> method (documented below). The object being
568
+ # replaced will still be saved to update its foreign key.
569
+ # * Assigning an object to a #belongs_to association does not save the object, since
570
+ # the foreign key field belongs on the parent. It does not save the parent either.
571
+ #
572
+ # === Collections
573
+ #
574
+ # * Adding an object to a collection (#has_many or #has_and_belongs_to_many) automatically
575
+ # saves that object, except if the parent object (the owner of the collection) is not yet
576
+ # stored in the database.
577
+ # * If saving any of the objects being added to a collection (via <tt>push</tt> or similar)
578
+ # fails, then <tt>push</tt> returns +false+.
579
+ # * If saving fails while replacing the collection (via <tt>association=</tt>), an
580
+ # ActiveRecord::RecordNotSaved exception is raised and the assignment is
581
+ # cancelled.
582
+ # * You can add an object to a collection without automatically saving it by using the
583
+ # <tt>collection.build</tt> method (documented below).
584
+ # * All unsaved (<tt>new_record? == true</tt>) members of the collection are automatically
585
+ # saved when the parent is saved.
586
+ #
587
+ # == Customizing the query
588
+ #
589
+ # \Associations are built from <tt>Relation</tt> objects, and you can use the Relation syntax
590
+ # to customize them. For example, to add a condition:
591
+ #
592
+ # class Blog < ActiveRecord::Base
593
+ # has_many :published_posts, -> { where(published: true) }, class_name: 'Post'
594
+ # end
595
+ #
596
+ # Inside the <tt>-> { ... }</tt> block you can use all of the usual Relation methods.
597
+ #
598
+ # === Accessing the owner object
599
+ #
600
+ # Sometimes it is useful to have access to the owner object when building the query. The owner
601
+ # is passed as a parameter to the block. For example, the following association would find all
602
+ # events that occur on the user's birthday:
603
+ #
604
+ # class User < ActiveRecord::Base
605
+ # has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
606
+ # end
607
+ #
608
+ # Note: Joining, eager loading and preloading of these associations is not possible.
609
+ # These operations happen before instance creation and the scope will be called with a +nil+ argument.
610
+ #
611
+ # == Association callbacks
612
+ #
613
+ # Similar to the normal callbacks that hook into the life cycle of an Active Record object,
614
+ # you can also define callbacks that get triggered when you add an object to or remove an
615
+ # object from an association collection.
616
+ #
617
+ # class Project
618
+ # has_and_belongs_to_many :developers, after_add: :evaluate_velocity
619
+ #
620
+ # def evaluate_velocity(developer)
621
+ # ...
622
+ # end
623
+ # end
624
+ #
625
+ # It's possible to stack callbacks by passing them as an array. Example:
626
+ #
627
+ # class Project
628
+ # has_and_belongs_to_many :developers,
629
+ # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
630
+ # end
631
+ #
632
+ # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
633
+ #
634
+ # If any of the +before_add+ callbacks throw an exception, the object will not be
635
+ # added to the collection.
636
+ #
637
+ # Similarly, if any of the +before_remove+ callbacks throw an exception, the object
638
+ # will not be removed from the collection.
639
+ #
640
+ # == Association extensions
641
+ #
642
+ # The proxy objects that control the access to associations can be extended through anonymous
643
+ # modules. This is especially beneficial for adding new finders, creators, and other
644
+ # factory-type methods that are only used as part of this association.
645
+ #
646
+ # class Account < ActiveRecord::Base
647
+ # has_many :people do
648
+ # def find_or_create_by_name(name)
649
+ # first_name, last_name = name.split(" ", 2)
650
+ # find_or_create_by(first_name: first_name, last_name: last_name)
1540
651
  # end
1541
652
  # end
1542
653
  # end
1543
654
  #
1544
- # It's also a good idea to add indexes to each of those columns to speed up the joins process.
1545
- # However, in MySQL it is advised to add a compound index for both of the columns as MySQL only
1546
- # uses one index per table during the lookup.
1547
- #
1548
- # Adds the following methods for retrieval and query:
1549
- #
1550
- # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1551
- # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
1552
- #
1553
- # [collection(force_reload = false)]
1554
- # Returns an array of all the associated objects.
1555
- # An empty array is returned if none are found.
1556
- # [collection<<(object, ...)]
1557
- # Adds one or more objects to the collection by creating associations in the join table
1558
- # (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
1559
- # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1560
- # parent object, unless the parent object is a new record.
1561
- # [collection.delete(object, ...)]
1562
- # Removes one or more objects from the collection by removing their associations from the join table.
1563
- # This does not destroy the objects.
1564
- # [collection.destroy(object, ...)]
1565
- # Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option.
1566
- # This does not destroy the objects.
1567
- # [collection=objects]
1568
- # Replaces the collection's content by deleting and adding objects as appropriate.
1569
- # [collection_singular_ids]
1570
- # Returns an array of the associated objects' ids.
1571
- # [collection_singular_ids=ids]
1572
- # Replace the collection by the objects identified by the primary keys in +ids+.
1573
- # [collection.clear]
1574
- # Removes every object from the collection. This does not destroy the objects.
1575
- # [collection.empty?]
1576
- # Returns +true+ if there are no associated objects.
1577
- # [collection.size]
1578
- # Returns the number of associated objects.
1579
- # [collection.find(id)]
1580
- # Finds an associated object responding to the +id+ and that
1581
- # meets the condition that it has to be associated with this object.
1582
- # Uses the same rules as <tt>ActiveRecord::Base.find</tt>.
1583
- # [collection.exists?(...)]
1584
- # Checks whether an associated object with the given conditions exists.
1585
- # Uses the same rules as <tt>ActiveRecord::Base.exists?</tt>.
1586
- # [collection.build(attributes = {})]
1587
- # Returns a new object of the collection type that has been instantiated
1588
- # with +attributes+ and linked to this object through the join table, but has not yet been saved.
1589
- # [collection.create(attributes = {})]
1590
- # Returns a new object of the collection type that has been instantiated
1591
- # with +attributes+, linked to this object through the join table, and that has already been
1592
- # saved (if it passed the validation).
1593
- #
1594
- # === Example
1595
- #
1596
- # A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
1597
- # * <tt>Developer#projects</tt>
1598
- # * <tt>Developer#projects<<</tt>
1599
- # * <tt>Developer#projects.delete</tt>
1600
- # * <tt>Developer#projects.destroy</tt>
1601
- # * <tt>Developer#projects=</tt>
1602
- # * <tt>Developer#project_ids</tt>
1603
- # * <tt>Developer#project_ids=</tt>
1604
- # * <tt>Developer#projects.clear</tt>
1605
- # * <tt>Developer#projects.empty?</tt>
1606
- # * <tt>Developer#projects.size</tt>
1607
- # * <tt>Developer#projects.find(id)</tt>
1608
- # * <tt>Developer#projects.exists?(...)</tt>
1609
- # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("developer_id" => id)</tt>)
1610
- # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("developer_id" => id); c.save; c</tt>)
1611
- # The declaration may include an +options+ hash to specialize the behavior of the association.
1612
- #
1613
- # === Scopes
1614
- #
1615
- # You can pass a second argument +scope+ as a callable (i.e. proc or
1616
- # lambda) to retrieve a specific set of records or customize the generated
1617
- # query when you access the associated collection.
1618
- #
1619
- # Scope examples:
1620
- # has_and_belongs_to_many :projects, -> { includes :milestones, :manager }
1621
- # has_and_belongs_to_many :categories, ->(category) {
1622
- # where("default_category = ?", category.name)
1623
- # }
1624
- #
1625
- # === Extensions
1626
- #
1627
- # The +extension+ argument allows you to pass a block into a
1628
- # has_and_belongs_to_many association. This is useful for adding new
1629
- # finders, creators and other factory-type methods to be used as part of
1630
- # the association.
1631
- #
1632
- # Extension examples:
1633
- # has_and_belongs_to_many :contractors do
655
+ # person = Account.first.people.find_or_create_by_name("David Heinemeier Hansson")
656
+ # person.first_name # => "David"
657
+ # person.last_name # => "Heinemeier Hansson"
658
+ #
659
+ # If you need to share the same extensions between many associations, you can use a named
660
+ # extension module.
661
+ #
662
+ # module FindOrCreateByNameExtension
1634
663
  # def find_or_create_by_name(name)
1635
664
  # first_name, last_name = name.split(" ", 2)
1636
665
  # find_or_create_by(first_name: first_name, last_name: last_name)
1637
666
  # end
1638
667
  # end
1639
668
  #
1640
- # === Options
1641
- #
1642
- # [:class_name]
1643
- # Specify the class name of the association. Use it only if that name can't be inferred
1644
- # from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
1645
- # Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
1646
- # [:join_table]
1647
- # Specify the name of the join table if the default based on lexical order isn't what you want.
1648
- # <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
1649
- # MUST be declared underneath any +has_and_belongs_to_many+ declaration in order to work.
1650
- # [:foreign_key]
1651
- # Specify the foreign key used for the association. By default this is guessed to be the name
1652
- # of this class in lower-case and "_id" suffixed. So a Person class that makes
1653
- # a +has_and_belongs_to_many+ association to Project will use "person_id" as the
1654
- # default <tt>:foreign_key</tt>.
1655
- # [:association_foreign_key]
1656
- # Specify the foreign key used for the association on the receiving side of the association.
1657
- # By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
1658
- # So if a Person class makes a +has_and_belongs_to_many+ association to Project,
1659
- # the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
1660
- # [:readonly]
1661
- # If true, all the associated objects are readonly through the association.
1662
- # [:validate]
1663
- # If +false+, don't validate the associated objects when saving the parent object. +true+ by default.
1664
- # [:autosave]
1665
- # If true, always save the associated objects or destroy them if marked for destruction, when
1666
- # saving the parent object.
1667
- # If false, never save or destroy the associated objects.
1668
- # By default, only save associated objects that are new records.
1669
- #
1670
- # Note that <tt>accepts_nested_attributes_for</tt> sets <tt>:autosave</tt> to <tt>true</tt>.
1671
- #
1672
- # Option examples:
1673
- # has_and_belongs_to_many :projects
1674
- # has_and_belongs_to_many :projects, -> { includes :milestones, :manager }
1675
- # has_and_belongs_to_many :nations, class_name: "Country"
1676
- # has_and_belongs_to_many :categories, join_table: "prods_cats"
1677
- # has_and_belongs_to_many :categories, -> { readonly }
1678
- def has_and_belongs_to_many(name, scope = nil, options = {}, &extension)
1679
- if scope.is_a?(Hash)
1680
- options = scope
1681
- scope = nil
669
+ # class Account < ActiveRecord::Base
670
+ # has_many :people, -> { extending FindOrCreateByNameExtension }
671
+ # end
672
+ #
673
+ # class Company < ActiveRecord::Base
674
+ # has_many :people, -> { extending FindOrCreateByNameExtension }
675
+ # end
676
+ #
677
+ # Some extensions can only be made to work with knowledge of the association's internals.
678
+ # Extensions can access relevant state using the following methods (where +items+ is the
679
+ # name of the association):
680
+ #
681
+ # * <tt>record.association(:items).owner</tt> - Returns the object the association is part of.
682
+ # * <tt>record.association(:items).reflection</tt> - Returns the reflection object that describes the association.
683
+ # * <tt>record.association(:items).target</tt> - Returns the associated object for #belongs_to and #has_one, or
684
+ # the collection of associated objects for #has_many and #has_and_belongs_to_many.
685
+ #
686
+ # However, inside the actual extension code, you will not have access to the <tt>record</tt> as
687
+ # above. In this case, you can access <tt>proxy_association</tt>. For example,
688
+ # <tt>record.association(:items)</tt> and <tt>record.items.proxy_association</tt> will return
689
+ # the same object, allowing you to make calls like <tt>proxy_association.owner</tt> inside
690
+ # association extensions.
691
+ #
692
+ # == Association Join Models
693
+ #
694
+ # Has Many associations can be configured with the <tt>:through</tt> option to use an
695
+ # explicit join model to retrieve the data. This operates similarly to a
696
+ # #has_and_belongs_to_many association. The advantage is that you're able to add validations,
697
+ # callbacks, and extra attributes on the join model. Consider the following schema:
698
+ #
699
+ # class Author < ActiveRecord::Base
700
+ # has_many :authorships
701
+ # has_many :books, through: :authorships
702
+ # end
703
+ #
704
+ # class Authorship < ActiveRecord::Base
705
+ # belongs_to :author
706
+ # belongs_to :book
707
+ # end
708
+ #
709
+ # @author = Author.first
710
+ # @author.authorships.collect { |a| a.book } # selects all books that the author's authorships belong to
711
+ # @author.books # selects all books by using the Authorship join model
712
+ #
713
+ # You can also go through a #has_many association on the join model:
714
+ #
715
+ # class Firm < ActiveRecord::Base
716
+ # has_many :clients
717
+ # has_many :invoices, through: :clients
718
+ # end
719
+ #
720
+ # class Client < ActiveRecord::Base
721
+ # belongs_to :firm
722
+ # has_many :invoices
723
+ # end
724
+ #
725
+ # class Invoice < ActiveRecord::Base
726
+ # belongs_to :client
727
+ # end
728
+ #
729
+ # @firm = Firm.first
730
+ # @firm.clients.flat_map { |c| c.invoices } # select all invoices for all clients of the firm
731
+ # @firm.invoices # selects all invoices by going through the Client join model
732
+ #
733
+ # Similarly you can go through a #has_one association on the join model:
734
+ #
735
+ # class Group < ActiveRecord::Base
736
+ # has_many :users
737
+ # has_many :avatars, through: :users
738
+ # end
739
+ #
740
+ # class User < ActiveRecord::Base
741
+ # belongs_to :group
742
+ # has_one :avatar
743
+ # end
744
+ #
745
+ # class Avatar < ActiveRecord::Base
746
+ # belongs_to :user
747
+ # end
748
+ #
749
+ # @group = Group.first
750
+ # @group.users.collect { |u| u.avatar }.compact # select all avatars for all users in the group
751
+ # @group.avatars # selects all avatars by going through the User join model.
752
+ #
753
+ # An important caveat with going through #has_one or #has_many associations on the
754
+ # join model is that these associations are *read-only*. For example, the following
755
+ # would not work following the previous example:
756
+ #
757
+ # @group.avatars << Avatar.new # this would work if User belonged_to Avatar rather than the other way around
758
+ # @group.avatars.delete(@group.avatars.last) # so would this
759
+ #
760
+ # == Setting Inverses
761
+ #
762
+ # If you are using a #belongs_to on the join model, it is a good idea to set the
763
+ # <tt>:inverse_of</tt> option on the #belongs_to, which will mean that the following example
764
+ # works correctly (where <tt>tags</tt> is a #has_many <tt>:through</tt> association):
765
+ #
766
+ # @post = Post.first
767
+ # @tag = @post.tags.build name: "ruby"
768
+ # @tag.save
769
+ #
770
+ # The last line ought to save the through record (a <tt>Tagging</tt>). This will only work if the
771
+ # <tt>:inverse_of</tt> is set:
772
+ #
773
+ # class Tagging < ActiveRecord::Base
774
+ # belongs_to :post
775
+ # belongs_to :tag, inverse_of: :taggings
776
+ # end
777
+ #
778
+ # If you do not set the <tt>:inverse_of</tt> record, the association will
779
+ # do its best to match itself up with the correct inverse. Automatic
780
+ # inverse detection only works on #has_many, #has_one, and
781
+ # #belongs_to associations.
782
+ #
783
+ # <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations,
784
+ # or a custom scope, will also prevent the association's inverse
785
+ # from being found automatically.
786
+ #
787
+ # The automatic guessing of the inverse association uses a heuristic based
788
+ # on the name of the class, so it may not work for all associations,
789
+ # especially the ones with non-standard names.
790
+ #
791
+ # You can turn off the automatic detection of inverse associations by setting
792
+ # the <tt>:inverse_of</tt> option to <tt>false</tt> like so:
793
+ #
794
+ # class Tagging < ActiveRecord::Base
795
+ # belongs_to :tag, inverse_of: false
796
+ # end
797
+ #
798
+ # == Nested \Associations
799
+ #
800
+ # You can actually specify *any* association with the <tt>:through</tt> option, including an
801
+ # association which has a <tt>:through</tt> option itself. For example:
802
+ #
803
+ # class Author < ActiveRecord::Base
804
+ # has_many :posts
805
+ # has_many :comments, through: :posts
806
+ # has_many :commenters, through: :comments
807
+ # end
808
+ #
809
+ # class Post < ActiveRecord::Base
810
+ # has_many :comments
811
+ # end
812
+ #
813
+ # class Comment < ActiveRecord::Base
814
+ # belongs_to :commenter
815
+ # end
816
+ #
817
+ # @author = Author.first
818
+ # @author.commenters # => People who commented on posts written by the author
819
+ #
820
+ # An equivalent way of setting up this association this would be:
821
+ #
822
+ # class Author < ActiveRecord::Base
823
+ # has_many :posts
824
+ # has_many :commenters, through: :posts
825
+ # end
826
+ #
827
+ # class Post < ActiveRecord::Base
828
+ # has_many :comments
829
+ # has_many :commenters, through: :comments
830
+ # end
831
+ #
832
+ # class Comment < ActiveRecord::Base
833
+ # belongs_to :commenter
834
+ # end
835
+ #
836
+ # When using a nested association, you will not be able to modify the association because there
837
+ # is not enough information to know what modification to make. For example, if you tried to
838
+ # add a <tt>Commenter</tt> in the example above, there would be no way to tell how to set up the
839
+ # intermediate <tt>Post</tt> and <tt>Comment</tt> objects.
840
+ #
841
+ # == Polymorphic \Associations
842
+ #
843
+ # Polymorphic associations on models are not restricted on what types of models they
844
+ # can be associated with. Rather, they specify an interface that a #has_many association
845
+ # must adhere to.
846
+ #
847
+ # class Asset < ActiveRecord::Base
848
+ # belongs_to :attachable, polymorphic: true
849
+ # end
850
+ #
851
+ # class Post < ActiveRecord::Base
852
+ # has_many :assets, as: :attachable # The :as option specifies the polymorphic interface to use.
853
+ # end
854
+ #
855
+ # @asset.attachable = @post
856
+ #
857
+ # This works by using a type column in addition to a foreign key to specify the associated
858
+ # record. In the Asset example, you'd need an +attachable_id+ integer column and an
859
+ # +attachable_type+ string column.
860
+ #
861
+ # Using polymorphic associations in combination with single table inheritance (STI) is
862
+ # a little tricky. In order for the associations to work as expected, ensure that you
863
+ # store the base model for the STI models in the type column of the polymorphic
864
+ # association. To continue with the asset example above, suppose there are guest posts
865
+ # and member posts that use the posts table for STI. In this case, there must be a +type+
866
+ # column in the posts table.
867
+ #
868
+ # Note: The <tt>attachable_type=</tt> method is being called when assigning an +attachable+.
869
+ # The +class_name+ of the +attachable+ is passed as a String.
870
+ #
871
+ # class Asset < ActiveRecord::Base
872
+ # belongs_to :attachable, polymorphic: true
873
+ #
874
+ # def attachable_type=(class_name)
875
+ # super(class_name.constantize.base_class.to_s)
876
+ # end
877
+ # end
878
+ #
879
+ # class Post < ActiveRecord::Base
880
+ # # because we store "Post" in attachable_type now dependent: :destroy will work
881
+ # has_many :assets, as: :attachable, dependent: :destroy
882
+ # end
883
+ #
884
+ # class GuestPost < Post
885
+ # end
886
+ #
887
+ # class MemberPost < Post
888
+ # end
889
+ #
890
+ # == Caching
891
+ #
892
+ # All of the methods are built on a simple caching principle that will keep the result
893
+ # of the last query around unless specifically instructed not to. The cache is even
894
+ # shared across methods to make it even cheaper to use the macro-added methods without
895
+ # worrying too much about performance at the first go.
896
+ #
897
+ # project.milestones # fetches milestones from the database
898
+ # project.milestones.size # uses the milestone cache
899
+ # project.milestones.empty? # uses the milestone cache
900
+ # project.milestones.reload.size # fetches milestones from the database
901
+ # project.milestones # uses the milestone cache
902
+ #
903
+ # == Eager loading of associations
904
+ #
905
+ # Eager loading is a way to find objects of a certain class and a number of named associations.
906
+ # It is one of the easiest ways to prevent the dreaded N+1 problem in which fetching 100
907
+ # posts that each need to display their author triggers 101 database queries. Through the
908
+ # use of eager loading, the number of queries will be reduced from 101 to 2.
909
+ #
910
+ # class Post < ActiveRecord::Base
911
+ # belongs_to :author
912
+ # has_many :comments
913
+ # end
914
+ #
915
+ # Consider the following loop using the class above:
916
+ #
917
+ # Post.all.each do |post|
918
+ # puts "Post: " + post.title
919
+ # puts "Written by: " + post.author.name
920
+ # puts "Last comment on: " + post.comments.first.created_on
921
+ # end
922
+ #
923
+ # To iterate over these one hundred posts, we'll generate 201 database queries. Let's
924
+ # first just optimize it for retrieving the author:
925
+ #
926
+ # Post.includes(:author).each do |post|
927
+ #
928
+ # This references the name of the #belongs_to association that also used the <tt>:author</tt>
929
+ # symbol. After loading the posts, +find+ will collect the +author_id+ from each one and load
930
+ # all of the referenced authors with one query. Doing so will cut down the number of queries
931
+ # from 201 to 102.
932
+ #
933
+ # We can improve upon the situation further by referencing both associations in the finder with:
934
+ #
935
+ # Post.includes(:author, :comments).each do |post|
936
+ #
937
+ # This will load all comments with a single query. This reduces the total number of queries
938
+ # to 3. In general, the number of queries will be 1 plus the number of associations
939
+ # named (except if some of the associations are polymorphic #belongs_to - see below).
940
+ #
941
+ # To include a deep hierarchy of associations, use a hash:
942
+ #
943
+ # Post.includes(:author, { comments: { author: :gravatar } }).each do |post|
944
+ #
945
+ # The above code will load all the comments and all of their associated
946
+ # authors and gravatars. You can mix and match any combination of symbols,
947
+ # arrays, and hashes to retrieve the associations you want to load.
948
+ #
949
+ # All of this power shouldn't fool you into thinking that you can pull out huge amounts
950
+ # of data with no performance penalty just because you've reduced the number of queries.
951
+ # The database still needs to send all the data to Active Record and it still needs to
952
+ # be processed. So it's no catch-all for performance problems, but it's a great way to
953
+ # cut down on the number of queries in a situation as the one described above.
954
+ #
955
+ # Since only one table is loaded at a time, conditions or orders cannot reference tables
956
+ # other than the main one. If this is the case, Active Record falls back to the previously
957
+ # used <tt>LEFT OUTER JOIN</tt> based strategy. For example:
958
+ #
959
+ # Post.includes([:author, :comments]).where(['comments.approved = ?', true])
960
+ #
961
+ # This will result in a single SQL query with joins along the lines of:
962
+ # <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and
963
+ # <tt>LEFT OUTER JOIN authors ON authors.id = posts.author_id</tt>. Note that using conditions
964
+ # like this can have unintended consequences.
965
+ # In the above example, posts with no approved comments are not returned at all because
966
+ # the conditions apply to the SQL statement as a whole and not just to the association.
967
+ #
968
+ # You must disambiguate column references for this fallback to happen, for example
969
+ # <tt>order: "author.name DESC"</tt> will work but <tt>order: "name DESC"</tt> will not.
970
+ #
971
+ # If you want to load all posts (including posts with no approved comments), then write
972
+ # your own <tt>LEFT OUTER JOIN</tt> query using <tt>ON</tt>:
973
+ #
974
+ # Post.joins("LEFT OUTER JOIN comments ON comments.post_id = posts.id AND comments.approved = '1'")
975
+ #
976
+ # In this case, it is usually more natural to include an association which has conditions defined on it:
977
+ #
978
+ # class Post < ActiveRecord::Base
979
+ # has_many :approved_comments, -> { where(approved: true) }, class_name: 'Comment'
980
+ # end
981
+ #
982
+ # Post.includes(:approved_comments)
983
+ #
984
+ # This will load posts and eager load the +approved_comments+ association, which contains
985
+ # only those comments that have been approved.
986
+ #
987
+ # If you eager load an association with a specified <tt>:limit</tt> option, it will be ignored,
988
+ # returning all the associated objects:
989
+ #
990
+ # class Picture < ActiveRecord::Base
991
+ # has_many :most_recent_comments, -> { order('id DESC').limit(10) }, class_name: 'Comment'
992
+ # end
993
+ #
994
+ # Picture.includes(:most_recent_comments).first.most_recent_comments # => returns all associated comments.
995
+ #
996
+ # Eager loading is supported with polymorphic associations.
997
+ #
998
+ # class Address < ActiveRecord::Base
999
+ # belongs_to :addressable, polymorphic: true
1000
+ # end
1001
+ #
1002
+ # A call that tries to eager load the addressable model
1003
+ #
1004
+ # Address.includes(:addressable)
1005
+ #
1006
+ # This will execute one query to load the addresses and load the addressables with one
1007
+ # query per addressable type.
1008
+ # For example, if all the addressables are either of class Person or Company, then a total
1009
+ # of 3 queries will be executed. The list of addressable types to load is determined on
1010
+ # the back of the addresses loaded. This is not supported if Active Record has to fallback
1011
+ # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
1012
+ # The reason is that the parent model's type is a column value so its corresponding table
1013
+ # name cannot be put in the +FROM+/+JOIN+ clauses of that query.
1014
+ #
1015
+ # == Table Aliasing
1016
+ #
1017
+ # Active Record uses table aliasing in the case that a table is referenced multiple times
1018
+ # in a join. If a table is referenced only once, the standard table name is used. The
1019
+ # second time, the table is aliased as <tt>#{reflection_name}_#{parent_table_name}</tt>.
1020
+ # Indexes are appended for any more successive uses of the table name.
1021
+ #
1022
+ # Post.joins(:comments)
1023
+ # # => SELECT ... FROM posts INNER JOIN comments ON ...
1024
+ # Post.joins(:special_comments) # STI
1025
+ # # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
1026
+ # Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
1027
+ # # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
1028
+ #
1029
+ # Acts as tree example:
1030
+ #
1031
+ # TreeMixin.joins(:children)
1032
+ # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1033
+ # TreeMixin.joins(children: :parent)
1034
+ # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1035
+ # INNER JOIN parents_mixins ...
1036
+ # TreeMixin.joins(children: {parent: :children})
1037
+ # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1038
+ # INNER JOIN parents_mixins ...
1039
+ # INNER JOIN mixins childrens_mixins_2
1040
+ #
1041
+ # Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
1042
+ #
1043
+ # Post.joins(:categories)
1044
+ # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1045
+ # Post.joins(categories: :posts)
1046
+ # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1047
+ # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
1048
+ # Post.joins(categories: {posts: :categories})
1049
+ # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1050
+ # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
1051
+ # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
1052
+ #
1053
+ # If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
1054
+ # names will take precedence over the eager associations:
1055
+ #
1056
+ # Post.joins(:comments).joins("inner join comments ...")
1057
+ # # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
1058
+ # Post.joins(:comments, :special_comments).joins("inner join comments ...")
1059
+ # # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
1060
+ # INNER JOIN comments special_comments_posts ...
1061
+ # INNER JOIN comments ...
1062
+ #
1063
+ # Table aliases are automatically truncated according to the maximum length of table identifiers
1064
+ # according to the specific database.
1065
+ #
1066
+ # == Modules
1067
+ #
1068
+ # By default, associations will look for objects within the current module scope. Consider:
1069
+ #
1070
+ # module MyApplication
1071
+ # module Business
1072
+ # class Firm < ActiveRecord::Base
1073
+ # has_many :clients
1074
+ # end
1075
+ #
1076
+ # class Client < ActiveRecord::Base; end
1077
+ # end
1078
+ # end
1079
+ #
1080
+ # When <tt>Firm#clients</tt> is called, it will in turn call
1081
+ # <tt>MyApplication::Business::Client.find_all_by_firm_id(firm.id)</tt>.
1082
+ # If you want to associate with a class in another module scope, this can be done by
1083
+ # specifying the complete class name.
1084
+ #
1085
+ # module MyApplication
1086
+ # module Business
1087
+ # class Firm < ActiveRecord::Base; end
1088
+ # end
1089
+ #
1090
+ # module Billing
1091
+ # class Account < ActiveRecord::Base
1092
+ # belongs_to :firm, class_name: "MyApplication::Business::Firm"
1093
+ # end
1094
+ # end
1095
+ # end
1096
+ #
1097
+ # == Bi-directional associations
1098
+ #
1099
+ # When you specify an association, there is usually an association on the associated model
1100
+ # that specifies the same relationship in reverse. For example, with the following models:
1101
+ #
1102
+ # class Dungeon < ActiveRecord::Base
1103
+ # has_many :traps
1104
+ # has_one :evil_wizard
1105
+ # end
1106
+ #
1107
+ # class Trap < ActiveRecord::Base
1108
+ # belongs_to :dungeon
1109
+ # end
1110
+ #
1111
+ # class EvilWizard < ActiveRecord::Base
1112
+ # belongs_to :dungeon
1113
+ # end
1114
+ #
1115
+ # The +traps+ association on +Dungeon+ and the +dungeon+ association on +Trap+ are
1116
+ # the inverse of each other, and the inverse of the +dungeon+ association on +EvilWizard+
1117
+ # is the +evil_wizard+ association on +Dungeon+ (and vice-versa). By default,
1118
+ # Active Record can guess the inverse of the association based on the name
1119
+ # of the class. The result is the following:
1120
+ #
1121
+ # d = Dungeon.first
1122
+ # t = d.traps.first
1123
+ # d.object_id == t.dungeon.object_id # => true
1124
+ #
1125
+ # The +Dungeon+ instances +d+ and <tt>t.dungeon</tt> in the above example refer to
1126
+ # the same in-memory instance since the association matches the name of the class.
1127
+ # The result would be the same if we added +:inverse_of+ to our model definitions:
1128
+ #
1129
+ # class Dungeon < ActiveRecord::Base
1130
+ # has_many :traps, inverse_of: :dungeon
1131
+ # has_one :evil_wizard, inverse_of: :dungeon
1132
+ # end
1133
+ #
1134
+ # class Trap < ActiveRecord::Base
1135
+ # belongs_to :dungeon, inverse_of: :traps
1136
+ # end
1137
+ #
1138
+ # class EvilWizard < ActiveRecord::Base
1139
+ # belongs_to :dungeon, inverse_of: :evil_wizard
1140
+ # end
1141
+ #
1142
+ # For more information, see the documentation for the +:inverse_of+ option.
1143
+ #
1144
+ # == Deleting from associations
1145
+ #
1146
+ # === Dependent associations
1147
+ #
1148
+ # #has_many, #has_one, and #belongs_to associations support the <tt>:dependent</tt> option.
1149
+ # This allows you to specify that associated records should be deleted when the owner is
1150
+ # deleted.
1151
+ #
1152
+ # For example:
1153
+ #
1154
+ # class Author
1155
+ # has_many :posts, dependent: :destroy
1156
+ # end
1157
+ # Author.find(1).destroy # => Will destroy all of the author's posts, too
1158
+ #
1159
+ # The <tt>:dependent</tt> option can have different values which specify how the deletion
1160
+ # is done. For more information, see the documentation for this option on the different
1161
+ # specific association types. When no option is given, the behavior is to do nothing
1162
+ # with the associated records when destroying a record.
1163
+ #
1164
+ # Note that <tt>:dependent</tt> is implemented using Rails' callback
1165
+ # system, which works by processing callbacks in order. Therefore, other
1166
+ # callbacks declared either before or after the <tt>:dependent</tt> option
1167
+ # can affect what it does.
1168
+ #
1169
+ # Note that <tt>:dependent</tt> option is ignored for #has_one <tt>:through</tt> associations.
1170
+ #
1171
+ # === Delete or destroy?
1172
+ #
1173
+ # #has_many and #has_and_belongs_to_many associations have the methods <tt>destroy</tt>,
1174
+ # <tt>delete</tt>, <tt>destroy_all</tt> and <tt>delete_all</tt>.
1175
+ #
1176
+ # For #has_and_belongs_to_many, <tt>delete</tt> and <tt>destroy</tt> are the same: they
1177
+ # cause the records in the join table to be removed.
1178
+ #
1179
+ # For #has_many, <tt>destroy</tt> and <tt>destroy_all</tt> will always call the <tt>destroy</tt> method of the
1180
+ # record(s) being removed so that callbacks are run. However <tt>delete</tt> and <tt>delete_all</tt> will either
1181
+ # do the deletion according to the strategy specified by the <tt>:dependent</tt> option, or
1182
+ # if no <tt>:dependent</tt> option is given, then it will follow the default strategy.
1183
+ # The default strategy is to do nothing (leave the foreign keys with the parent ids set), except for
1184
+ # #has_many <tt>:through</tt>, where the default strategy is <tt>delete_all</tt> (delete
1185
+ # the join records, without running their callbacks).
1186
+ #
1187
+ # There is also a <tt>clear</tt> method which is the same as <tt>delete_all</tt>, except that
1188
+ # it returns the association rather than the records which have been deleted.
1189
+ #
1190
+ # === What gets deleted?
1191
+ #
1192
+ # There is a potential pitfall here: #has_and_belongs_to_many and #has_many <tt>:through</tt>
1193
+ # associations have records in join tables, as well as the associated records. So when we
1194
+ # call one of these deletion methods, what exactly should be deleted?
1195
+ #
1196
+ # The answer is that it is assumed that deletion on an association is about removing the
1197
+ # <i>link</i> between the owner and the associated object(s), rather than necessarily the
1198
+ # associated objects themselves. So with #has_and_belongs_to_many and #has_many
1199
+ # <tt>:through</tt>, the join records will be deleted, but the associated records won't.
1200
+ #
1201
+ # This makes sense if you think about it: if you were to call <tt>post.tags.delete(Tag.find_by(name: 'food'))</tt>
1202
+ # you would want the 'food' tag to be unlinked from the post, rather than for the tag itself
1203
+ # to be removed from the database.
1204
+ #
1205
+ # However, there are examples where this strategy doesn't make sense. For example, suppose
1206
+ # a person has many projects, and each project has many tasks. If we deleted one of a person's
1207
+ # tasks, we would probably not want the project to be deleted. In this scenario, the delete method
1208
+ # won't actually work: it can only be used if the association on the join model is a
1209
+ # #belongs_to. In other situations you are expected to perform operations directly on
1210
+ # either the associated records or the <tt>:through</tt> association.
1211
+ #
1212
+ # With a regular #has_many there is no distinction between the "associated records"
1213
+ # and the "link", so there is only one choice for what gets deleted.
1214
+ #
1215
+ # With #has_and_belongs_to_many and #has_many <tt>:through</tt>, if you want to delete the
1216
+ # associated records themselves, you can always do something along the lines of
1217
+ # <tt>person.tasks.each(&:destroy)</tt>.
1218
+ #
1219
+ # == Type safety with ActiveRecord::AssociationTypeMismatch
1220
+ #
1221
+ # If you attempt to assign an object to an association that doesn't match the inferred
1222
+ # or specified <tt>:class_name</tt>, you'll get an ActiveRecord::AssociationTypeMismatch.
1223
+ #
1224
+ # == Options
1225
+ #
1226
+ # All of the association macros can be specialized through options. This makes cases
1227
+ # more complex than the simple and guessable ones possible.
1228
+ module ClassMethods
1229
+ # Specifies a one-to-many association. The following methods for retrieval and query of
1230
+ # collections of associated objects will be added:
1231
+ #
1232
+ # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1233
+ # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
1234
+ #
1235
+ # [collection]
1236
+ # Returns a Relation of all the associated objects.
1237
+ # An empty Relation is returned if none are found.
1238
+ # [collection<<(object, ...)]
1239
+ # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
1240
+ # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1241
+ # parent object, unless the parent object is a new record.
1242
+ # This will also run validations and callbacks of associated object(s).
1243
+ # [collection.delete(object, ...)]
1244
+ # Removes one or more objects from the collection by setting their foreign keys to +NULL+.
1245
+ # Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
1246
+ # and deleted if they're associated with <tt>dependent: :delete_all</tt>.
1247
+ #
1248
+ # If the <tt>:through</tt> option is used, then the join records are deleted (rather than
1249
+ # nullified) by default, but you can specify <tt>dependent: :destroy</tt> or
1250
+ # <tt>dependent: :nullify</tt> to override this.
1251
+ # [collection.destroy(object, ...)]
1252
+ # Removes one or more objects from the collection by running <tt>destroy</tt> on
1253
+ # each record, regardless of any dependent option, ensuring callbacks are run.
1254
+ #
1255
+ # If the <tt>:through</tt> option is used, then the join records are destroyed
1256
+ # instead, not the objects themselves.
1257
+ # [collection=objects]
1258
+ # Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
1259
+ # option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
1260
+ # direct by default. You can specify <tt>dependent: :destroy</tt> or
1261
+ # <tt>dependent: :nullify</tt> to override this.
1262
+ # [collection_singular_ids]
1263
+ # Returns an array of the associated objects' ids
1264
+ # [collection_singular_ids=ids]
1265
+ # Replace the collection with the objects identified by the primary keys in +ids+. This
1266
+ # method loads the models and calls <tt>collection=</tt>. See above.
1267
+ # [collection.clear]
1268
+ # Removes every object from the collection. This destroys the associated objects if they
1269
+ # are associated with <tt>dependent: :destroy</tt>, deletes them directly from the
1270
+ # database if <tt>dependent: :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
1271
+ # If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
1272
+ # Join models are directly deleted.
1273
+ # [collection.empty?]
1274
+ # Returns +true+ if there are no associated objects.
1275
+ # [collection.size]
1276
+ # Returns the number of associated objects.
1277
+ # [collection.find(...)]
1278
+ # Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
1279
+ # [collection.exists?(...)]
1280
+ # Checks whether an associated object with the given conditions exists.
1281
+ # Uses the same rules as ActiveRecord::FinderMethods#exists?.
1282
+ # [collection.build(attributes = {}, ...)]
1283
+ # Returns one or more new objects of the collection type that have been instantiated
1284
+ # with +attributes+ and linked to this object through a foreign key, but have not yet
1285
+ # been saved.
1286
+ # [collection.create(attributes = {})]
1287
+ # Returns a new object of the collection type that has been instantiated
1288
+ # with +attributes+, linked to this object through a foreign key, and that has already
1289
+ # been saved (if it passed the validation). *Note*: This only works if the base model
1290
+ # already exists in the DB, not if it is a new (unsaved) record!
1291
+ # [collection.create!(attributes = {})]
1292
+ # Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
1293
+ # if the record is invalid.
1294
+ # [collection.reload]
1295
+ # Returns a Relation of all of the associated objects, forcing a database read.
1296
+ # An empty Relation is returned if none are found.
1297
+ #
1298
+ # === Example
1299
+ #
1300
+ # A <tt>Firm</tt> class declares <tt>has_many :clients</tt>, which will add:
1301
+ # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>)
1302
+ # * <tt>Firm#clients<<</tt>
1303
+ # * <tt>Firm#clients.delete</tt>
1304
+ # * <tt>Firm#clients.destroy</tt>
1305
+ # * <tt>Firm#clients=</tt>
1306
+ # * <tt>Firm#client_ids</tt>
1307
+ # * <tt>Firm#client_ids=</tt>
1308
+ # * <tt>Firm#clients.clear</tt>
1309
+ # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
1310
+ # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
1311
+ # * <tt>Firm#clients.find</tt> (similar to <tt>Client.where(firm_id: id).find(id)</tt>)
1312
+ # * <tt>Firm#clients.exists?(name: 'ACME')</tt> (similar to <tt>Client.exists?(name: 'ACME', firm_id: firm.id)</tt>)
1313
+ # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new(firm_id: id)</tt>)
1314
+ # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new(firm_id: id); c.save; c</tt>)
1315
+ # * <tt>Firm#clients.create!</tt> (similar to <tt>c = Client.new(firm_id: id); c.save!</tt>)
1316
+ # * <tt>Firm#clients.reload</tt>
1317
+ # The declaration can also include an +options+ hash to specialize the behavior of the association.
1318
+ #
1319
+ # === Scopes
1320
+ #
1321
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
1322
+ # lambda) to retrieve a specific set of records or customize the generated
1323
+ # query when you access the associated collection.
1324
+ #
1325
+ # Scope examples:
1326
+ # has_many :comments, -> { where(author_id: 1) }
1327
+ # has_many :employees, -> { joins(:address) }
1328
+ # has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
1329
+ #
1330
+ # === Extensions
1331
+ #
1332
+ # The +extension+ argument allows you to pass a block into a has_many
1333
+ # association. This is useful for adding new finders, creators and other
1334
+ # factory-type methods to be used as part of the association.
1335
+ #
1336
+ # Extension examples:
1337
+ # has_many :employees do
1338
+ # def find_or_create_by_name(name)
1339
+ # first_name, last_name = name.split(" ", 2)
1340
+ # find_or_create_by(first_name: first_name, last_name: last_name)
1341
+ # end
1342
+ # end
1343
+ #
1344
+ # === Options
1345
+ # [:class_name]
1346
+ # Specify the class name of the association. Use it only if that name can't be inferred
1347
+ # from the association name. So <tt>has_many :products</tt> will by default be linked
1348
+ # to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
1349
+ # specify it with this option.
1350
+ # [:foreign_key]
1351
+ # Specify the foreign key used for the association. By default this is guessed to be the name
1352
+ # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
1353
+ # association will use "person_id" as the default <tt>:foreign_key</tt>.
1354
+ #
1355
+ # If you are going to modify the association (rather than just read from it), then it is
1356
+ # a good idea to set the <tt>:inverse_of</tt> option.
1357
+ # [:foreign_type]
1358
+ # Specify the column used to store the associated object's type, if this is a polymorphic
1359
+ # association. By default this is guessed to be the name of the polymorphic association
1360
+ # specified on "as" option with a "_type" suffix. So a class that defines a
1361
+ # <tt>has_many :tags, as: :taggable</tt> association will use "taggable_type" as the
1362
+ # default <tt>:foreign_type</tt>.
1363
+ # [:primary_key]
1364
+ # Specify the name of the column to use as the primary key for the association. By default this is +id+.
1365
+ # [:dependent]
1366
+ # Controls what happens to the associated objects when
1367
+ # their owner is destroyed. Note that these are implemented as
1368
+ # callbacks, and Rails executes callbacks in order. Therefore, other
1369
+ # similar callbacks may affect the <tt>:dependent</tt> behavior, and the
1370
+ # <tt>:dependent</tt> behavior may affect other callbacks.
1371
+ #
1372
+ # * <tt>nil</tt> do nothing (default).
1373
+ # * <tt>:destroy</tt> causes all the associated objects to also be destroyed.
1374
+ # * <tt>:destroy_async</tt> destroys all the associated objects in a background job. <b>WARNING:</b> Do not use
1375
+ # this option if the association is backed by foreign key constraints in your database. The foreign key
1376
+ # constraint actions will occur inside the same transaction that deletes its owner.
1377
+ # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
1378
+ # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
1379
+ # on polymorphic associations. Callbacks are not executed.
1380
+ # * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there are any associated records.
1381
+ # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
1382
+ #
1383
+ # If using with the <tt>:through</tt> option, the association on the join model must be
1384
+ # a #belongs_to, and the records which get deleted are the join records, rather than
1385
+ # the associated records.
1386
+ #
1387
+ # If using <tt>dependent: :destroy</tt> on a scoped association, only the scoped objects are destroyed.
1388
+ # For example, if a Post model defines
1389
+ # <tt>has_many :comments, -> { where published: true }, dependent: :destroy</tt> and <tt>destroy</tt> is
1390
+ # called on a post, only published comments are destroyed. This means that any unpublished comments in the
1391
+ # database would still contain a foreign key pointing to the now deleted post.
1392
+ # [:counter_cache]
1393
+ # This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
1394
+ # when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
1395
+ # [:as]
1396
+ # Specifies a polymorphic interface (See #belongs_to).
1397
+ # [:through]
1398
+ # Specifies an association through which to perform the query. This can be any other type
1399
+ # of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
1400
+ # <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
1401
+ # source reflection.
1402
+ #
1403
+ # If the association on the join model is a #belongs_to, the collection can be modified
1404
+ # and the records on the <tt>:through</tt> model will be automatically created and removed
1405
+ # as appropriate. Otherwise, the collection is read-only, so you should manipulate the
1406
+ # <tt>:through</tt> association directly.
1407
+ #
1408
+ # If you are going to modify the association (rather than just read from it), then it is
1409
+ # a good idea to set the <tt>:inverse_of</tt> option on the source association on the
1410
+ # join model. This allows associated records to be built which will automatically create
1411
+ # the appropriate join model records when they are saved. (See the 'Association Join Models'
1412
+ # section above.)
1413
+ # [:source]
1414
+ # Specifies the source association name used by #has_many <tt>:through</tt> queries.
1415
+ # Only use it if the name cannot be inferred from the association.
1416
+ # <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
1417
+ # <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
1418
+ # [:source_type]
1419
+ # Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
1420
+ # association is a polymorphic #belongs_to.
1421
+ # [:validate]
1422
+ # When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
1423
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1424
+ # [:autosave]
1425
+ # If true, always save the associated objects or destroy them if marked for destruction,
1426
+ # when saving the parent object. If false, never save or destroy the associated objects.
1427
+ # By default, only save associated objects that are new records. This option is implemented as a
1428
+ # +before_save+ callback. Because callbacks are run in the order they are defined, associated objects
1429
+ # may need to be explicitly saved in any user-defined +before_save+ callbacks.
1430
+ #
1431
+ # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
1432
+ # <tt>:autosave</tt> to <tt>true</tt>.
1433
+ # [:inverse_of]
1434
+ # Specifies the name of the #belongs_to association on the associated object
1435
+ # that is the inverse of this #has_many association.
1436
+ # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1437
+ # [:extend]
1438
+ # Specifies a module or array of modules that will be extended into the association object returned.
1439
+ # Useful for defining methods on associations, especially when they should be shared between multiple
1440
+ # association objects.
1441
+ # [:strict_loading]
1442
+ # Enforces strict loading every time the associated record is loaded through this association.
1443
+ # [:ensuring_owner_was]
1444
+ # Specifies an instance method to be called on the owner. The method must return true in order for the
1445
+ # associated records to be deleted in a background job.
1446
+ #
1447
+ # Option examples:
1448
+ # has_many :comments, -> { order("posted_on") }
1449
+ # has_many :comments, -> { includes(:author) }
1450
+ # has_many :people, -> { where(deleted: false).order("name") }, class_name: "Person"
1451
+ # has_many :tracks, -> { order("position") }, dependent: :destroy
1452
+ # has_many :comments, dependent: :nullify
1453
+ # has_many :tags, as: :taggable
1454
+ # has_many :reports, -> { readonly }
1455
+ # has_many :subscribers, through: :subscriptions, source: :user
1456
+ # has_many :comments, strict_loading: true
1457
+ def has_many(name, scope = nil, **options, &extension)
1458
+ reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1459
+ Reflection.add_reflection self, name, reflection
1682
1460
  end
1683
1461
 
1684
- habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(name, scope, options, self)
1462
+ # Specifies a one-to-one association with another class. This method should only be used
1463
+ # if the other class contains the foreign key. If the current class contains the foreign key,
1464
+ # then you should use #belongs_to instead. See also ActiveRecord::Associations::ClassMethods's overview
1465
+ # on when to use #has_one and when to use #belongs_to.
1466
+ #
1467
+ # The following methods for retrieval and query of a single associated object will be added:
1468
+ #
1469
+ # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1470
+ # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
1471
+ #
1472
+ # [association]
1473
+ # Returns the associated object. +nil+ is returned if none is found.
1474
+ # [association=(associate)]
1475
+ # Assigns the associate object, extracts the primary key, sets it as the foreign key,
1476
+ # and saves the associate object. To avoid database inconsistencies, permanently deletes an existing
1477
+ # associated object when assigning a new one, even if the new one isn't saved to database.
1478
+ # [build_association(attributes = {})]
1479
+ # Returns a new object of the associated type that has been instantiated
1480
+ # with +attributes+ and linked to this object through a foreign key, but has not
1481
+ # yet been saved.
1482
+ # [create_association(attributes = {})]
1483
+ # Returns a new object of the associated type that has been instantiated
1484
+ # with +attributes+, linked to this object through a foreign key, and that
1485
+ # has already been saved (if it passed the validation).
1486
+ # [create_association!(attributes = {})]
1487
+ # Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
1488
+ # if the record is invalid.
1489
+ # [reload_association]
1490
+ # Returns the associated object, forcing a database read.
1491
+ #
1492
+ # === Example
1493
+ #
1494
+ # An Account class declares <tt>has_one :beneficiary</tt>, which will add:
1495
+ # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.where(account_id: id).first</tt>)
1496
+ # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
1497
+ # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new(account_id: id)</tt>)
1498
+ # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new(account_id: id); b.save; b</tt>)
1499
+ # * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new(account_id: id); b.save!; b</tt>)
1500
+ # * <tt>Account#reload_beneficiary</tt>
1501
+ #
1502
+ # === Scopes
1503
+ #
1504
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
1505
+ # lambda) to retrieve a specific record or customize the generated query
1506
+ # when you access the associated object.
1507
+ #
1508
+ # Scope examples:
1509
+ # has_one :author, -> { where(comment_id: 1) }
1510
+ # has_one :employer, -> { joins(:company) }
1511
+ # has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
1512
+ #
1513
+ # === Options
1514
+ #
1515
+ # The declaration can also include an +options+ hash to specialize the behavior of the association.
1516
+ #
1517
+ # Options are:
1518
+ # [:class_name]
1519
+ # Specify the class name of the association. Use it only if that name can't be inferred
1520
+ # from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
1521
+ # if the real class name is Person, you'll have to specify it with this option.
1522
+ # [:dependent]
1523
+ # Controls what happens to the associated object when
1524
+ # its owner is destroyed:
1525
+ #
1526
+ # * <tt>nil</tt> do nothing (default).
1527
+ # * <tt>:destroy</tt> causes the associated object to also be destroyed
1528
+ # * <tt>:destroy_async</tt> causes the associated object to be destroyed in a background job. <b>WARNING:</b> Do not use
1529
+ # this option if the association is backed by foreign key constraints in your database. The foreign key
1530
+ # constraint actions will occur inside the same transaction that deletes its owner.
1531
+ # * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
1532
+ # * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
1533
+ # on polymorphic associations. Callbacks are not executed.
1534
+ # * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there is an associated record
1535
+ # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
1536
+ #
1537
+ # Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
1538
+ # [:foreign_key]
1539
+ # Specify the foreign key used for the association. By default this is guessed to be the name
1540
+ # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
1541
+ # will use "person_id" as the default <tt>:foreign_key</tt>.
1542
+ #
1543
+ # If you are going to modify the association (rather than just read from it), then it is
1544
+ # a good idea to set the <tt>:inverse_of</tt> option.
1545
+ # [:foreign_type]
1546
+ # Specify the column used to store the associated object's type, if this is a polymorphic
1547
+ # association. By default this is guessed to be the name of the polymorphic association
1548
+ # specified on "as" option with a "_type" suffix. So a class that defines a
1549
+ # <tt>has_one :tag, as: :taggable</tt> association will use "taggable_type" as the
1550
+ # default <tt>:foreign_type</tt>.
1551
+ # [:primary_key]
1552
+ # Specify the method that returns the primary key used for the association. By default this is +id+.
1553
+ # [:as]
1554
+ # Specifies a polymorphic interface (See #belongs_to).
1555
+ # [:through]
1556
+ # Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
1557
+ # <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
1558
+ # source reflection. You can only use a <tt>:through</tt> query through a #has_one
1559
+ # or #belongs_to association on the join model.
1560
+ #
1561
+ # If you are going to modify the association (rather than just read from it), then it is
1562
+ # a good idea to set the <tt>:inverse_of</tt> option.
1563
+ # [:source]
1564
+ # Specifies the source association name used by #has_one <tt>:through</tt> queries.
1565
+ # Only use it if the name cannot be inferred from the association.
1566
+ # <tt>has_one :favorite, through: :favorites</tt> will look for a
1567
+ # <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
1568
+ # [:source_type]
1569
+ # Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
1570
+ # association is a polymorphic #belongs_to.
1571
+ # [:validate]
1572
+ # When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
1573
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1574
+ # [:autosave]
1575
+ # If true, always save the associated object or destroy it if marked for destruction,
1576
+ # when saving the parent object. If false, never save or destroy the associated object.
1577
+ # By default, only save the associated object if it's a new record.
1578
+ #
1579
+ # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
1580
+ # <tt>:autosave</tt> to <tt>true</tt>.
1581
+ # [:inverse_of]
1582
+ # Specifies the name of the #belongs_to association on the associated object
1583
+ # that is the inverse of this #has_one association.
1584
+ # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1585
+ # [:required]
1586
+ # When set to +true+, the association will also have its presence validated.
1587
+ # This will validate the association itself, not the id. You can use
1588
+ # +:inverse_of+ to avoid an extra query during validation.
1589
+ # [:strict_loading]
1590
+ # Enforces strict loading every time the associated record is loaded through this association.
1591
+ # [:ensuring_owner_was]
1592
+ # Specifies an instance method to be called on the owner. The method must return true in order for the
1593
+ # associated records to be deleted in a background job.
1594
+ #
1595
+ # Option examples:
1596
+ # has_one :credit_card, dependent: :destroy # destroys the associated credit card
1597
+ # has_one :credit_card, dependent: :nullify # updates the associated records foreign
1598
+ # # key value to NULL rather than destroying it
1599
+ # has_one :last_comment, -> { order('posted_on') }, class_name: "Comment"
1600
+ # has_one :project_manager, -> { where(role: 'project_manager') }, class_name: "Person"
1601
+ # has_one :attachment, as: :attachable
1602
+ # has_one :boss, -> { readonly }
1603
+ # has_one :club, through: :membership
1604
+ # has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
1605
+ # has_one :credit_card, required: true
1606
+ # has_one :credit_card, strict_loading: true
1607
+ def has_one(name, scope = nil, **options)
1608
+ reflection = Builder::HasOne.build(self, name, scope, options)
1609
+ Reflection.add_reflection self, name, reflection
1610
+ end
1685
1611
 
1686
- builder = Builder::HasAndBelongsToMany.new name, self, options
1612
+ # Specifies a one-to-one association with another class. This method should only be used
1613
+ # if this class contains the foreign key. If the other class contains the foreign key,
1614
+ # then you should use #has_one instead. See also ActiveRecord::Associations::ClassMethods's overview
1615
+ # on when to use #has_one and when to use #belongs_to.
1616
+ #
1617
+ # Methods will be added for retrieval and query for a single associated object, for which
1618
+ # this object holds an id:
1619
+ #
1620
+ # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1621
+ # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
1622
+ #
1623
+ # [association]
1624
+ # Returns the associated object. +nil+ is returned if none is found.
1625
+ # [association=(associate)]
1626
+ # Assigns the associate object, extracts the primary key, and sets it as the foreign key.
1627
+ # No modification or deletion of existing records takes place.
1628
+ # [build_association(attributes = {})]
1629
+ # Returns a new object of the associated type that has been instantiated
1630
+ # with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
1631
+ # [create_association(attributes = {})]
1632
+ # Returns a new object of the associated type that has been instantiated
1633
+ # with +attributes+, linked to this object through a foreign key, and that
1634
+ # has already been saved (if it passed the validation).
1635
+ # [create_association!(attributes = {})]
1636
+ # Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
1637
+ # if the record is invalid.
1638
+ # [reload_association]
1639
+ # Returns the associated object, forcing a database read.
1640
+ #
1641
+ # === Example
1642
+ #
1643
+ # A Post class declares <tt>belongs_to :author</tt>, which will add:
1644
+ # * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
1645
+ # * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
1646
+ # * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
1647
+ # * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
1648
+ # * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
1649
+ # * <tt>Post#reload_author</tt>
1650
+ # The declaration can also include an +options+ hash to specialize the behavior of the association.
1651
+ #
1652
+ # === Scopes
1653
+ #
1654
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
1655
+ # lambda) to retrieve a specific record or customize the generated query
1656
+ # when you access the associated object.
1657
+ #
1658
+ # Scope examples:
1659
+ # belongs_to :firm, -> { where(id: 2) }
1660
+ # belongs_to :user, -> { joins(:friends) }
1661
+ # belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
1662
+ #
1663
+ # === Options
1664
+ #
1665
+ # [:class_name]
1666
+ # Specify the class name of the association. Use it only if that name can't be inferred
1667
+ # from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
1668
+ # if the real class name is Person, you'll have to specify it with this option.
1669
+ # [:foreign_key]
1670
+ # Specify the foreign key used for the association. By default this is guessed to be the name
1671
+ # of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
1672
+ # association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
1673
+ # <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
1674
+ # of "favorite_person_id".
1675
+ #
1676
+ # If you are going to modify the association (rather than just read from it), then it is
1677
+ # a good idea to set the <tt>:inverse_of</tt> option.
1678
+ # [:foreign_type]
1679
+ # Specify the column used to store the associated object's type, if this is a polymorphic
1680
+ # association. By default this is guessed to be the name of the association with a "_type"
1681
+ # suffix. So a class that defines a <tt>belongs_to :taggable, polymorphic: true</tt>
1682
+ # association will use "taggable_type" as the default <tt>:foreign_type</tt>.
1683
+ # [:primary_key]
1684
+ # Specify the method that returns the primary key of associated object used for the association.
1685
+ # By default this is +id+.
1686
+ # [:dependent]
1687
+ # If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
1688
+ # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to
1689
+ # <tt>:destroy_async</tt>, the associated object is scheduled to be destroyed in a background job.
1690
+ # This option should not be specified when #belongs_to is used in conjunction with
1691
+ # a #has_many relationship on another class because of the potential to leave
1692
+ # orphaned records behind.
1693
+ # [:counter_cache]
1694
+ # Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
1695
+ # and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
1696
+ # class is created and decremented when it's destroyed. This requires that a column
1697
+ # named <tt>#{table_name}_count</tt> (such as +comments_count+ for a belonging Comment class)
1698
+ # is used on the associate class (such as a Post class) - that is the migration for
1699
+ # <tt>#{table_name}_count</tt> is created on the associate class (such that <tt>Post.comments_count</tt> will
1700
+ # return the count cached, see note below). You can also specify a custom counter
1701
+ # cache column by providing a column name instead of a +true+/+false+ value to this
1702
+ # option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
1703
+ # Note: Specifying a counter cache will add it to that model's list of readonly attributes
1704
+ # using +attr_readonly+.
1705
+ # [:polymorphic]
1706
+ # Specify this association is a polymorphic association by passing +true+.
1707
+ # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
1708
+ # to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
1709
+ # [:validate]
1710
+ # When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
1711
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1712
+ # [:autosave]
1713
+ # If true, always save the associated object or destroy it if marked for destruction, when
1714
+ # saving the parent object.
1715
+ # If false, never save or destroy the associated object.
1716
+ # By default, only save the associated object if it's a new record.
1717
+ #
1718
+ # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
1719
+ # sets <tt>:autosave</tt> to <tt>true</tt>.
1720
+ # [:touch]
1721
+ # If true, the associated object will be touched (the updated_at/on attributes set to current time)
1722
+ # when this record is either saved or destroyed. If you specify a symbol, that attribute
1723
+ # will be updated with the current time in addition to the updated_at/on attribute.
1724
+ # Please note that with touching no validation is performed and only the +after_touch+,
1725
+ # +after_commit+ and +after_rollback+ callbacks are executed.
1726
+ # [:inverse_of]
1727
+ # Specifies the name of the #has_one or #has_many association on the associated
1728
+ # object that is the inverse of this #belongs_to association.
1729
+ # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1730
+ # [:optional]
1731
+ # When set to +true+, the association will not have its presence validated.
1732
+ # [:required]
1733
+ # When set to +true+, the association will also have its presence validated.
1734
+ # This will validate the association itself, not the id. You can use
1735
+ # +:inverse_of+ to avoid an extra query during validation.
1736
+ # NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
1737
+ # you don't want to have association presence validated, use <tt>optional: true</tt>.
1738
+ # [:default]
1739
+ # Provide a callable (i.e. proc or lambda) to specify that the association should
1740
+ # be initialized with a particular record before validation.
1741
+ # [:strict_loading]
1742
+ # Enforces strict loading every time the associated record is loaded through this association.
1743
+ # [:ensuring_owner_was]
1744
+ # Specifies an instance method to be called on the owner. The method must return true in order for the
1745
+ # associated records to be deleted in a background job.
1746
+ #
1747
+ # Option examples:
1748
+ # belongs_to :firm, foreign_key: "client_of"
1749
+ # belongs_to :person, primary_key: "name", foreign_key: "person_name"
1750
+ # belongs_to :author, class_name: "Person", foreign_key: "author_id"
1751
+ # belongs_to :valid_coupon, ->(o) { where "discounts > ?", o.payments_count },
1752
+ # class_name: "Coupon", foreign_key: "coupon_id"
1753
+ # belongs_to :attachable, polymorphic: true
1754
+ # belongs_to :project, -> { readonly }
1755
+ # belongs_to :post, counter_cache: true
1756
+ # belongs_to :comment, touch: true
1757
+ # belongs_to :company, touch: :employees_last_updated_at
1758
+ # belongs_to :user, optional: true
1759
+ # belongs_to :account, default: -> { company.account }
1760
+ # belongs_to :account, strict_loading: true
1761
+ def belongs_to(name, scope = nil, **options)
1762
+ reflection = Builder::BelongsTo.build(self, name, scope, options)
1763
+ Reflection.add_reflection self, name, reflection
1764
+ end
1687
1765
 
1688
- join_model = builder.through_model
1766
+ # Specifies a many-to-many relationship with another class. This associates two classes via an
1767
+ # intermediate join table. Unless the join table is explicitly specified as an option, it is
1768
+ # guessed using the lexical order of the class names. So a join between Developer and Project
1769
+ # will give the default join table name of "developers_projects" because "D" precedes "P" alphabetically.
1770
+ # Note that this precedence is calculated using the <tt><</tt> operator for String. This
1771
+ # means that if the strings are of different lengths, and the strings are equal when compared
1772
+ # up to the shortest length, then the longer string is considered of higher
1773
+ # lexical precedence than the shorter one. For example, one would expect the tables "paper_boxes" and "papers"
1774
+ # to generate a join table name of "papers_paper_boxes" because of the length of the name "paper_boxes",
1775
+ # but it in fact generates a join table name of "paper_boxes_papers". Be aware of this caveat, and use the
1776
+ # custom <tt>:join_table</tt> option if you need to.
1777
+ # If your tables share a common prefix, it will only appear once at the beginning. For example,
1778
+ # the tables "catalog_categories" and "catalog_products" generate a join table name of "catalog_categories_products".
1779
+ #
1780
+ # The join table should not have a primary key or a model associated with it. You must manually generate the
1781
+ # join table with a migration such as this:
1782
+ #
1783
+ # class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[6.0]
1784
+ # def change
1785
+ # create_join_table :developers, :projects
1786
+ # end
1787
+ # end
1788
+ #
1789
+ # It's also a good idea to add indexes to each of those columns to speed up the joins process.
1790
+ # However, in MySQL it is advised to add a compound index for both of the columns as MySQL only
1791
+ # uses one index per table during the lookup.
1792
+ #
1793
+ # Adds the following methods for retrieval and query:
1794
+ #
1795
+ # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1796
+ # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
1797
+ #
1798
+ # [collection]
1799
+ # Returns a Relation of all the associated objects.
1800
+ # An empty Relation is returned if none are found.
1801
+ # [collection<<(object, ...)]
1802
+ # Adds one or more objects to the collection by creating associations in the join table
1803
+ # (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
1804
+ # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1805
+ # parent object, unless the parent object is a new record.
1806
+ # [collection.delete(object, ...)]
1807
+ # Removes one or more objects from the collection by removing their associations from the join table.
1808
+ # This does not destroy the objects.
1809
+ # [collection.destroy(object, ...)]
1810
+ # Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option.
1811
+ # This does not destroy the objects.
1812
+ # [collection=objects]
1813
+ # Replaces the collection's content by deleting and adding objects as appropriate.
1814
+ # [collection_singular_ids]
1815
+ # Returns an array of the associated objects' ids.
1816
+ # [collection_singular_ids=ids]
1817
+ # Replace the collection by the objects identified by the primary keys in +ids+.
1818
+ # [collection.clear]
1819
+ # Removes every object from the collection. This does not destroy the objects.
1820
+ # [collection.empty?]
1821
+ # Returns +true+ if there are no associated objects.
1822
+ # [collection.size]
1823
+ # Returns the number of associated objects.
1824
+ # [collection.find(id)]
1825
+ # Finds an associated object responding to the +id+ and that
1826
+ # meets the condition that it has to be associated with this object.
1827
+ # Uses the same rules as ActiveRecord::FinderMethods#find.
1828
+ # [collection.exists?(...)]
1829
+ # Checks whether an associated object with the given conditions exists.
1830
+ # Uses the same rules as ActiveRecord::FinderMethods#exists?.
1831
+ # [collection.build(attributes = {})]
1832
+ # Returns a new object of the collection type that has been instantiated
1833
+ # with +attributes+ and linked to this object through the join table, but has not yet been saved.
1834
+ # [collection.create(attributes = {})]
1835
+ # Returns a new object of the collection type that has been instantiated
1836
+ # with +attributes+, linked to this object through the join table, and that has already been
1837
+ # saved (if it passed the validation).
1838
+ # [collection.reload]
1839
+ # Returns a Relation of all of the associated objects, forcing a database read.
1840
+ # An empty Relation is returned if none are found.
1841
+ #
1842
+ # === Example
1843
+ #
1844
+ # A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
1845
+ # * <tt>Developer#projects</tt>
1846
+ # * <tt>Developer#projects<<</tt>
1847
+ # * <tt>Developer#projects.delete</tt>
1848
+ # * <tt>Developer#projects.destroy</tt>
1849
+ # * <tt>Developer#projects=</tt>
1850
+ # * <tt>Developer#project_ids</tt>
1851
+ # * <tt>Developer#project_ids=</tt>
1852
+ # * <tt>Developer#projects.clear</tt>
1853
+ # * <tt>Developer#projects.empty?</tt>
1854
+ # * <tt>Developer#projects.size</tt>
1855
+ # * <tt>Developer#projects.find(id)</tt>
1856
+ # * <tt>Developer#projects.exists?(...)</tt>
1857
+ # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new(developer_id: id)</tt>)
1858
+ # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new(developer_id: id); c.save; c</tt>)
1859
+ # * <tt>Developer#projects.reload</tt>
1860
+ # The declaration may include an +options+ hash to specialize the behavior of the association.
1861
+ #
1862
+ # === Scopes
1863
+ #
1864
+ # You can pass a second argument +scope+ as a callable (i.e. proc or
1865
+ # lambda) to retrieve a specific set of records or customize the generated
1866
+ # query when you access the associated collection.
1867
+ #
1868
+ # Scope examples:
1869
+ # has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
1870
+ # has_and_belongs_to_many :categories, ->(post) {
1871
+ # where("default_category = ?", post.default_category)
1872
+ # }
1873
+ #
1874
+ # === Extensions
1875
+ #
1876
+ # The +extension+ argument allows you to pass a block into a
1877
+ # has_and_belongs_to_many association. This is useful for adding new
1878
+ # finders, creators and other factory-type methods to be used as part of
1879
+ # the association.
1880
+ #
1881
+ # Extension examples:
1882
+ # has_and_belongs_to_many :contractors do
1883
+ # def find_or_create_by_name(name)
1884
+ # first_name, last_name = name.split(" ", 2)
1885
+ # find_or_create_by(first_name: first_name, last_name: last_name)
1886
+ # end
1887
+ # end
1888
+ #
1889
+ # === Options
1890
+ #
1891
+ # [:class_name]
1892
+ # Specify the class name of the association. Use it only if that name can't be inferred
1893
+ # from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
1894
+ # Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
1895
+ # [:join_table]
1896
+ # Specify the name of the join table if the default based on lexical order isn't what you want.
1897
+ # <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
1898
+ # MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
1899
+ # [:foreign_key]
1900
+ # Specify the foreign key used for the association. By default this is guessed to be the name
1901
+ # of this class in lower-case and "_id" suffixed. So a Person class that makes
1902
+ # a #has_and_belongs_to_many association to Project will use "person_id" as the
1903
+ # default <tt>:foreign_key</tt>.
1904
+ #
1905
+ # If you are going to modify the association (rather than just read from it), then it is
1906
+ # a good idea to set the <tt>:inverse_of</tt> option.
1907
+ # [:association_foreign_key]
1908
+ # Specify the foreign key used for the association on the receiving side of the association.
1909
+ # By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
1910
+ # So if a Person class makes a #has_and_belongs_to_many association to Project,
1911
+ # the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
1912
+ # [:validate]
1913
+ # When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
1914
+ # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1915
+ # [:autosave]
1916
+ # If true, always save the associated objects or destroy them if marked for destruction, when
1917
+ # saving the parent object.
1918
+ # If false, never save or destroy the associated objects.
1919
+ # By default, only save associated objects that are new records.
1920
+ #
1921
+ # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
1922
+ # <tt>:autosave</tt> to <tt>true</tt>.
1923
+ # [:strict_loading]
1924
+ # Enforces strict loading every time an associated record is loaded through this association.
1925
+ #
1926
+ # Option examples:
1927
+ # has_and_belongs_to_many :projects
1928
+ # has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
1929
+ # has_and_belongs_to_many :nations, class_name: "Country"
1930
+ # has_and_belongs_to_many :categories, join_table: "prods_cats"
1931
+ # has_and_belongs_to_many :categories, -> { readonly }
1932
+ # has_and_belongs_to_many :categories, strict_loading: true
1933
+ def has_and_belongs_to_many(name, scope = nil, **options, &extension)
1934
+ habtm_reflection = ActiveRecord::Reflection::HasAndBelongsToManyReflection.new(name, scope, options, self)
1689
1935
 
1690
- # FIXME: we should move this to the internal constants. Also people
1691
- # should never directly access this constant so I'm not happy about
1692
- # setting it.
1693
- const_set join_model.name, join_model
1936
+ builder = Builder::HasAndBelongsToMany.new name, self, options
1694
1937
 
1695
- middle_reflection = builder.middle_reflection join_model
1938
+ join_model = builder.through_model
1696
1939
 
1697
- Builder::HasMany.define_callbacks self, middle_reflection
1698
- Reflection.add_reflection self, middle_reflection.name, middle_reflection
1699
- middle_reflection.parent_reflection = [name.to_s, habtm_reflection]
1940
+ const_set join_model.name, join_model
1941
+ private_constant join_model.name
1700
1942
 
1701
- include Module.new {
1702
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
1703
- def destroy_associations
1704
- association(:#{middle_reflection.name}).delete_all(:delete_all)
1705
- association(:#{name}).reset
1706
- super
1707
- end
1708
- RUBY
1709
- }
1943
+ middle_reflection = builder.middle_reflection join_model
1710
1944
 
1711
- hm_options = {}
1712
- hm_options[:through] = middle_reflection.name
1713
- hm_options[:source] = join_model.right_reflection.name
1945
+ Builder::HasMany.define_callbacks self, middle_reflection
1946
+ Reflection.add_reflection self, middle_reflection.name, middle_reflection
1947
+ middle_reflection.parent_reflection = habtm_reflection
1714
1948
 
1715
- [:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name].each do |k|
1716
- hm_options[k] = options[k] if options.key? k
1717
- end
1949
+ include Module.new {
1950
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
1951
+ def destroy_associations
1952
+ association(:#{middle_reflection.name}).delete_all(:delete_all)
1953
+ association(:#{name}).reset
1954
+ super
1955
+ end
1956
+ RUBY
1957
+ }
1718
1958
 
1719
- has_many name, scope, hm_options, &extension
1720
- self._reflections[name.to_s].parent_reflection = [name.to_s, habtm_reflection]
1959
+ hm_options = {}
1960
+ hm_options[:through] = middle_reflection.name
1961
+ hm_options[:source] = join_model.right_reflection.name
1962
+
1963
+ [:before_add, :after_add, :before_remove, :after_remove, :autosave, :validate, :join_table, :class_name, :extend, :strict_loading].each do |k|
1964
+ hm_options[k] = options[k] if options.key? k
1965
+ end
1966
+
1967
+ has_many name, scope, **hm_options, &extension
1968
+ _reflections[name.to_s].parent_reflection = habtm_reflection
1969
+ end
1721
1970
  end
1722
- end
1723
1971
  end
1724
1972
  end