activerecord 3.2.19 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

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