activerecord 3.1.10 → 4.2.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

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