omg-activerecord 8.0.0.alpha1

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