activerecord 6.1.7 → 7.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +2030 -1020
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +18 -18
  5. data/lib/active_record/aggregations.rb +17 -14
  6. data/lib/active_record/association_relation.rb +1 -11
  7. data/lib/active_record/associations/association.rb +51 -19
  8. data/lib/active_record/associations/association_scope.rb +17 -12
  9. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +11 -5
  12. data/lib/active_record/associations/builder/belongs_to.rb +40 -14
  13. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  14. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
  15. data/lib/active_record/associations/builder/has_many.rb +3 -2
  16. data/lib/active_record/associations/builder/has_one.rb +2 -1
  17. data/lib/active_record/associations/builder/singular_association.rb +6 -2
  18. data/lib/active_record/associations/collection_association.rb +39 -35
  19. data/lib/active_record/associations/collection_proxy.rb +30 -15
  20. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  21. data/lib/active_record/associations/foreign_association.rb +10 -3
  22. data/lib/active_record/associations/has_many_association.rb +28 -18
  23. data/lib/active_record/associations/has_many_through_association.rb +12 -7
  24. data/lib/active_record/associations/has_one_association.rb +20 -10
  25. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  26. data/lib/active_record/associations/join_dependency/join_association.rb +3 -2
  27. data/lib/active_record/associations/join_dependency.rb +28 -20
  28. data/lib/active_record/associations/preloader/association.rb +210 -52
  29. data/lib/active_record/associations/preloader/batch.rb +48 -0
  30. data/lib/active_record/associations/preloader/branch.rb +147 -0
  31. data/lib/active_record/associations/preloader/through_association.rb +50 -14
  32. data/lib/active_record/associations/preloader.rb +50 -121
  33. data/lib/active_record/associations/singular_association.rb +9 -3
  34. data/lib/active_record/associations/through_association.rb +25 -14
  35. data/lib/active_record/associations.rb +446 -306
  36. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  37. data/lib/active_record/attribute_assignment.rb +1 -3
  38. data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
  39. data/lib/active_record/attribute_methods/dirty.rb +73 -22
  40. data/lib/active_record/attribute_methods/primary_key.rb +78 -26
  41. data/lib/active_record/attribute_methods/query.rb +31 -19
  42. data/lib/active_record/attribute_methods/read.rb +27 -12
  43. data/lib/active_record/attribute_methods/serialization.rb +194 -37
  44. data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
  45. data/lib/active_record/attribute_methods/write.rb +12 -15
  46. data/lib/active_record/attribute_methods.rb +161 -40
  47. data/lib/active_record/attributes.rb +27 -38
  48. data/lib/active_record/autosave_association.rb +65 -31
  49. data/lib/active_record/base.rb +25 -2
  50. data/lib/active_record/callbacks.rb +18 -34
  51. data/lib/active_record/coders/column_serializer.rb +61 -0
  52. data/lib/active_record/coders/json.rb +1 -1
  53. data/lib/active_record/coders/yaml_column.rb +70 -46
  54. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
  55. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
  57. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +113 -597
  58. data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
  59. data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
  60. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -27
  61. data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
  62. data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +367 -141
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
  70. data/lib/active_record/connection_adapters/column.rb +13 -0
  71. data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
  72. data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +39 -14
  78. data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
  80. data/lib/active_record/connection_adapters/pool_config.rb +20 -11
  81. data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  85. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  89. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +12 -3
  91. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  94. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/quoting.rb +89 -56
  96. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
  97. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
  98. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
  99. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
  100. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +397 -75
  101. data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
  102. data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
  103. data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
  104. data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
  105. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +72 -53
  106. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
  107. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
  108. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
  109. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +296 -104
  110. data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
  111. data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
  112. data/lib/active_record/connection_adapters/trilogy_adapter.rb +258 -0
  113. data/lib/active_record/connection_adapters.rb +9 -6
  114. data/lib/active_record/connection_handling.rb +108 -137
  115. data/lib/active_record/core.rb +242 -233
  116. data/lib/active_record/counter_cache.rb +52 -27
  117. data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
  118. data/lib/active_record/database_configurations/database_config.rb +21 -12
  119. data/lib/active_record/database_configurations/hash_config.rb +88 -16
  120. data/lib/active_record/database_configurations/url_config.rb +18 -12
  121. data/lib/active_record/database_configurations.rb +95 -59
  122. data/lib/active_record/delegated_type.rb +66 -20
  123. data/lib/active_record/deprecator.rb +7 -0
  124. data/lib/active_record/destroy_association_async_job.rb +4 -2
  125. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  126. data/lib/active_record/dynamic_matchers.rb +1 -1
  127. data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
  128. data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
  129. data/lib/active_record/encryption/cipher.rb +53 -0
  130. data/lib/active_record/encryption/config.rb +68 -0
  131. data/lib/active_record/encryption/configurable.rb +60 -0
  132. data/lib/active_record/encryption/context.rb +42 -0
  133. data/lib/active_record/encryption/contexts.rb +76 -0
  134. data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
  135. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  136. data/lib/active_record/encryption/encryptable_record.rb +230 -0
  137. data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -0
  138. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  139. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  140. data/lib/active_record/encryption/encryptor.rb +155 -0
  141. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  142. data/lib/active_record/encryption/errors.rb +15 -0
  143. data/lib/active_record/encryption/extended_deterministic_queries.rb +157 -0
  144. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  145. data/lib/active_record/encryption/key.rb +28 -0
  146. data/lib/active_record/encryption/key_generator.rb +53 -0
  147. data/lib/active_record/encryption/key_provider.rb +46 -0
  148. data/lib/active_record/encryption/message.rb +33 -0
  149. data/lib/active_record/encryption/message_serializer.rb +92 -0
  150. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  151. data/lib/active_record/encryption/properties.rb +76 -0
  152. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  153. data/lib/active_record/encryption/scheme.rb +100 -0
  154. data/lib/active_record/encryption.rb +58 -0
  155. data/lib/active_record/enum.rb +154 -63
  156. data/lib/active_record/errors.rb +172 -15
  157. data/lib/active_record/explain.rb +23 -3
  158. data/lib/active_record/explain_registry.rb +11 -6
  159. data/lib/active_record/explain_subscriber.rb +1 -1
  160. data/lib/active_record/fixture_set/file.rb +15 -1
  161. data/lib/active_record/fixture_set/model_metadata.rb +14 -4
  162. data/lib/active_record/fixture_set/render_context.rb +2 -0
  163. data/lib/active_record/fixture_set/table_row.rb +70 -14
  164. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  165. data/lib/active_record/fixtures.rb +147 -86
  166. data/lib/active_record/future_result.rb +174 -0
  167. data/lib/active_record/gem_version.rb +3 -3
  168. data/lib/active_record/inheritance.rb +81 -29
  169. data/lib/active_record/insert_all.rb +135 -22
  170. data/lib/active_record/integration.rb +11 -10
  171. data/lib/active_record/internal_metadata.rb +119 -33
  172. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  173. data/lib/active_record/locking/optimistic.rb +37 -22
  174. data/lib/active_record/locking/pessimistic.rb +15 -6
  175. data/lib/active_record/log_subscriber.rb +52 -19
  176. data/lib/active_record/marshalling.rb +59 -0
  177. data/lib/active_record/message_pack.rb +124 -0
  178. data/lib/active_record/middleware/database_selector/resolver.rb +10 -10
  179. data/lib/active_record/middleware/database_selector.rb +23 -13
  180. data/lib/active_record/middleware/shard_selector.rb +62 -0
  181. data/lib/active_record/migration/command_recorder.rb +112 -14
  182. data/lib/active_record/migration/compatibility.rb +233 -46
  183. data/lib/active_record/migration/default_strategy.rb +23 -0
  184. data/lib/active_record/migration/execution_strategy.rb +19 -0
  185. data/lib/active_record/migration/join_table.rb +1 -1
  186. data/lib/active_record/migration/pending_migration_connection.rb +21 -0
  187. data/lib/active_record/migration.rb +361 -173
  188. data/lib/active_record/model_schema.rb +125 -101
  189. data/lib/active_record/nested_attributes.rb +50 -20
  190. data/lib/active_record/no_touching.rb +3 -3
  191. data/lib/active_record/normalization.rb +167 -0
  192. data/lib/active_record/persistence.rb +409 -88
  193. data/lib/active_record/promise.rb +84 -0
  194. data/lib/active_record/query_cache.rb +4 -22
  195. data/lib/active_record/query_logs.rb +174 -0
  196. data/lib/active_record/query_logs_formatter.rb +41 -0
  197. data/lib/active_record/querying.rb +29 -6
  198. data/lib/active_record/railtie.rb +220 -44
  199. data/lib/active_record/railties/controller_runtime.rb +15 -10
  200. data/lib/active_record/railties/databases.rake +188 -252
  201. data/lib/active_record/railties/job_runtime.rb +23 -0
  202. data/lib/active_record/readonly_attributes.rb +41 -3
  203. data/lib/active_record/reflection.rb +248 -81
  204. data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
  205. data/lib/active_record/relation/batches.rb +192 -63
  206. data/lib/active_record/relation/calculations.rb +246 -90
  207. data/lib/active_record/relation/delegation.rb +28 -14
  208. data/lib/active_record/relation/finder_methods.rb +108 -51
  209. data/lib/active_record/relation/merger.rb +22 -13
  210. data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
  211. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -7
  212. data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
  213. data/lib/active_record/relation/predicate_builder.rb +27 -20
  214. data/lib/active_record/relation/query_attribute.rb +30 -12
  215. data/lib/active_record/relation/query_methods.rb +670 -129
  216. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  217. data/lib/active_record/relation/spawn_methods.rb +20 -3
  218. data/lib/active_record/relation/where_clause.rb +10 -19
  219. data/lib/active_record/relation.rb +287 -120
  220. data/lib/active_record/result.rb +37 -11
  221. data/lib/active_record/runtime_registry.rb +32 -13
  222. data/lib/active_record/sanitization.rb +65 -20
  223. data/lib/active_record/schema.rb +36 -22
  224. data/lib/active_record/schema_dumper.rb +73 -24
  225. data/lib/active_record/schema_migration.rb +68 -33
  226. data/lib/active_record/scoping/default.rb +72 -15
  227. data/lib/active_record/scoping/named.rb +5 -13
  228. data/lib/active_record/scoping.rb +65 -34
  229. data/lib/active_record/secure_password.rb +60 -0
  230. data/lib/active_record/secure_token.rb +21 -3
  231. data/lib/active_record/serialization.rb +6 -1
  232. data/lib/active_record/signed_id.rb +10 -8
  233. data/lib/active_record/store.rb +10 -10
  234. data/lib/active_record/suppressor.rb +13 -15
  235. data/lib/active_record/table_metadata.rb +16 -3
  236. data/lib/active_record/tasks/database_tasks.rb +251 -140
  237. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
  238. data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
  239. data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
  240. data/lib/active_record/test_databases.rb +1 -1
  241. data/lib/active_record/test_fixtures.rb +117 -96
  242. data/lib/active_record/timestamp.rb +32 -19
  243. data/lib/active_record/token_for.rb +113 -0
  244. data/lib/active_record/touch_later.rb +11 -6
  245. data/lib/active_record/transactions.rb +48 -27
  246. data/lib/active_record/translation.rb +3 -3
  247. data/lib/active_record/type/adapter_specific_registry.rb +32 -14
  248. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  249. data/lib/active_record/type/internal/timezone.rb +7 -2
  250. data/lib/active_record/type/serialized.rb +9 -5
  251. data/lib/active_record/type/time.rb +4 -0
  252. data/lib/active_record/type/type_map.rb +17 -20
  253. data/lib/active_record/type.rb +1 -2
  254. data/lib/active_record/validations/absence.rb +1 -1
  255. data/lib/active_record/validations/associated.rb +4 -4
  256. data/lib/active_record/validations/numericality.rb +5 -4
  257. data/lib/active_record/validations/presence.rb +5 -28
  258. data/lib/active_record/validations/uniqueness.rb +51 -6
  259. data/lib/active_record/validations.rb +8 -4
  260. data/lib/active_record/version.rb +1 -1
  261. data/lib/active_record.rb +335 -32
  262. data/lib/arel/attributes/attribute.rb +0 -8
  263. data/lib/arel/crud.rb +28 -22
  264. data/lib/arel/delete_manager.rb +18 -4
  265. data/lib/arel/errors.rb +10 -0
  266. data/lib/arel/factory_methods.rb +4 -0
  267. data/lib/arel/filter_predications.rb +9 -0
  268. data/lib/arel/insert_manager.rb +2 -3
  269. data/lib/arel/nodes/and.rb +4 -0
  270. data/lib/arel/nodes/binary.rb +6 -1
  271. data/lib/arel/nodes/bound_sql_literal.rb +61 -0
  272. data/lib/arel/nodes/casted.rb +1 -1
  273. data/lib/arel/nodes/cte.rb +36 -0
  274. data/lib/arel/nodes/delete_statement.rb +12 -13
  275. data/lib/arel/nodes/filter.rb +10 -0
  276. data/lib/arel/nodes/fragments.rb +35 -0
  277. data/lib/arel/nodes/function.rb +1 -0
  278. data/lib/arel/nodes/homogeneous_in.rb +1 -9
  279. data/lib/arel/nodes/insert_statement.rb +2 -2
  280. data/lib/arel/nodes/leading_join.rb +8 -0
  281. data/lib/arel/nodes/node.rb +111 -2
  282. data/lib/arel/nodes/select_core.rb +2 -2
  283. data/lib/arel/nodes/select_statement.rb +2 -2
  284. data/lib/arel/nodes/sql_literal.rb +6 -0
  285. data/lib/arel/nodes/table_alias.rb +4 -0
  286. data/lib/arel/nodes/update_statement.rb +8 -3
  287. data/lib/arel/nodes.rb +5 -0
  288. data/lib/arel/predications.rb +13 -3
  289. data/lib/arel/select_manager.rb +10 -4
  290. data/lib/arel/table.rb +9 -6
  291. data/lib/arel/tree_manager.rb +5 -13
  292. data/lib/arel/update_manager.rb +18 -4
  293. data/lib/arel/visitors/dot.rb +80 -90
  294. data/lib/arel/visitors/mysql.rb +16 -3
  295. data/lib/arel/visitors/postgresql.rb +0 -10
  296. data/lib/arel/visitors/to_sql.rb +141 -20
  297. data/lib/arel/visitors/visitor.rb +2 -2
  298. data/lib/arel.rb +18 -3
  299. data/lib/rails/generators/active_record/application_record/USAGE +8 -0
  300. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  301. data/lib/rails/generators/active_record/migration.rb +3 -1
  302. data/lib/rails/generators/active_record/model/USAGE +113 -0
  303. data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
  304. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  305. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  306. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  307. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  308. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  309. metadata +96 -16
  310. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
  311. data/lib/active_record/null_relation.rb +0 -67
@@ -1,11 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/enumerable"
4
- require "active_support/core_ext/string/conversions"
5
-
6
3
  module ActiveRecord
7
- class AssociationNotFoundError < ConfigurationError #:nodoc:
4
+ class AssociationNotFoundError < ConfigurationError # :nodoc:
8
5
  attr_reader :record, :association_name
6
+
9
7
  def initialize(record = nil, association_name = nil)
10
8
  @record = record
11
9
  @association_name = association_name
@@ -16,32 +14,25 @@ module ActiveRecord
16
14
  end
17
15
  end
18
16
 
19
- class Correction
20
- def initialize(error)
21
- @error = error
22
- end
17
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
18
+ include DidYouMean::Correctable
23
19
 
24
20
  def corrections
25
- if @error.association_name
26
- maybe_these = @error.record.class.reflections.keys
27
-
28
- maybe_these.sort_by { |n|
29
- DidYouMean::Jaro.distance(@error.association_name.to_s, n)
30
- }.reverse.first(4)
21
+ if record && association_name
22
+ @corrections ||= begin
23
+ maybe_these = record.class.reflections.keys
24
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(association_name)
25
+ end
31
26
  else
32
27
  []
33
28
  end
34
29
  end
35
30
  end
36
-
37
- # We may not have DYM, and DYM might not let us register error handlers
38
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
39
- DidYouMean.correct_error(self, Correction)
40
- end
41
31
  end
42
32
 
43
- class InverseOfAssociationNotFoundError < ActiveRecordError #:nodoc:
33
+ class InverseOfAssociationNotFoundError < ActiveRecordError # :nodoc:
44
34
  attr_reader :reflection, :associated_class
35
+
45
36
  def initialize(reflection = nil, associated_class = nil)
46
37
  if reflection
47
38
  @reflection = reflection
@@ -52,31 +43,35 @@ module ActiveRecord
52
43
  end
53
44
  end
54
45
 
55
- class Correction
56
- def initialize(error)
57
- @error = error
58
- end
46
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
47
+ include DidYouMean::Correctable
59
48
 
60
49
  def corrections
61
- if @error.reflection && @error.associated_class
62
- maybe_these = @error.associated_class.reflections.keys
63
-
64
- maybe_these.sort_by { |n|
65
- DidYouMean::Jaro.distance(@error.reflection.options[:inverse_of].to_s, n)
66
- }.reverse.first(4)
50
+ if reflection && associated_class
51
+ @corrections ||= begin
52
+ maybe_these = associated_class.reflections.keys
53
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:inverse_of].to_s)
54
+ end
67
55
  else
68
56
  []
69
57
  end
70
58
  end
71
59
  end
60
+ end
72
61
 
73
- # We may not have DYM, and DYM might not let us register error handlers
74
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
75
- DidYouMean.correct_error(self, Correction)
62
+ class InverseOfAssociationRecursiveError < ActiveRecordError # :nodoc:
63
+ attr_reader :reflection
64
+ def initialize(reflection = nil)
65
+ if reflection
66
+ @reflection = reflection
67
+ super("Inverse association #{reflection.name} (#{reflection.options[:inverse_of].inspect} in #{reflection.class_name}) is recursive.")
68
+ else
69
+ super("Inverse association is recursive.")
70
+ end
76
71
  end
77
72
  end
78
73
 
79
- class HasManyThroughAssociationNotFoundError < ActiveRecordError #:nodoc:
74
+ class HasManyThroughAssociationNotFoundError < ActiveRecordError # :nodoc:
80
75
  attr_reader :owner_class, :reflection
81
76
 
82
77
  def initialize(owner_class = nil, reflection = nil)
@@ -89,32 +84,24 @@ module ActiveRecord
89
84
  end
90
85
  end
91
86
 
92
- class Correction
93
- def initialize(error)
94
- @error = error
95
- end
87
+ if defined?(DidYouMean::Correctable) && defined?(DidYouMean::SpellChecker)
88
+ include DidYouMean::Correctable
96
89
 
97
90
  def corrections
98
- if @error.reflection && @error.owner_class
99
- maybe_these = @error.owner_class.reflections.keys
100
- maybe_these -= [@error.reflection.name.to_s] # remove failing reflection
101
-
102
- maybe_these.sort_by { |n|
103
- DidYouMean::Jaro.distance(@error.reflection.options[:through].to_s, n)
104
- }.reverse.first(4)
91
+ if owner_class && reflection
92
+ @corrections ||= begin
93
+ maybe_these = owner_class.reflections.keys
94
+ maybe_these -= [reflection.name.to_s] # remove failing reflection
95
+ DidYouMean::SpellChecker.new(dictionary: maybe_these).correct(reflection.options[:through].to_s)
96
+ end
105
97
  else
106
98
  []
107
99
  end
108
100
  end
109
101
  end
110
-
111
- # We may not have DYM, and DYM might not let us register error handlers
112
- if defined?(DidYouMean) && DidYouMean.respond_to?(:correct_error)
113
- DidYouMean.correct_error(self, Correction)
114
- end
115
102
  end
116
103
 
117
- class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError #:nodoc:
104
+ class HasManyThroughAssociationPolymorphicSourceError < ActiveRecordError # :nodoc:
118
105
  def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
119
106
  if owner_class_name && reflection && source_reflection
120
107
  super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' on the polymorphic object '#{source_reflection.class_name}##{source_reflection.name}' without 'source_type'. Try adding 'source_type: \"#{reflection.name.to_s.classify}\"' to 'has_many :through' definition.")
@@ -124,7 +111,7 @@ module ActiveRecord
124
111
  end
125
112
  end
126
113
 
127
- class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
114
+ class HasManyThroughAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
128
115
  def initialize(owner_class_name = nil, reflection = nil)
129
116
  if owner_class_name && reflection
130
117
  super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
@@ -134,7 +121,7 @@ module ActiveRecord
134
121
  end
135
122
  end
136
123
 
137
- class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError #:nodoc:
124
+ class HasManyThroughAssociationPointlessSourceTypeError < ActiveRecordError # :nodoc:
138
125
  def initialize(owner_class_name = nil, reflection = nil, source_reflection = nil)
139
126
  if owner_class_name && reflection && source_reflection
140
127
  super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' with a :source_type option if the '#{reflection.through_reflection.class_name}##{source_reflection.name}' is not polymorphic. Try removing :source_type on your association.")
@@ -144,7 +131,7 @@ module ActiveRecord
144
131
  end
145
132
  end
146
133
 
147
- class HasOneThroughCantAssociateThroughCollection < ActiveRecordError #:nodoc:
134
+ class HasOneThroughCantAssociateThroughCollection < ActiveRecordError # :nodoc:
148
135
  def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
149
136
  if owner_class_name && reflection && through_reflection
150
137
  super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' where the :through association '#{owner_class_name}##{through_reflection.name}' is a collection. Specify a has_one or belongs_to association in the :through option instead.")
@@ -154,7 +141,7 @@ module ActiveRecord
154
141
  end
155
142
  end
156
143
 
157
- class HasOneAssociationPolymorphicThroughError < ActiveRecordError #:nodoc:
144
+ class HasOneAssociationPolymorphicThroughError < ActiveRecordError # :nodoc:
158
145
  def initialize(owner_class_name = nil, reflection = nil)
159
146
  if owner_class_name && reflection
160
147
  super("Cannot have a has_one :through association '#{owner_class_name}##{reflection.name}' which goes through the polymorphic association '#{owner_class_name}##{reflection.through_reflection.name}'.")
@@ -164,7 +151,7 @@ module ActiveRecord
164
151
  end
165
152
  end
166
153
 
167
- class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError #:nodoc:
154
+ class HasManyThroughSourceAssociationNotFoundError < ActiveRecordError # :nodoc:
168
155
  def initialize(reflection = nil)
169
156
  if reflection
170
157
  through_reflection = reflection.through_reflection
@@ -177,7 +164,7 @@ module ActiveRecord
177
164
  end
178
165
  end
179
166
 
180
- class HasManyThroughOrderError < ActiveRecordError #:nodoc:
167
+ class HasManyThroughOrderError < ActiveRecordError # :nodoc:
181
168
  def initialize(owner_class_name = nil, reflection = nil, through_reflection = nil)
182
169
  if owner_class_name && reflection && through_reflection
183
170
  super("Cannot have a has_many :through association '#{owner_class_name}##{reflection.name}' which goes through '#{owner_class_name}##{through_reflection.name}' before the through association is defined.")
@@ -187,7 +174,7 @@ module ActiveRecord
187
174
  end
188
175
  end
189
176
 
190
- class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError #:nodoc:
177
+ class ThroughCantAssociateThroughHasOneOrManyReflection < ActiveRecordError # :nodoc:
191
178
  def initialize(owner = nil, reflection = nil)
192
179
  if owner && reflection
193
180
  super("Cannot modify association '#{owner.class.name}##{reflection.name}' because the source reflection class '#{reflection.source_reflection.class_name}' is associated to '#{reflection.through_reflection.class_name}' via :#{reflection.source_reflection.macro}.")
@@ -197,6 +184,22 @@ module ActiveRecord
197
184
  end
198
185
  end
199
186
 
187
+ class CompositePrimaryKeyMismatchError < ActiveRecordError # :nodoc:
188
+ attr_reader :reflection
189
+
190
+ def initialize(reflection = nil)
191
+ if reflection
192
+ if reflection.has_one? || reflection.collection?
193
+ super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.active_record_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
194
+ else
195
+ super("Association #{reflection.active_record}##{reflection.name} primary key #{reflection.association_primary_key} doesn't match with foreign key #{reflection.foreign_key}. Please specify query_constraints, or primary_key and foreign_key values.")
196
+ end
197
+ else
198
+ super("Association primary key doesn't match with foreign key.")
199
+ end
200
+ end
201
+ end
202
+
200
203
  class AmbiguousSourceReflectionForThroughAssociation < ActiveRecordError # :nodoc:
201
204
  def initialize(klass, macro, association_name, options, possible_sources)
202
205
  example_options = options.dup
@@ -212,13 +215,13 @@ module ActiveRecord
212
215
  end
213
216
  end
214
217
 
215
- class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
218
+ class HasManyThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
216
219
  end
217
220
 
218
- class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
221
+ class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection # :nodoc:
219
222
  end
220
223
 
221
- class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
224
+ class ThroughNestedAssociationsAreReadonly < ActiveRecordError # :nodoc:
222
225
  def initialize(owner = nil, reflection = nil)
223
226
  if owner && reflection
224
227
  super("Cannot modify association '#{owner.class.name}##{reflection.name}' because it goes through more than one other association.")
@@ -228,10 +231,10 @@ module ActiveRecord
228
231
  end
229
232
  end
230
233
 
231
- class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
234
+ class HasManyThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
232
235
  end
233
236
 
234
- class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly #:nodoc:
237
+ class HasOneThroughNestedAssociationsAreReadonly < ThroughNestedAssociationsAreReadonly # :nodoc:
235
238
  end
236
239
 
237
240
  # This error is raised when trying to eager load a polymorphic association using a JOIN.
@@ -250,7 +253,7 @@ module ActiveRecord
250
253
  # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
251
254
  # (has_many, has_one) when there is at least 1 child associated instance.
252
255
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
253
- class DeleteRestrictionError < ActiveRecordError #:nodoc:
256
+ class DeleteRestrictionError < ActiveRecordError # :nodoc:
254
257
  def initialize(name = nil)
255
258
  if name
256
259
  super("Cannot delete record because of dependent #{name}")
@@ -274,7 +277,7 @@ module ActiveRecord
274
277
  autoload :CollectionProxy
275
278
  autoload :ThroughAssociation
276
279
 
277
- module Builder #:nodoc:
280
+ module Builder # :nodoc:
278
281
  autoload :Association, "active_record/associations/builder/association"
279
282
  autoload :SingularAssociation, "active_record/associations/builder/singular_association"
280
283
  autoload :CollectionAssociation, "active_record/associations/builder/collection_association"
@@ -296,16 +299,18 @@ module ActiveRecord
296
299
  autoload :Preloader
297
300
  autoload :JoinDependency
298
301
  autoload :AssociationScope
302
+ autoload :DisableJoinsAssociationScope
299
303
  autoload :AliasTracker
300
304
  end
301
305
 
302
306
  def self.eager_load!
303
307
  super
304
308
  Preloader.eager_load!
309
+ JoinDependency.eager_load!
305
310
  end
306
311
 
307
312
  # Returns the association instance for the given name, instantiating it if it doesn't already exist
308
- def association(name) #:nodoc:
313
+ def association(name) # :nodoc:
309
314
  association = association_instance_get(name)
310
315
 
311
316
  if association.nil?
@@ -328,20 +333,10 @@ module ActiveRecord
328
333
  super
329
334
  end
330
335
 
331
- def reload(*) # :nodoc:
332
- clear_association_cache
333
- super
334
- end
335
-
336
336
  private
337
- # Clears out the association cache.
338
- def clear_association_cache
339
- @association_cache.clear if persisted?
340
- end
341
-
342
337
  def init_internals
343
- @association_cache = {}
344
338
  super
339
+ @association_cache = {}
345
340
  end
346
341
 
347
342
  # Returns the specified association instance if it exists, +nil+ otherwise.
@@ -354,6 +349,8 @@ module ActiveRecord
354
349
  @association_cache[name] = association
355
350
  end
356
351
 
352
+ # = Active Record \Associations
353
+ #
357
354
  # \Associations are a set of macro-like class methods for tying objects together through
358
355
  # foreign keys. They express relationships like "Project has one Project Manager"
359
356
  # or "Project belongs to a Portfolio". Each macro adds a number of methods to the
@@ -370,23 +367,42 @@ module ActiveRecord
370
367
  #
371
368
  # The project class now has the following methods (and more) to ease the traversal and
372
369
  # manipulation of its relationships:
373
- # * <tt>Project#portfolio</tt>, <tt>Project#portfolio=(portfolio)</tt>, <tt>Project#reload_portfolio</tt>
374
- # * <tt>Project#project_manager</tt>, <tt>Project#project_manager=(project_manager)</tt>, <tt>Project#reload_project_manager</tt>
375
- # * <tt>Project#milestones.empty?</tt>, <tt>Project#milestones.size</tt>, <tt>Project#milestones</tt>, <tt>Project#milestones<<(milestone)</tt>,
376
- # <tt>Project#milestones.delete(milestone)</tt>, <tt>Project#milestones.destroy(milestone)</tt>, <tt>Project#milestones.find(milestone_id)</tt>,
377
- # <tt>Project#milestones.build</tt>, <tt>Project#milestones.create</tt>
378
- # * <tt>Project#categories.empty?</tt>, <tt>Project#categories.size</tt>, <tt>Project#categories</tt>, <tt>Project#categories<<(category1)</tt>,
379
- # <tt>Project#categories.delete(category1)</tt>, <tt>Project#categories.destroy(category1)</tt>
370
+ #
371
+ # project = Project.first
372
+ # project.portfolio
373
+ # project.portfolio = Portfolio.first
374
+ # project.reload_portfolio
375
+ #
376
+ # project.project_manager
377
+ # project.project_manager = ProjectManager.first
378
+ # project.reload_project_manager
379
+ #
380
+ # project.milestones.empty?
381
+ # project.milestones.size
382
+ # project.milestones
383
+ # project.milestones << Milestone.first
384
+ # project.milestones.delete(Milestone.first)
385
+ # project.milestones.destroy(Milestone.first)
386
+ # project.milestones.find(Milestone.first.id)
387
+ # project.milestones.build
388
+ # project.milestones.create
389
+ #
390
+ # project.categories.empty?
391
+ # project.categories.size
392
+ # project.categories
393
+ # project.categories << Category.first
394
+ # project.categories.delete(category1)
395
+ # project.categories.destroy(category1)
380
396
  #
381
397
  # === A word of warning
382
398
  #
383
399
  # Don't create associations that have the same name as {instance methods}[rdoc-ref:ActiveRecord::Core] of
384
- # <tt>ActiveRecord::Base</tt>. Since the association adds a method with that name to
385
- # its model, using an association with the same name as one provided by <tt>ActiveRecord::Base</tt> will override the method inherited through <tt>ActiveRecord::Base</tt> and will break things.
386
- # For instance, +attributes+ and +connection+ would be bad choices for association names, because those names already exist in the list of <tt>ActiveRecord::Base</tt> instance methods.
400
+ # +ActiveRecord::Base+. Since the association adds a method with that name to
401
+ # 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.
402
+ # 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.
387
403
  #
388
404
  # == Auto-generated methods
389
- # See also Instance Public methods below for more details.
405
+ # See also "Instance Public methods" below ( from #belongs_to ) for more details.
390
406
  #
391
407
  # === Singular associations (one-to-one)
392
408
  # | | belongs_to |
@@ -398,6 +414,8 @@ module ActiveRecord
398
414
  # create_other(attributes={}) | X | | X
399
415
  # create_other!(attributes={}) | X | | X
400
416
  # reload_other | X | X | X
417
+ # other_changed? | X | X |
418
+ # other_previously_changed? | X | X |
401
419
  #
402
420
  # === Collection associations (one-to-many / many-to-many)
403
421
  # | | | has_many
@@ -451,7 +469,7 @@ module ActiveRecord
451
469
  #
452
470
  # == Cardinality and associations
453
471
  #
454
- # Active Record associations can be used to describe one-to-one, one-to-many and many-to-many
472
+ # Active Record associations can be used to describe one-to-one, one-to-many, and many-to-many
455
473
  # relationships between models. Each model uses an association to describe its role in
456
474
  # the relation. The #belongs_to association is always used in the model that has
457
475
  # the foreign key.
@@ -605,8 +623,11 @@ module ActiveRecord
605
623
  # has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
606
624
  # end
607
625
  #
608
- # Note: Joining, eager loading and preloading of these associations is not possible.
609
- # These operations happen before instance creation and the scope will be called with a +nil+ argument.
626
+ # Note: Joining or eager loading such associations is not possible because
627
+ # those operations happen before instance creation. Such associations
628
+ # _can_ be preloaded, but doing so will perform N+1 queries because there
629
+ # will be a different scope for each record (similar to preloading
630
+ # polymorphic scopes).
610
631
  #
611
632
  # == Association callbacks
612
633
  #
@@ -614,22 +635,31 @@ module ActiveRecord
614
635
  # you can also define callbacks that get triggered when you add an object to or remove an
615
636
  # object from an association collection.
616
637
  #
617
- # class Project
618
- # has_and_belongs_to_many :developers, after_add: :evaluate_velocity
638
+ # class Firm < ActiveRecord::Base
639
+ # has_many :clients,
640
+ # dependent: :destroy,
641
+ # after_add: :congratulate_client,
642
+ # after_remove: :log_after_remove
643
+ #
644
+ # def congratulate_client(record)
645
+ # # ...
646
+ # end
619
647
  #
620
- # def evaluate_velocity(developer)
621
- # ...
648
+ # def log_after_remove(record)
649
+ # # ...
622
650
  # end
623
651
  # end
624
652
  #
625
653
  # It's possible to stack callbacks by passing them as an array. Example:
626
654
  #
627
- # class Project
628
- # has_and_belongs_to_many :developers,
629
- # after_add: [:evaluate_velocity, Proc.new { |p, d| p.shipping_date = Time.now}]
655
+ # class Firm < ActiveRecord::Base
656
+ # has_many :clients,
657
+ # dependent: :destroy,
658
+ # after_add: [:congratulate_client, -> (firm, record) { firm.log << "after_adding#{record.id}" }],
659
+ # after_remove: :log_after_remove
630
660
  # end
631
661
  #
632
- # Possible callbacks are: +before_add+, +after_add+, +before_remove+ and +after_remove+.
662
+ # Possible callbacks are: +before_add+, +after_add+, +before_remove+, and +after_remove+.
633
663
  #
634
664
  # If any of the +before_add+ callbacks throw an exception, the object will not be
635
665
  # added to the collection.
@@ -637,6 +667,18 @@ module ActiveRecord
637
667
  # Similarly, if any of the +before_remove+ callbacks throw an exception, the object
638
668
  # will not be removed from the collection.
639
669
  #
670
+ # Note: To trigger remove callbacks, you must use +destroy+ / +destroy_all+ methods. For example:
671
+ #
672
+ # * <tt>firm.clients.destroy(client)</tt>
673
+ # * <tt>firm.clients.destroy(*clients)</tt>
674
+ # * <tt>firm.clients.destroy_all</tt>
675
+ #
676
+ # +delete+ / +delete_all+ methods like the following do *not* trigger remove callbacks:
677
+ #
678
+ # * <tt>firm.clients.delete(client)</tt>
679
+ # * <tt>firm.clients.delete(*clients)</tt>
680
+ # * <tt>firm.clients.delete_all</tt>
681
+ #
640
682
  # == Association extensions
641
683
  #
642
684
  # The proxy objects that control the access to associations can be extended through anonymous
@@ -780,9 +822,10 @@ module ActiveRecord
780
822
  # inverse detection only works on #has_many, #has_one, and
781
823
  # #belongs_to associations.
782
824
  #
783
- # <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations,
784
- # or a custom scope, will also prevent the association's inverse
785
- # from being found automatically.
825
+ # <tt>:foreign_key</tt> and <tt>:through</tt> options on the associations
826
+ # will also prevent the association's inverse from being found automatically,
827
+ # as will a custom scopes in some cases. See further details in the
828
+ # {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
786
829
  #
787
830
  # The automatic guessing of the inverse association uses a heuristic based
788
831
  # on the name of the class, so it may not work for all associations,
@@ -1007,7 +1050,7 @@ module ActiveRecord
1007
1050
  # query per addressable type.
1008
1051
  # For example, if all the addressables are either of class Person or Company, then a total
1009
1052
  # of 3 queries will be executed. The list of addressable types to load is determined on
1010
- # the back of the addresses loaded. This is not supported if Active Record has to fallback
1053
+ # the back of the addresses loaded. This is not supported if Active Record has to fall back
1011
1054
  # to the previous implementation of eager loading and will raise ActiveRecord::EagerLoadPolymorphicError.
1012
1055
  # The reason is that the parent model's type is a column value so its corresponding table
1013
1056
  # name cannot be put in the +FROM+/+JOIN+ clauses of that query.
@@ -1020,45 +1063,45 @@ module ActiveRecord
1020
1063
  # Indexes are appended for any more successive uses of the table name.
1021
1064
  #
1022
1065
  # Post.joins(:comments)
1023
- # # => SELECT ... FROM posts INNER JOIN comments ON ...
1066
+ # # SELECT ... FROM posts INNER JOIN comments ON ...
1024
1067
  # Post.joins(:special_comments) # STI
1025
- # # => SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
1068
+ # # SELECT ... FROM posts INNER JOIN comments ON ... AND comments.type = 'SpecialComment'
1026
1069
  # Post.joins(:comments, :special_comments) # special_comments is the reflection name, posts is the parent table name
1027
- # # => SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
1070
+ # # SELECT ... FROM posts INNER JOIN comments ON ... INNER JOIN comments special_comments_posts
1028
1071
  #
1029
1072
  # Acts as tree example:
1030
1073
  #
1031
1074
  # TreeMixin.joins(:children)
1032
- # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1075
+ # # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1033
1076
  # TreeMixin.joins(children: :parent)
1034
- # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1035
- # INNER JOIN parents_mixins ...
1077
+ # # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1078
+ # # INNER JOIN parents_mixins ...
1036
1079
  # TreeMixin.joins(children: {parent: :children})
1037
- # # => SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1038
- # INNER JOIN parents_mixins ...
1039
- # INNER JOIN mixins childrens_mixins_2
1080
+ # # SELECT ... FROM mixins INNER JOIN mixins childrens_mixins ...
1081
+ # # INNER JOIN parents_mixins ...
1082
+ # # INNER JOIN mixins childrens_mixins_2
1040
1083
  #
1041
1084
  # Has and Belongs to Many join tables use the same idea, but add a <tt>_join</tt> suffix:
1042
1085
  #
1043
1086
  # Post.joins(:categories)
1044
- # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1087
+ # # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1045
1088
  # Post.joins(categories: :posts)
1046
- # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1047
- # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
1089
+ # # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1090
+ # # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
1048
1091
  # Post.joins(categories: {posts: :categories})
1049
- # # => SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1050
- # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
1051
- # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
1092
+ # # SELECT ... FROM posts INNER JOIN categories_posts ... INNER JOIN categories ...
1093
+ # # INNER JOIN categories_posts posts_categories_join INNER JOIN posts posts_categories
1094
+ # # INNER JOIN categories_posts categories_posts_join INNER JOIN categories categories_posts_2
1052
1095
  #
1053
1096
  # If you wish to specify your own custom joins using ActiveRecord::QueryMethods#joins method, those table
1054
1097
  # names will take precedence over the eager associations:
1055
1098
  #
1056
1099
  # Post.joins(:comments).joins("inner join comments ...")
1057
- # # => SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
1100
+ # # SELECT ... FROM posts INNER JOIN comments_posts ON ... INNER JOIN comments ...
1058
1101
  # Post.joins(:comments, :special_comments).joins("inner join comments ...")
1059
- # # => SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
1060
- # INNER JOIN comments special_comments_posts ...
1061
- # INNER JOIN comments ...
1102
+ # # SELECT ... FROM posts INNER JOIN comments comments_posts ON ...
1103
+ # # INNER JOIN comments special_comments_posts ...
1104
+ # # INNER JOIN comments ...
1062
1105
  #
1063
1106
  # Table aliases are automatically truncated according to the maximum length of table identifiers
1064
1107
  # according to the specific database.
@@ -1139,7 +1182,8 @@ module ActiveRecord
1139
1182
  # belongs_to :dungeon, inverse_of: :evil_wizard
1140
1183
  # end
1141
1184
  #
1142
- # For more information, see the documentation for the +:inverse_of+ option.
1185
+ # For more information, see the documentation for the +:inverse_of+ option and the
1186
+ # {Active Record Associations guide}[https://guides.rubyonrails.org/association_basics.html#bi-directional-associations].
1143
1187
  #
1144
1188
  # == Deleting from associations
1145
1189
  #
@@ -1161,7 +1205,7 @@ module ActiveRecord
1161
1205
  # specific association types. When no option is given, the behavior is to do nothing
1162
1206
  # with the associated records when destroying a record.
1163
1207
  #
1164
- # Note that <tt>:dependent</tt> is implemented using Rails' callback
1208
+ # Note that <tt>:dependent</tt> is implemented using \Rails' callback
1165
1209
  # system, which works by processing callbacks in order. Therefore, other
1166
1210
  # callbacks declared either before or after the <tt>:dependent</tt> option
1167
1211
  # can affect what it does.
@@ -1232,15 +1276,15 @@ module ActiveRecord
1232
1276
  # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1233
1277
  # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
1234
1278
  #
1235
- # [collection]
1279
+ # [<tt>collection</tt>]
1236
1280
  # Returns a Relation of all the associated objects.
1237
1281
  # An empty Relation is returned if none are found.
1238
- # [collection<<(object, ...)]
1282
+ # [<tt>collection<<(object, ...)</tt>]
1239
1283
  # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
1240
1284
  # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1241
1285
  # parent object, unless the parent object is a new record.
1242
1286
  # This will also run validations and callbacks of associated object(s).
1243
- # [collection.delete(object, ...)]
1287
+ # [<tt>collection.delete(object, ...)</tt>]
1244
1288
  # Removes one or more objects from the collection by setting their foreign keys to +NULL+.
1245
1289
  # Objects will be in addition destroyed if they're associated with <tt>dependent: :destroy</tt>,
1246
1290
  # and deleted if they're associated with <tt>dependent: :delete_all</tt>.
@@ -1248,75 +1292,84 @@ module ActiveRecord
1248
1292
  # If the <tt>:through</tt> option is used, then the join records are deleted (rather than
1249
1293
  # nullified) by default, but you can specify <tt>dependent: :destroy</tt> or
1250
1294
  # <tt>dependent: :nullify</tt> to override this.
1251
- # [collection.destroy(object, ...)]
1295
+ # [<tt>collection.destroy(object, ...)</tt>]
1252
1296
  # Removes one or more objects from the collection by running <tt>destroy</tt> on
1253
1297
  # each record, regardless of any dependent option, ensuring callbacks are run.
1254
1298
  #
1255
1299
  # If the <tt>:through</tt> option is used, then the join records are destroyed
1256
1300
  # instead, not the objects themselves.
1257
- # [collection=objects]
1301
+ # [<tt>collection=objects</tt>]
1258
1302
  # Replaces the collections content by deleting and adding objects as appropriate. If the <tt>:through</tt>
1259
1303
  # option is true callbacks in the join models are triggered except destroy callbacks, since deletion is
1260
1304
  # direct by default. You can specify <tt>dependent: :destroy</tt> or
1261
1305
  # <tt>dependent: :nullify</tt> to override this.
1262
- # [collection_singular_ids]
1306
+ # [<tt>collection_singular_ids</tt>]
1263
1307
  # Returns an array of the associated objects' ids
1264
- # [collection_singular_ids=ids]
1308
+ # [<tt>collection_singular_ids=ids</tt>]
1265
1309
  # Replace the collection with the objects identified by the primary keys in +ids+. This
1266
1310
  # method loads the models and calls <tt>collection=</tt>. See above.
1267
- # [collection.clear]
1311
+ # [<tt>collection.clear</tt>]
1268
1312
  # Removes every object from the collection. This destroys the associated objects if they
1269
1313
  # are associated with <tt>dependent: :destroy</tt>, deletes them directly from the
1270
1314
  # database if <tt>dependent: :delete_all</tt>, otherwise sets their foreign keys to +NULL+.
1271
1315
  # If the <tt>:through</tt> option is true no destroy callbacks are invoked on the join models.
1272
1316
  # Join models are directly deleted.
1273
- # [collection.empty?]
1317
+ # [<tt>collection.empty?</tt>]
1274
1318
  # Returns +true+ if there are no associated objects.
1275
- # [collection.size]
1319
+ # [<tt>collection.size</tt>]
1276
1320
  # Returns the number of associated objects.
1277
- # [collection.find(...)]
1321
+ # [<tt>collection.find(...)</tt>]
1278
1322
  # Finds an associated object according to the same rules as ActiveRecord::FinderMethods#find.
1279
- # [collection.exists?(...)]
1323
+ # [<tt>collection.exists?(...)</tt>]
1280
1324
  # Checks whether an associated object with the given conditions exists.
1281
1325
  # Uses the same rules as ActiveRecord::FinderMethods#exists?.
1282
- # [collection.build(attributes = {}, ...)]
1326
+ # [<tt>collection.build(attributes = {}, ...)</tt>]
1283
1327
  # Returns one or more new objects of the collection type that have been instantiated
1284
1328
  # with +attributes+ and linked to this object through a foreign key, but have not yet
1285
1329
  # been saved.
1286
- # [collection.create(attributes = {})]
1330
+ # [<tt>collection.create(attributes = {})</tt>]
1287
1331
  # Returns a new object of the collection type that has been instantiated
1288
1332
  # with +attributes+, linked to this object through a foreign key, and that has already
1289
1333
  # been saved (if it passed the validation). *Note*: This only works if the base model
1290
1334
  # already exists in the DB, not if it is a new (unsaved) record!
1291
- # [collection.create!(attributes = {})]
1335
+ # [<tt>collection.create!(attributes = {})</tt>]
1292
1336
  # Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
1293
1337
  # if the record is invalid.
1294
- # [collection.reload]
1338
+ # [<tt>collection.reload</tt>]
1295
1339
  # Returns a Relation of all of the associated objects, forcing a database read.
1296
1340
  # An empty Relation is returned if none are found.
1297
1341
  #
1298
- # === Example
1299
- #
1300
- # A <tt>Firm</tt> class declares <tt>has_many :clients</tt>, which will add:
1301
- # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>)
1302
- # * <tt>Firm#clients<<</tt>
1303
- # * <tt>Firm#clients.delete</tt>
1304
- # * <tt>Firm#clients.destroy</tt>
1305
- # * <tt>Firm#clients=</tt>
1306
- # * <tt>Firm#client_ids</tt>
1307
- # * <tt>Firm#client_ids=</tt>
1308
- # * <tt>Firm#clients.clear</tt>
1309
- # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>)
1310
- # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>)
1311
- # * <tt>Firm#clients.find</tt> (similar to <tt>Client.where(firm_id: id).find(id)</tt>)
1312
- # * <tt>Firm#clients.exists?(name: 'ACME')</tt> (similar to <tt>Client.exists?(name: 'ACME', firm_id: firm.id)</tt>)
1313
- # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new(firm_id: id)</tt>)
1314
- # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new(firm_id: id); c.save; c</tt>)
1315
- # * <tt>Firm#clients.create!</tt> (similar to <tt>c = Client.new(firm_id: id); c.save!</tt>)
1316
- # * <tt>Firm#clients.reload</tt>
1342
+ # ==== Example
1343
+ #
1344
+ # class Firm < ActiveRecord::Base
1345
+ # has_many :clients
1346
+ # end
1347
+ #
1348
+ # Declaring <tt>has_many :clients</tt> adds the following methods (and more):
1349
+ #
1350
+ # firm = Firm.find(2)
1351
+ # client = Client.find(6)
1352
+ #
1353
+ # firm.clients # similar to Client.where(firm_id: 2)
1354
+ # firm.clients << client
1355
+ # firm.clients.delete(client)
1356
+ # firm.clients.destroy(client)
1357
+ # firm.clients = [client]
1358
+ # firm.client_ids
1359
+ # firm.client_ids = [6]
1360
+ # firm.clients.clear
1361
+ # firm.clients.empty? # similar to firm.clients.size == 0
1362
+ # firm.clients.size # similar to Client.count "firm_id = 2"
1363
+ # firm.clients.find # similar to Client.where(firm_id: 2).find(6)
1364
+ # firm.clients.exists?(name: 'ACME') # similar to Client.exists?(name: 'ACME', firm_id: 2)
1365
+ # firm.clients.build # similar to Client.new(firm_id: 2)
1366
+ # firm.clients.create # similar to Client.create(firm_id: 2)
1367
+ # firm.clients.create! # similar to Client.create!(firm_id: 2)
1368
+ # firm.clients.reload
1369
+ #
1317
1370
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1318
1371
  #
1319
- # === Scopes
1372
+ # ==== Scopes
1320
1373
  #
1321
1374
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1322
1375
  # lambda) to retrieve a specific set of records or customize the generated
@@ -1327,10 +1380,10 @@ module ActiveRecord
1327
1380
  # has_many :employees, -> { joins(:address) }
1328
1381
  # has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
1329
1382
  #
1330
- # === Extensions
1383
+ # ==== Extensions
1331
1384
  #
1332
1385
  # The +extension+ argument allows you to pass a block into a has_many
1333
- # association. This is useful for adding new finders, creators and other
1386
+ # association. This is useful for adding new finders, creators, and other
1334
1387
  # factory-type methods to be used as part of the association.
1335
1388
  #
1336
1389
  # Extension examples:
@@ -1341,31 +1394,31 @@ module ActiveRecord
1341
1394
  # end
1342
1395
  # end
1343
1396
  #
1344
- # === Options
1345
- # [:class_name]
1397
+ # ==== Options
1398
+ # [+:class_name+]
1346
1399
  # Specify the class name of the association. Use it only if that name can't be inferred
1347
1400
  # from the association name. So <tt>has_many :products</tt> will by default be linked
1348
1401
  # to the +Product+ class, but if the real class name is +SpecialProduct+, you'll have to
1349
1402
  # specify it with this option.
1350
- # [:foreign_key]
1403
+ # [+:foreign_key+]
1351
1404
  # Specify the foreign key used for the association. By default this is guessed to be the name
1352
1405
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
1353
1406
  # association will use "person_id" as the default <tt>:foreign_key</tt>.
1354
1407
  #
1355
- # If you are going to modify the association (rather than just read from it), then it is
1356
- # a good idea to set the <tt>:inverse_of</tt> option.
1357
- # [:foreign_type]
1408
+ # Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
1409
+ # inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
1410
+ # [+:foreign_type+]
1358
1411
  # Specify the column used to store the associated object's type, if this is a polymorphic
1359
1412
  # association. By default this is guessed to be the name of the polymorphic association
1360
1413
  # specified on "as" option with a "_type" suffix. So a class that defines a
1361
1414
  # <tt>has_many :tags, as: :taggable</tt> association will use "taggable_type" as the
1362
1415
  # default <tt>:foreign_type</tt>.
1363
- # [:primary_key]
1416
+ # [+:primary_key+]
1364
1417
  # Specify the name of the column to use as the primary key for the association. By default this is +id+.
1365
- # [:dependent]
1418
+ # [+:dependent+]
1366
1419
  # Controls what happens to the associated objects when
1367
1420
  # their owner is destroyed. Note that these are implemented as
1368
- # callbacks, and Rails executes callbacks in order. Therefore, other
1421
+ # callbacks, and \Rails executes callbacks in order. Therefore, other
1369
1422
  # similar callbacks may affect the <tt>:dependent</tt> behavior, and the
1370
1423
  # <tt>:dependent</tt> behavior may affect other callbacks.
1371
1424
  #
@@ -1377,7 +1430,7 @@ module ActiveRecord
1377
1430
  # * <tt>:delete_all</tt> causes all the associated objects to be deleted directly from the database (so callbacks will not be executed).
1378
1431
  # * <tt>:nullify</tt> causes the foreign keys to be set to +NULL+. Polymorphic type will also be nullified
1379
1432
  # on polymorphic associations. Callbacks are not executed.
1380
- # * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there are any associated records.
1433
+ # * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there are any associated records.
1381
1434
  # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there are any associated objects.
1382
1435
  #
1383
1436
  # If using with the <tt>:through</tt> option, the association on the join model must be
@@ -1389,12 +1442,12 @@ module ActiveRecord
1389
1442
  # <tt>has_many :comments, -> { where published: true }, dependent: :destroy</tt> and <tt>destroy</tt> is
1390
1443
  # called on a post, only published comments are destroyed. This means that any unpublished comments in the
1391
1444
  # database would still contain a foreign key pointing to the now deleted post.
1392
- # [:counter_cache]
1445
+ # [+:counter_cache+]
1393
1446
  # This option can be used to configure a custom named <tt>:counter_cache.</tt> You only need this option,
1394
1447
  # when you customized the name of your <tt>:counter_cache</tt> on the #belongs_to association.
1395
- # [:as]
1448
+ # [+:as+]
1396
1449
  # Specifies a polymorphic interface (See #belongs_to).
1397
- # [:through]
1450
+ # [+:through+]
1398
1451
  # Specifies an association through which to perform the query. This can be any other type
1399
1452
  # of association, including other <tt>:through</tt> associations. Options for <tt>:class_name</tt>,
1400
1453
  # <tt>:primary_key</tt> and <tt>:foreign_key</tt> are ignored, as the association uses the
@@ -1409,19 +1462,24 @@ module ActiveRecord
1409
1462
  # a good idea to set the <tt>:inverse_of</tt> option on the source association on the
1410
1463
  # join model. This allows associated records to be built which will automatically create
1411
1464
  # the appropriate join model records when they are saved. (See the 'Association Join Models'
1412
- # section above.)
1413
- # [:source]
1465
+ # and 'Setting Inverses' sections above.)
1466
+ # [+:disable_joins+]
1467
+ # Specifies whether joins should be skipped for an association. If set to true, two or more queries
1468
+ # will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
1469
+ # due to database limitations. This option is only applicable on <tt>has_many :through</tt> associations as
1470
+ # +has_many+ alone do not perform a join.
1471
+ # [+:source+]
1414
1472
  # Specifies the source association name used by #has_many <tt>:through</tt> queries.
1415
1473
  # Only use it if the name cannot be inferred from the association.
1416
1474
  # <tt>has_many :subscribers, through: :subscriptions</tt> will look for either <tt>:subscribers</tt> or
1417
1475
  # <tt>:subscriber</tt> on Subscription, unless a <tt>:source</tt> is given.
1418
- # [:source_type]
1476
+ # [+:source_type+]
1419
1477
  # Specifies type of the source association used by #has_many <tt>:through</tt> queries where the source
1420
1478
  # association is a polymorphic #belongs_to.
1421
- # [:validate]
1479
+ # [+:validate+]
1422
1480
  # When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
1423
1481
  # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1424
- # [:autosave]
1482
+ # [+:autosave+]
1425
1483
  # If true, always save the associated objects or destroy them if marked for destruction,
1426
1484
  # when saving the parent object. If false, never save or destroy the associated objects.
1427
1485
  # By default, only save associated objects that are new records. This option is implemented as a
@@ -1430,19 +1488,29 @@ module ActiveRecord
1430
1488
  #
1431
1489
  # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
1432
1490
  # <tt>:autosave</tt> to <tt>true</tt>.
1433
- # [:inverse_of]
1491
+ # [+:inverse_of+]
1434
1492
  # Specifies the name of the #belongs_to association on the associated object
1435
1493
  # that is the inverse of this #has_many association.
1436
1494
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1437
- # [:extend]
1495
+ # [+:extend+]
1438
1496
  # Specifies a module or array of modules that will be extended into the association object returned.
1439
1497
  # Useful for defining methods on associations, especially when they should be shared between multiple
1440
1498
  # association objects.
1441
- # [:strict_loading]
1442
- # Enforces strict loading every time the associated record is loaded through this association.
1443
- # [:ensuring_owner_was]
1499
+ # [+:strict_loading+]
1500
+ # When set to +true+, enforces strict loading every time the associated record is loaded through this
1501
+ # association.
1502
+ # [+:ensuring_owner_was+]
1444
1503
  # Specifies an instance method to be called on the owner. The method must return true in order for the
1445
1504
  # associated records to be deleted in a background job.
1505
+ # [+:query_constraints+]
1506
+ # Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
1507
+ # This is an optional option. By default Rails will attempt to derive the value automatically.
1508
+ # When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
1509
+ # [+:index_errors+]
1510
+ # Enables differentiation of multiple validation errors from the association records, by including
1511
+ # an index in the error attribute name, e.g. +roles[2].level+.
1512
+ # The index is based on association order, i.e. database order, with yet to be
1513
+ # persisted new records placed at the end.
1446
1514
  #
1447
1515
  # Option examples:
1448
1516
  # has_many :comments, -> { order("posted_on") }
@@ -1453,7 +1521,10 @@ module ActiveRecord
1453
1521
  # has_many :tags, as: :taggable
1454
1522
  # has_many :reports, -> { readonly }
1455
1523
  # has_many :subscribers, through: :subscriptions, source: :user
1524
+ # has_many :subscribers, through: :subscriptions, disable_joins: true
1456
1525
  # has_many :comments, strict_loading: true
1526
+ # has_many :comments, query_constraints: [:blog_id, :post_id]
1527
+ # has_many :comments, index_errors: true
1457
1528
  def has_many(name, scope = nil, **options, &extension)
1458
1529
  reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1459
1530
  Reflection.add_reflection self, name, reflection
@@ -1469,37 +1540,48 @@ module ActiveRecord
1469
1540
  # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1470
1541
  # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
1471
1542
  #
1472
- # [association]
1543
+ # [<tt>association</tt>]
1473
1544
  # Returns the associated object. +nil+ is returned if none is found.
1474
- # [association=(associate)]
1545
+ # [<tt>association=(associate)</tt>]
1475
1546
  # Assigns the associate object, extracts the primary key, sets it as the foreign key,
1476
1547
  # and saves the associate object. To avoid database inconsistencies, permanently deletes an existing
1477
1548
  # associated object when assigning a new one, even if the new one isn't saved to database.
1478
- # [build_association(attributes = {})]
1549
+ # [<tt>build_association(attributes = {})</tt>]
1479
1550
  # Returns a new object of the associated type that has been instantiated
1480
1551
  # with +attributes+ and linked to this object through a foreign key, but has not
1481
1552
  # yet been saved.
1482
- # [create_association(attributes = {})]
1553
+ # [<tt>create_association(attributes = {})</tt>]
1483
1554
  # Returns a new object of the associated type that has been instantiated
1484
1555
  # with +attributes+, linked to this object through a foreign key, and that
1485
1556
  # has already been saved (if it passed the validation).
1486
- # [create_association!(attributes = {})]
1557
+ # [<tt>create_association!(attributes = {})</tt>]
1487
1558
  # Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
1488
1559
  # if the record is invalid.
1489
- # [reload_association]
1560
+ # [<tt>reload_association</tt>]
1490
1561
  # Returns the associated object, forcing a database read.
1562
+ # [<tt>reset_association</tt>]
1563
+ # Unloads the associated object. The next access will query it from the database.
1564
+ #
1565
+ # ==== Example
1566
+ #
1567
+ # class Account < ActiveRecord::Base
1568
+ # has_one :beneficiary
1569
+ # end
1570
+ #
1571
+ # Declaring <tt>has_one :beneficiary</tt> adds the following methods (and more):
1491
1572
  #
1492
- # === Example
1573
+ # account = Account.find(5)
1574
+ # beneficiary = Beneficiary.find(8)
1493
1575
  #
1494
- # An Account class declares <tt>has_one :beneficiary</tt>, which will add:
1495
- # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.where(account_id: id).first</tt>)
1496
- # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>)
1497
- # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new(account_id: id)</tt>)
1498
- # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new(account_id: id); b.save; b</tt>)
1499
- # * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new(account_id: id); b.save!; b</tt>)
1500
- # * <tt>Account#reload_beneficiary</tt>
1576
+ # account.beneficiary # similar to Beneficiary.find_by(account_id: 5)
1577
+ # account.beneficiary = beneficiary # similar to beneficiary.update(account_id: 5)
1578
+ # account.build_beneficiary # similar to Beneficiary.new(account_id: 5)
1579
+ # account.create_beneficiary # similar to Beneficiary.create(account_id: 5)
1580
+ # account.create_beneficiary! # similar to Beneficiary.create!(account_id: 5)
1581
+ # account.reload_beneficiary
1582
+ # account.reset_beneficiary
1501
1583
  #
1502
- # === Scopes
1584
+ # ==== Scopes
1503
1585
  #
1504
1586
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1505
1587
  # lambda) to retrieve a specific record or customize the generated query
@@ -1510,16 +1592,16 @@ module ActiveRecord
1510
1592
  # has_one :employer, -> { joins(:company) }
1511
1593
  # has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
1512
1594
  #
1513
- # === Options
1595
+ # ==== Options
1514
1596
  #
1515
1597
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1516
1598
  #
1517
1599
  # Options are:
1518
- # [:class_name]
1600
+ # [+:class_name+]
1519
1601
  # Specify the class name of the association. Use it only if that name can't be inferred
1520
1602
  # from the association name. So <tt>has_one :manager</tt> will by default be linked to the Manager class, but
1521
1603
  # if the real class name is Person, you'll have to specify it with this option.
1522
- # [:dependent]
1604
+ # [+:dependent+]
1523
1605
  # Controls what happens to the associated object when
1524
1606
  # its owner is destroyed:
1525
1607
  #
@@ -1531,66 +1613,89 @@ module ActiveRecord
1531
1613
  # * <tt>:delete</tt> causes the associated object to be deleted directly from the database (so callbacks will not execute)
1532
1614
  # * <tt>:nullify</tt> causes the foreign key to be set to +NULL+. Polymorphic type column is also nullified
1533
1615
  # on polymorphic associations. Callbacks are not executed.
1534
- # * <tt>:restrict_with_exception</tt> causes an <tt>ActiveRecord::DeleteRestrictionError</tt> exception to be raised if there is an associated record
1616
+ # * <tt>:restrict_with_exception</tt> causes an ActiveRecord::DeleteRestrictionError exception to be raised if there is an associated record
1535
1617
  # * <tt>:restrict_with_error</tt> causes an error to be added to the owner if there is an associated object
1536
1618
  #
1537
1619
  # Note that <tt>:dependent</tt> option is ignored when using <tt>:through</tt> option.
1538
- # [:foreign_key]
1620
+ # [+:foreign_key+]
1539
1621
  # Specify the foreign key used for the association. By default this is guessed to be the name
1540
1622
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
1541
1623
  # will use "person_id" as the default <tt>:foreign_key</tt>.
1542
1624
  #
1543
- # If you are going to modify the association (rather than just read from it), then it is
1544
- # a good idea to set the <tt>:inverse_of</tt> option.
1545
- # [:foreign_type]
1625
+ # Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
1626
+ # inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
1627
+ # [+:foreign_type+]
1546
1628
  # Specify the column used to store the associated object's type, if this is a polymorphic
1547
1629
  # association. By default this is guessed to be the name of the polymorphic association
1548
1630
  # specified on "as" option with a "_type" suffix. So a class that defines a
1549
1631
  # <tt>has_one :tag, as: :taggable</tt> association will use "taggable_type" as the
1550
1632
  # default <tt>:foreign_type</tt>.
1551
- # [:primary_key]
1633
+ # [+:primary_key+]
1552
1634
  # Specify the method that returns the primary key used for the association. By default this is +id+.
1553
- # [:as]
1635
+ # [+:as+]
1554
1636
  # Specifies a polymorphic interface (See #belongs_to).
1555
- # [:through]
1637
+ # [+:through+]
1556
1638
  # Specifies a Join Model through which to perform the query. Options for <tt>:class_name</tt>,
1557
1639
  # <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
1558
1640
  # source reflection. You can only use a <tt>:through</tt> query through a #has_one
1559
1641
  # or #belongs_to association on the join model.
1560
1642
  #
1643
+ # If the association on the join model is a #belongs_to, the collection can be modified
1644
+ # and the records on the <tt>:through</tt> model will be automatically created and removed
1645
+ # as appropriate. Otherwise, the collection is read-only, so you should manipulate the
1646
+ # <tt>:through</tt> association directly.
1647
+ #
1561
1648
  # If you are going to modify the association (rather than just read from it), then it is
1562
- # a good idea to set the <tt>:inverse_of</tt> option.
1563
- # [:source]
1649
+ # a good idea to set the <tt>:inverse_of</tt> option on the source association on the
1650
+ # join model. This allows associated records to be built which will automatically create
1651
+ # the appropriate join model records when they are saved. (See the 'Association Join Models'
1652
+ # and 'Setting Inverses' sections above.)
1653
+ # [+:disable_joins+]
1654
+ # Specifies whether joins should be skipped for an association. If set to true, two or more queries
1655
+ # will be generated. Note that in some cases, if order or limit is applied, it will be done in-memory
1656
+ # due to database limitations. This option is only applicable on <tt>has_one :through</tt> associations as
1657
+ # +has_one+ alone does not perform a join.
1658
+ # [+:source+]
1564
1659
  # Specifies the source association name used by #has_one <tt>:through</tt> queries.
1565
1660
  # Only use it if the name cannot be inferred from the association.
1566
1661
  # <tt>has_one :favorite, through: :favorites</tt> will look for a
1567
1662
  # <tt>:favorite</tt> on Favorite, unless a <tt>:source</tt> is given.
1568
- # [:source_type]
1663
+ # [+:source_type+]
1569
1664
  # Specifies type of the source association used by #has_one <tt>:through</tt> queries where the source
1570
1665
  # association is a polymorphic #belongs_to.
1571
- # [:validate]
1666
+ # [+:validate+]
1572
1667
  # When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
1573
1668
  # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1574
- # [:autosave]
1669
+ # [+:autosave+]
1575
1670
  # If true, always save the associated object or destroy it if marked for destruction,
1576
1671
  # when saving the parent object. If false, never save or destroy the associated object.
1577
1672
  # By default, only save the associated object if it's a new record.
1578
1673
  #
1579
1674
  # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
1580
1675
  # <tt>:autosave</tt> to <tt>true</tt>.
1581
- # [:inverse_of]
1676
+ # [+:touch+]
1677
+ # If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
1678
+ # when this record is either saved or destroyed. If you specify a symbol, that attribute
1679
+ # will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
1680
+ # Please note that no validation will be performed when touching, and only the +after_touch+,
1681
+ # +after_commit+, and +after_rollback+ callbacks will be executed.
1682
+ # [+:inverse_of+]
1582
1683
  # Specifies the name of the #belongs_to association on the associated object
1583
1684
  # that is the inverse of this #has_one association.
1584
1685
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1585
- # [:required]
1686
+ # [+:required+]
1586
1687
  # When set to +true+, the association will also have its presence validated.
1587
1688
  # This will validate the association itself, not the id. You can use
1588
1689
  # +:inverse_of+ to avoid an extra query during validation.
1589
- # [:strict_loading]
1690
+ # [+:strict_loading+]
1590
1691
  # Enforces strict loading every time the associated record is loaded through this association.
1591
- # [:ensuring_owner_was]
1692
+ # [+:ensuring_owner_was+]
1592
1693
  # Specifies an instance method to be called on the owner. The method must return true in order for the
1593
1694
  # associated records to be deleted in a background job.
1695
+ # [+:query_constraints+]
1696
+ # Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
1697
+ # This is an optional option. By default Rails will attempt to derive the value automatically.
1698
+ # When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
1594
1699
  #
1595
1700
  # Option examples:
1596
1701
  # has_one :credit_card, dependent: :destroy # destroys the associated credit card
@@ -1601,9 +1706,11 @@ module ActiveRecord
1601
1706
  # has_one :attachment, as: :attachable
1602
1707
  # has_one :boss, -> { readonly }
1603
1708
  # has_one :club, through: :membership
1709
+ # has_one :club, through: :membership, disable_joins: true
1604
1710
  # has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
1605
1711
  # has_one :credit_card, required: true
1606
1712
  # has_one :credit_card, strict_loading: true
1713
+ # has_one :employment_record_book, query_constraints: [:organization_id, :employee_id]
1607
1714
  def has_one(name, scope = nil, **options)
1608
1715
  reflection = Builder::HasOne.build(self, name, scope, options)
1609
1716
  Reflection.add_reflection self, name, reflection
@@ -1620,36 +1727,52 @@ module ActiveRecord
1620
1727
  # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1621
1728
  # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
1622
1729
  #
1623
- # [association]
1730
+ # [<tt>association</tt>]
1624
1731
  # Returns the associated object. +nil+ is returned if none is found.
1625
- # [association=(associate)]
1732
+ # [<tt>association=(associate)</tt>]
1626
1733
  # Assigns the associate object, extracts the primary key, and sets it as the foreign key.
1627
1734
  # No modification or deletion of existing records takes place.
1628
- # [build_association(attributes = {})]
1735
+ # [<tt>build_association(attributes = {})</tt>]
1629
1736
  # Returns a new object of the associated type that has been instantiated
1630
1737
  # with +attributes+ and linked to this object through a foreign key, but has not yet been saved.
1631
- # [create_association(attributes = {})]
1738
+ # [<tt>create_association(attributes = {})</tt>]
1632
1739
  # Returns a new object of the associated type that has been instantiated
1633
1740
  # with +attributes+, linked to this object through a foreign key, and that
1634
1741
  # has already been saved (if it passed the validation).
1635
- # [create_association!(attributes = {})]
1742
+ # [<tt>create_association!(attributes = {})</tt>]
1636
1743
  # Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
1637
1744
  # if the record is invalid.
1638
- # [reload_association]
1745
+ # [<tt>reload_association</tt>]
1639
1746
  # Returns the associated object, forcing a database read.
1747
+ # [<tt>reset_association</tt>]
1748
+ # Unloads the associated object. The next access will query it from the database.
1749
+ # [<tt>association_changed?</tt>]
1750
+ # Returns true if a new associate object has been assigned and the next save will update the foreign key.
1751
+ # [<tt>association_previously_changed?</tt>]
1752
+ # Returns true if the previous save updated the association to reference a new associate object.
1640
1753
  #
1641
- # === Example
1754
+ # ==== Example
1642
1755
  #
1643
- # A Post class declares <tt>belongs_to :author</tt>, which will add:
1644
- # * <tt>Post#author</tt> (similar to <tt>Author.find(author_id)</tt>)
1645
- # * <tt>Post#author=(author)</tt> (similar to <tt>post.author_id = author.id</tt>)
1646
- # * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
1647
- # * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
1648
- # * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
1649
- # * <tt>Post#reload_author</tt>
1650
- # The declaration can also include an +options+ hash to specialize the behavior of the association.
1756
+ # class Post < ActiveRecord::Base
1757
+ # belongs_to :author
1758
+ # end
1759
+ #
1760
+ # Declaring <tt>belongs_to :author</tt> adds the following methods (and more):
1651
1761
  #
1652
- # === Scopes
1762
+ # post = Post.find(7)
1763
+ # author = Author.find(19)
1764
+ #
1765
+ # post.author # similar to Author.find(post.author_id)
1766
+ # post.author = author # similar to post.author_id = author.id
1767
+ # post.build_author # similar to post.author = Author.new
1768
+ # post.create_author # similar to post.author = Author.new; post.author.save; post.author
1769
+ # post.create_author! # similar to post.author = Author.new; post.author.save!; post.author
1770
+ # post.reload_author
1771
+ # post.reset_author
1772
+ # post.author_changed?
1773
+ # post.author_previously_changed?
1774
+ #
1775
+ # ==== Scopes
1653
1776
  #
1654
1777
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1655
1778
  # lambda) to retrieve a specific record or customize the generated query
@@ -1660,37 +1783,39 @@ module ActiveRecord
1660
1783
  # belongs_to :user, -> { joins(:friends) }
1661
1784
  # belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
1662
1785
  #
1663
- # === Options
1786
+ # ==== Options
1664
1787
  #
1665
- # [:class_name]
1788
+ # The declaration can also include an +options+ hash to specialize the behavior of the association.
1789
+ #
1790
+ # [+:class_name+]
1666
1791
  # Specify the class name of the association. Use it only if that name can't be inferred
1667
1792
  # from the association name. So <tt>belongs_to :author</tt> will by default be linked to the Author class, but
1668
1793
  # if the real class name is Person, you'll have to specify it with this option.
1669
- # [:foreign_key]
1794
+ # [+:foreign_key+]
1670
1795
  # Specify the foreign key used for the association. By default this is guessed to be the name
1671
1796
  # of the association with an "_id" suffix. So a class that defines a <tt>belongs_to :person</tt>
1672
1797
  # association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
1673
1798
  # <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
1674
1799
  # of "favorite_person_id".
1675
1800
  #
1676
- # If you are going to modify the association (rather than just read from it), then it is
1677
- # a good idea to set the <tt>:inverse_of</tt> option.
1678
- # [:foreign_type]
1801
+ # Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
1802
+ # inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
1803
+ # [+:foreign_type+]
1679
1804
  # Specify the column used to store the associated object's type, if this is a polymorphic
1680
1805
  # association. By default this is guessed to be the name of the association with a "_type"
1681
1806
  # suffix. So a class that defines a <tt>belongs_to :taggable, polymorphic: true</tt>
1682
1807
  # association will use "taggable_type" as the default <tt>:foreign_type</tt>.
1683
- # [:primary_key]
1808
+ # [+:primary_key+]
1684
1809
  # Specify the method that returns the primary key of associated object used for the association.
1685
1810
  # By default this is +id+.
1686
- # [:dependent]
1811
+ # [+:dependent+]
1687
1812
  # If set to <tt>:destroy</tt>, the associated object is destroyed when this object is. If set to
1688
1813
  # <tt>:delete</tt>, the associated object is deleted *without* calling its destroy method. If set to
1689
1814
  # <tt>:destroy_async</tt>, the associated object is scheduled to be destroyed in a background job.
1690
1815
  # This option should not be specified when #belongs_to is used in conjunction with
1691
1816
  # a #has_many relationship on another class because of the potential to leave
1692
1817
  # orphaned records behind.
1693
- # [:counter_cache]
1818
+ # [+:counter_cache+]
1694
1819
  # Caches the number of belonging objects on the associate class through the use of CounterCache::ClassMethods#increment_counter
1695
1820
  # and CounterCache::ClassMethods#decrement_counter. The counter cache is incremented when an object of this
1696
1821
  # class is created and decremented when it's destroyed. This requires that a column
@@ -1702,14 +1827,14 @@ module ActiveRecord
1702
1827
  # option (e.g., <tt>counter_cache: :my_custom_counter</tt>.)
1703
1828
  # Note: Specifying a counter cache will add it to that model's list of readonly attributes
1704
1829
  # using +attr_readonly+.
1705
- # [:polymorphic]
1830
+ # [+:polymorphic+]
1706
1831
  # Specify this association is a polymorphic association by passing +true+.
1707
1832
  # Note: If you've enabled the counter cache, then you may want to add the counter cache attribute
1708
1833
  # to the +attr_readonly+ list in the associated classes (e.g. <tt>class Post; attr_readonly :comments_count; end</tt>).
1709
- # [:validate]
1834
+ # [+:validate+]
1710
1835
  # When set to +true+, validates new objects added to association when saving the parent object. +false+ by default.
1711
1836
  # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1712
- # [:autosave]
1837
+ # [+:autosave+]
1713
1838
  # If true, always save the associated object or destroy it if marked for destruction, when
1714
1839
  # saving the parent object.
1715
1840
  # If false, never save or destroy the associated object.
@@ -1717,32 +1842,37 @@ module ActiveRecord
1717
1842
  #
1718
1843
  # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for
1719
1844
  # sets <tt>:autosave</tt> to <tt>true</tt>.
1720
- # [:touch]
1721
- # If true, the associated object will be touched (the updated_at/on attributes set to current time)
1845
+ # [+:touch+]
1846
+ # If true, the associated object will be touched (the +updated_at+ / +updated_on+ attributes set to current time)
1722
1847
  # when this record is either saved or destroyed. If you specify a symbol, that attribute
1723
- # will be updated with the current time in addition to the updated_at/on attribute.
1724
- # Please note that with touching no validation is performed and only the +after_touch+,
1725
- # +after_commit+ and +after_rollback+ callbacks are executed.
1726
- # [:inverse_of]
1848
+ # will be updated with the current time in addition to the +updated_at+ / +updated_on+ attribute.
1849
+ # Please note that no validation will be performed when touching, and only the +after_touch+,
1850
+ # +after_commit+, and +after_rollback+ callbacks will be executed.
1851
+ # [+:inverse_of+]
1727
1852
  # Specifies the name of the #has_one or #has_many association on the associated
1728
1853
  # object that is the inverse of this #belongs_to association.
1729
1854
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1730
- # [:optional]
1855
+ # [+:optional+]
1731
1856
  # When set to +true+, the association will not have its presence validated.
1732
- # [:required]
1857
+ # [+:required+]
1733
1858
  # When set to +true+, the association will also have its presence validated.
1734
1859
  # This will validate the association itself, not the id. You can use
1735
1860
  # +:inverse_of+ to avoid an extra query during validation.
1736
1861
  # NOTE: <tt>required</tt> is set to <tt>true</tt> by default and is deprecated. If
1737
1862
  # you don't want to have association presence validated, use <tt>optional: true</tt>.
1738
- # [:default]
1863
+ # [+:default+]
1739
1864
  # Provide a callable (i.e. proc or lambda) to specify that the association should
1740
1865
  # be initialized with a particular record before validation.
1741
- # [:strict_loading]
1866
+ # Please note that callable won't be executed if the record exists.
1867
+ # [+:strict_loading+]
1742
1868
  # Enforces strict loading every time the associated record is loaded through this association.
1743
- # [:ensuring_owner_was]
1869
+ # [+:ensuring_owner_was+]
1744
1870
  # Specifies an instance method to be called on the owner. The method must return true in order for the
1745
1871
  # associated records to be deleted in a background job.
1872
+ # [+:query_constraints+]
1873
+ # Serves as a composite foreign key. Defines the list of columns to be used to query the associated object.
1874
+ # This is an optional option. By default Rails will attempt to derive the value automatically.
1875
+ # When the value is set the Array size must match associated model's primary key or +query_constraints+ size.
1746
1876
  #
1747
1877
  # Option examples:
1748
1878
  # belongs_to :firm, foreign_key: "client_of"
@@ -1758,6 +1888,7 @@ module ActiveRecord
1758
1888
  # belongs_to :user, optional: true
1759
1889
  # belongs_to :account, default: -> { company.account }
1760
1890
  # belongs_to :account, strict_loading: true
1891
+ # belong_to :note, query_constraints: [:organization_id, :note_id]
1761
1892
  def belongs_to(name, scope = nil, **options)
1762
1893
  reflection = Builder::BelongsTo.build(self, name, scope, options)
1763
1894
  Reflection.add_reflection self, name, reflection
@@ -1780,7 +1911,7 @@ module ActiveRecord
1780
1911
  # The join table should not have a primary key or a model associated with it. You must manually generate the
1781
1912
  # join table with a migration such as this:
1782
1913
  #
1783
- # class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[6.0]
1914
+ # class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration[7.1]
1784
1915
  # def change
1785
1916
  # create_join_table :developers, :projects
1786
1917
  # end
@@ -1795,71 +1926,80 @@ module ActiveRecord
1795
1926
  # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1796
1927
  # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
1797
1928
  #
1798
- # [collection]
1929
+ # [<tt>collection</tt>]
1799
1930
  # Returns a Relation of all the associated objects.
1800
1931
  # An empty Relation is returned if none are found.
1801
- # [collection<<(object, ...)]
1932
+ # [<tt>collection<<(object, ...)</tt>]
1802
1933
  # Adds one or more objects to the collection by creating associations in the join table
1803
1934
  # (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
1804
1935
  # Note that this operation instantly fires update SQL without waiting for the save or update call on the
1805
1936
  # parent object, unless the parent object is a new record.
1806
- # [collection.delete(object, ...)]
1937
+ # [<tt>collection.delete(object, ...)</tt>]
1807
1938
  # Removes one or more objects from the collection by removing their associations from the join table.
1808
1939
  # This does not destroy the objects.
1809
- # [collection.destroy(object, ...)]
1940
+ # [<tt>collection.destroy(object, ...)</tt>]
1810
1941
  # Removes one or more objects from the collection by running destroy on each association in the join table, overriding any dependent option.
1811
1942
  # This does not destroy the objects.
1812
- # [collection=objects]
1943
+ # [<tt>collection=objects</tt>]
1813
1944
  # Replaces the collection's content by deleting and adding objects as appropriate.
1814
- # [collection_singular_ids]
1945
+ # [<tt>collection_singular_ids</tt>]
1815
1946
  # Returns an array of the associated objects' ids.
1816
- # [collection_singular_ids=ids]
1947
+ # [<tt>collection_singular_ids=ids</tt>]
1817
1948
  # Replace the collection by the objects identified by the primary keys in +ids+.
1818
- # [collection.clear]
1949
+ # [<tt>collection.clear</tt>]
1819
1950
  # Removes every object from the collection. This does not destroy the objects.
1820
- # [collection.empty?]
1951
+ # [<tt>collection.empty?</tt>]
1821
1952
  # Returns +true+ if there are no associated objects.
1822
- # [collection.size]
1953
+ # [<tt>collection.size</tt>]
1823
1954
  # Returns the number of associated objects.
1824
- # [collection.find(id)]
1955
+ # [<tt>collection.find(id)</tt>]
1825
1956
  # Finds an associated object responding to the +id+ and that
1826
1957
  # meets the condition that it has to be associated with this object.
1827
1958
  # Uses the same rules as ActiveRecord::FinderMethods#find.
1828
- # [collection.exists?(...)]
1959
+ # [<tt>collection.exists?(...)</tt>]
1829
1960
  # Checks whether an associated object with the given conditions exists.
1830
1961
  # Uses the same rules as ActiveRecord::FinderMethods#exists?.
1831
- # [collection.build(attributes = {})]
1962
+ # [<tt>collection.build(attributes = {})</tt>]
1832
1963
  # Returns a new object of the collection type that has been instantiated
1833
1964
  # with +attributes+ and linked to this object through the join table, but has not yet been saved.
1834
- # [collection.create(attributes = {})]
1965
+ # [<tt>collection.create(attributes = {})</tt>]
1835
1966
  # Returns a new object of the collection type that has been instantiated
1836
1967
  # with +attributes+, linked to this object through the join table, and that has already been
1837
1968
  # saved (if it passed the validation).
1838
- # [collection.reload]
1969
+ # [<tt>collection.reload</tt>]
1839
1970
  # Returns a Relation of all of the associated objects, forcing a database read.
1840
1971
  # An empty Relation is returned if none are found.
1841
1972
  #
1842
- # === Example
1843
- #
1844
- # A Developer class declares <tt>has_and_belongs_to_many :projects</tt>, which will add:
1845
- # * <tt>Developer#projects</tt>
1846
- # * <tt>Developer#projects<<</tt>
1847
- # * <tt>Developer#projects.delete</tt>
1848
- # * <tt>Developer#projects.destroy</tt>
1849
- # * <tt>Developer#projects=</tt>
1850
- # * <tt>Developer#project_ids</tt>
1851
- # * <tt>Developer#project_ids=</tt>
1852
- # * <tt>Developer#projects.clear</tt>
1853
- # * <tt>Developer#projects.empty?</tt>
1854
- # * <tt>Developer#projects.size</tt>
1855
- # * <tt>Developer#projects.find(id)</tt>
1856
- # * <tt>Developer#projects.exists?(...)</tt>
1857
- # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new(developer_id: id)</tt>)
1858
- # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new(developer_id: id); c.save; c</tt>)
1859
- # * <tt>Developer#projects.reload</tt>
1973
+ # ==== Example
1974
+ #
1975
+ # class Developer < ActiveRecord::Base
1976
+ # has_and_belongs_to_many :projects
1977
+ # end
1978
+ #
1979
+ # Declaring <tt>has_and_belongs_to_many :projects</tt> adds the following methods (and more):
1980
+ #
1981
+ # developer = Developer.find(11)
1982
+ # project = Project.find(9)
1983
+ #
1984
+ # developer.projects
1985
+ # developer.projects << project
1986
+ # developer.projects.delete(project)
1987
+ # developer.projects.destroy(project)
1988
+ # developer.projects = [project]
1989
+ # developer.project_ids
1990
+ # developer.project_ids = [9]
1991
+ # developer.projects.clear
1992
+ # developer.projects.empty?
1993
+ # developer.projects.size
1994
+ # developer.projects.find(9)
1995
+ # developer.projects.exists?(9)
1996
+ # developer.projects.build # similar to Project.new(developer_id: 11)
1997
+ # developer.projects.create # similar to Project.create(developer_id: 11)
1998
+ # developer.projects.reload
1999
+ #
1860
2000
  # The declaration may include an +options+ hash to specialize the behavior of the association.
1861
2001
  #
1862
- # === Scopes
2002
+ # ==== Scopes
1863
2003
  #
1864
2004
  # You can pass a second argument +scope+ as a callable (i.e. proc or
1865
2005
  # lambda) to retrieve a specific set of records or customize the generated
@@ -1871,11 +2011,11 @@ module ActiveRecord
1871
2011
  # where("default_category = ?", post.default_category)
1872
2012
  # }
1873
2013
  #
1874
- # === Extensions
2014
+ # ==== Extensions
1875
2015
  #
1876
2016
  # The +extension+ argument allows you to pass a block into a
1877
2017
  # has_and_belongs_to_many association. This is useful for adding new
1878
- # finders, creators and other factory-type methods to be used as part of
2018
+ # finders, creators, and other factory-type methods to be used as part of
1879
2019
  # the association.
1880
2020
  #
1881
2021
  # Extension examples:
@@ -1886,33 +2026,33 @@ module ActiveRecord
1886
2026
  # end
1887
2027
  # end
1888
2028
  #
1889
- # === Options
2029
+ # ==== Options
1890
2030
  #
1891
- # [:class_name]
2031
+ # [+:class_name+]
1892
2032
  # Specify the class name of the association. Use it only if that name can't be inferred
1893
2033
  # from the association name. So <tt>has_and_belongs_to_many :projects</tt> will by default be linked to the
1894
2034
  # Project class, but if the real class name is SuperProject, you'll have to specify it with this option.
1895
- # [:join_table]
2035
+ # [+:join_table+]
1896
2036
  # Specify the name of the join table if the default based on lexical order isn't what you want.
1897
2037
  # <b>WARNING:</b> If you're overwriting the table name of either class, the +table_name+ method
1898
2038
  # MUST be declared underneath any #has_and_belongs_to_many declaration in order to work.
1899
- # [:foreign_key]
2039
+ # [+:foreign_key+]
1900
2040
  # Specify the foreign key used for the association. By default this is guessed to be the name
1901
2041
  # of this class in lower-case and "_id" suffixed. So a Person class that makes
1902
2042
  # a #has_and_belongs_to_many association to Project will use "person_id" as the
1903
2043
  # default <tt>:foreign_key</tt>.
1904
2044
  #
1905
- # If you are going to modify the association (rather than just read from it), then it is
1906
- # a good idea to set the <tt>:inverse_of</tt> option.
1907
- # [:association_foreign_key]
2045
+ # Setting the <tt>:foreign_key</tt> option prevents automatic detection of the association's
2046
+ # inverse, so it is generally a good idea to set the <tt>:inverse_of</tt> option as well.
2047
+ # [+:association_foreign_key+]
1908
2048
  # Specify the foreign key used for the association on the receiving side of the association.
1909
2049
  # By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
1910
2050
  # So if a Person class makes a #has_and_belongs_to_many association to Project,
1911
2051
  # the association will use "project_id" as the default <tt>:association_foreign_key</tt>.
1912
- # [:validate]
2052
+ # [+:validate+]
1913
2053
  # When set to +true+, validates new objects added to association when saving the parent object. +true+ by default.
1914
2054
  # If you want to ensure associated objects are revalidated on every update, use +validates_associated+.
1915
- # [:autosave]
2055
+ # [+:autosave+]
1916
2056
  # If true, always save the associated objects or destroy them if marked for destruction, when
1917
2057
  # saving the parent object.
1918
2058
  # If false, never save or destroy the associated objects.
@@ -1920,7 +2060,7 @@ module ActiveRecord
1920
2060
  #
1921
2061
  # Note that NestedAttributes::ClassMethods#accepts_nested_attributes_for sets
1922
2062
  # <tt>:autosave</tt> to <tt>true</tt>.
1923
- # [:strict_loading]
2063
+ # [+:strict_loading+]
1924
2064
  # Enforces strict loading every time an associated record is loaded through this association.
1925
2065
  #
1926
2066
  # Option examples: