activerecord 5.1.0 → 5.2.0.rc1

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

Potentially problematic release.


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

Files changed (260) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +410 -530
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +23 -32
  10. data/lib/active_record/associations/association.rb +20 -21
  11. data/lib/active_record/associations/association_scope.rb +49 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +12 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -6
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +50 -41
  22. data/lib/active_record/associations/collection_proxy.rb +22 -39
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +4 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +12 -18
  26. data/lib/active_record/associations/has_one_association.rb +5 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +27 -44
  32. data/lib/active_record/associations/preloader/association.rb +53 -92
  33. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -10
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +68 -76
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +24 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +8 -2
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +22 -19
  48. data/lib/active_record/attribute_methods.rb +48 -12
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +14 -10
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
  69. data/lib/active_record/connection_adapters/column.rb +4 -2
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -23
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +2 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +269 -126
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
  116. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +39 -60
  128. data/lib/active_record/counter_cache.rb +3 -2
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +17 -13
  132. data/lib/active_record/errors.rb +42 -3
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +67 -60
  138. data/lib/active_record/gem_version.rb +4 -2
  139. data/lib/active_record/inheritance.rb +9 -9
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +8 -6
  144. data/lib/active_record/locking/pessimistic.rb +9 -6
  145. data/lib/active_record/log_subscriber.rb +46 -4
  146. data/lib/active_record/migration/command_recorder.rb +11 -9
  147. data/lib/active_record/migration/compatibility.rb +74 -22
  148. data/lib/active_record/migration/join_table.rb +2 -0
  149. data/lib/active_record/migration.rb +181 -137
  150. data/lib/active_record/model_schema.rb +73 -58
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +153 -18
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +4 -2
  157. data/lib/active_record/railtie.rb +61 -3
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +47 -37
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +131 -204
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  164. data/lib/active_record/relation/batches.rb +32 -17
  165. data/lib/active_record/relation/calculations.rb +58 -20
  166. data/lib/active_record/relation/delegation.rb +10 -29
  167. data/lib/active_record/relation/finder_methods.rb +74 -85
  168. data/lib/active_record/relation/from_clause.rb +2 -8
  169. data/lib/active_record/relation/merger.rb +51 -20
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  172. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  173. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  175. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  176. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  177. data/lib/active_record/relation/predicate_builder.rb +53 -78
  178. data/lib/active_record/relation/query_attribute.rb +9 -2
  179. data/lib/active_record/relation/query_methods.rb +101 -95
  180. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  181. data/lib/active_record/relation/spawn_methods.rb +3 -1
  182. data/lib/active_record/relation/where_clause.rb +65 -67
  183. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  184. data/lib/active_record/relation.rb +99 -202
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +129 -121
  188. data/lib/active_record/schema.rb +4 -2
  189. data/lib/active_record/schema_dumper.rb +36 -26
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping/default.rb +10 -7
  192. data/lib/active_record/scoping/named.rb +38 -12
  193. data/lib/active_record/scoping.rb +12 -10
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +3 -1
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +12 -3
  200. data/lib/active_record/tasks/database_tasks.rb +37 -25
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -5
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  209. data/lib/active_record/type/date.rb +2 -0
  210. data/lib/active_record/type/date_time.rb +2 -0
  211. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  212. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  213. data/lib/active_record/type/internal/timezone.rb +2 -0
  214. data/lib/active_record/type/json.rb +30 -0
  215. data/lib/active_record/type/serialized.rb +2 -0
  216. data/lib/active_record/type/text.rb +2 -0
  217. data/lib/active_record/type/time.rb +2 -0
  218. data/lib/active_record/type/type_map.rb +2 -0
  219. data/lib/active_record/type/unsigned_integer.rb +2 -0
  220. data/lib/active_record/type.rb +4 -1
  221. data/lib/active_record/type_caster/connection.rb +2 -0
  222. data/lib/active_record/type_caster/map.rb +3 -1
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/validations/absence.rb +2 -0
  225. data/lib/active_record/validations/associated.rb +2 -0
  226. data/lib/active_record/validations/length.rb +2 -0
  227. data/lib/active_record/validations/presence.rb +2 -0
  228. data/lib/active_record/validations/uniqueness.rb +35 -5
  229. data/lib/active_record/validations.rb +2 -0
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/active_record.rb +11 -4
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  235. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration.rb +2 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record.rb +3 -1
  242. metadata +25 -37
  243. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  244. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  245. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  246. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  247. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  248. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  249. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -124
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/attribute_set.rb +0 -113
  256. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  257. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  258. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  259. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  260. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class SingularAssociation < Association #:nodoc:
@@ -30,24 +32,22 @@ module ActiveRecord
30
32
  end
31
33
 
32
34
  private
33
-
34
- def create_scope
35
- scope.scope_for_create.stringify_keys.except(klass.primary_key)
35
+ def scope_for_create
36
+ super.except!(klass.primary_key)
36
37
  end
37
38
 
38
39
  def find_target
39
- return scope.take if skip_statement_cache?
40
+ scope = self.scope
41
+ return scope.take if skip_statement_cache?(scope)
40
42
 
41
43
  conn = klass.connection
42
- sc = reflection.association_scope_cache(conn, owner) do
43
- StatementCache.create(conn) { |params|
44
- as = AssociationScope.create { params.bind }
45
- target_scope.merge(as.scope(self, conn)).limit(1)
46
- }
44
+ sc = reflection.association_scope_cache(conn, owner) do |params|
45
+ as = AssociationScope.create { params.bind }
46
+ target_scope.merge!(as.scope(self)).limit(1)
47
47
  end
48
48
 
49
49
  binds = AssociationScope.get_bind_values(owner, reflection.chain)
50
- sc.execute(binds, klass, conn) do |record|
50
+ sc.execute(binds, conn) do |record|
51
51
  set_inverse_instance record
52
52
  end.first
53
53
  rescue ::RangeError
@@ -63,6 +63,10 @@ module ActiveRecord
63
63
  end
64
64
 
65
65
  def _create_record(attributes, raise_error = false)
66
+ unless owner.persisted?
67
+ raise ActiveRecord::RecordNotSaved, "You cannot call create unless the parent is saved"
68
+ end
69
+
66
70
  record = build_record(attributes)
67
71
  yield(record) if block_given?
68
72
  saved = record.save
@@ -1,10 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
- # = Active Record Through Association
3
4
  module Associations
5
+ # = Active Record Through Association
4
6
  module ThroughAssociation #:nodoc:
5
- delegate :source_reflection, :through_reflection, to: :reflection
7
+ delegate :source_reflection, to: :reflection
6
8
 
7
9
  private
10
+ def through_reflection
11
+ @through_reflection ||= begin
12
+ refl = reflection.through_reflection
13
+
14
+ while refl.through_reflection?
15
+ refl = refl.through_reflection
16
+ end
17
+
18
+ refl
19
+ end
20
+ end
21
+
22
+ def through_association
23
+ @through_association ||= owner.association(through_reflection.name)
24
+ end
8
25
 
9
26
  # We merge in these scopes for two reasons:
10
27
  #
@@ -13,7 +30,7 @@ module ActiveRecord
13
30
  def target_scope
14
31
  scope = super
15
32
  reflection.chain.drop(1).each do |reflection|
16
- relation = reflection.klass.all
33
+ relation = reflection.klass.scope_for_association
17
34
  scope.merge!(
18
35
  relation.except(:select, :create_with, :includes, :preload, :joins, :eager_load)
19
36
  )
@@ -36,24 +53,22 @@ module ActiveRecord
36
53
  def construct_join_attributes(*records)
37
54
  ensure_mutable
38
55
 
39
- if source_reflection.association_primary_key(reflection.klass) == reflection.klass.primary_key
56
+ association_primary_key = source_reflection.association_primary_key(reflection.klass)
57
+
58
+ if association_primary_key == reflection.klass.primary_key && !options[:source_type]
40
59
  join_attributes = { source_reflection.name => records }
41
60
  else
42
61
  join_attributes = {
43
- source_reflection.foreign_key =>
44
- records.map { |record|
45
- record.send(source_reflection.association_primary_key(reflection.klass))
46
- }
62
+ source_reflection.foreign_key => records.map(&association_primary_key.to_sym)
47
63
  }
48
64
  end
49
65
 
50
66
  if options[:source_type]
51
- join_attributes[source_reflection.foreign_type] =
52
- records.map { |record| record.class.base_class.name }
67
+ join_attributes[source_reflection.foreign_type] = [ options[:source_type] ]
53
68
  end
54
69
 
55
70
  if records.count == 1
56
- Hash[join_attributes.map { |k, v| [k, v.first] }]
71
+ join_attributes.transform_values!(&:first)
57
72
  else
58
73
  join_attributes
59
74
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/enumerable"
2
4
  require "active_support/core_ext/string/conversions"
3
5
  require "active_support/core_ext/module/remove_method"
@@ -138,26 +140,6 @@ module ActiveRecord
138
140
  class HasOneThroughCantAssociateThroughHasOneOrManyReflection < ThroughCantAssociateThroughHasOneOrManyReflection #:nodoc:
139
141
  end
140
142
 
141
- class HasManyThroughCantAssociateNewRecords < ActiveRecordError #:nodoc:
142
- def initialize(owner = nil, reflection = nil)
143
- if owner && reflection
144
- super("Cannot associate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to create the has_many :through record associating them.")
145
- else
146
- super("Cannot associate new records.")
147
- end
148
- end
149
- end
150
-
151
- class HasManyThroughCantDissociateNewRecords < ActiveRecordError #:nodoc:
152
- def initialize(owner = nil, reflection = nil)
153
- if owner && reflection
154
- super("Cannot dissociate new records through '#{owner.class.name}##{reflection.name}' on '#{reflection.source_reflection.class_name rescue nil}##{reflection.source_reflection.name rescue nil}'. Both records must have an id in order to delete the has_many :through record associating them.")
155
- else
156
- super("Cannot dissociate new records.")
157
- end
158
- end
159
- end
160
-
161
143
  class ThroughNestedAssociationsAreReadonly < ActiveRecordError #:nodoc:
162
144
  def initialize(owner = nil, reflection = nil)
163
145
  if owner && reflection
@@ -187,16 +169,6 @@ module ActiveRecord
187
169
  end
188
170
  end
189
171
 
190
- class ReadOnlyAssociation < ActiveRecordError #:nodoc:
191
- def initialize(reflection = nil)
192
- if reflection
193
- super("Cannot add to a has_many :through association. Try adding to #{reflection.through_reflection.name.inspect}.")
194
- else
195
- super("Read-only reflection error.")
196
- end
197
- end
198
- end
199
-
200
172
  # This error is raised when trying to destroy a parent instance in N:1 or 1:1 associations
201
173
  # (has_many, has_one) when there is at least 1 child associated instance.
202
174
  # ex: if @project.tasks.size > 0, DeleteRestrictionError will be raised when trying to destroy @project
@@ -222,13 +194,6 @@ module ActiveRecord
222
194
  autoload :CollectionAssociation
223
195
  autoload :ForeignAssociation
224
196
  autoload :CollectionProxy
225
-
226
- autoload :BelongsToAssociation
227
- autoload :BelongsToPolymorphicAssociation
228
- autoload :HasManyAssociation
229
- autoload :HasManyThroughAssociation
230
- autoload :HasOneAssociation
231
- autoload :HasOneThroughAssociation
232
197
  autoload :ThroughAssociation
233
198
 
234
199
  module Builder #:nodoc:
@@ -243,6 +208,13 @@ module ActiveRecord
243
208
  end
244
209
 
245
210
  eager_autoload do
211
+ autoload :BelongsToAssociation
212
+ autoload :BelongsToPolymorphicAssociation
213
+ autoload :HasManyAssociation
214
+ autoload :HasManyThroughAssociation
215
+ autoload :HasOneAssociation
216
+ autoload :HasOneThroughAssociation
217
+
246
218
  autoload :Preloader
247
219
  autoload :JoinDependency
248
220
  autoload :AssociationScope
@@ -342,17 +314,18 @@ module ActiveRecord
342
314
  # | | belongs_to |
343
315
  # generated methods | belongs_to | :polymorphic | has_one
344
316
  # ----------------------------------+------------+--------------+---------
345
- # other(force_reload=false) | X | X | X
317
+ # other | X | X | X
346
318
  # other=(other) | X | X | X
347
319
  # build_other(attributes={}) | X | | X
348
320
  # create_other(attributes={}) | X | | X
349
321
  # create_other!(attributes={}) | X | | X
322
+ # reload_other | X | X | X
350
323
  #
351
324
  # === Collection associations (one-to-many / many-to-many)
352
325
  # | | | has_many
353
326
  # generated methods | habtm | has_many | :through
354
327
  # ----------------------------------+-------+----------+----------
355
- # others(force_reload=false) | X | X | X
328
+ # others | X | X | X
356
329
  # others=(other,other,...) | X | X | X
357
330
  # other_ids | X | X | X
358
331
  # other_ids=(id,id,...) | X | X | X
@@ -376,6 +349,7 @@ module ActiveRecord
376
349
  # others.exists? | X | X | X
377
350
  # others.distinct | X | X | X
378
351
  # others.reset | X | X | X
352
+ # others.reload | X | X | X
379
353
  #
380
354
  # === Overriding generated methods
381
355
  #
@@ -479,14 +453,14 @@ module ActiveRecord
479
453
  # The tables for these classes could look something like:
480
454
  #
481
455
  # CREATE TABLE users (
482
- # id int NOT NULL auto_increment,
483
- # account_id int default NULL,
456
+ # id bigint NOT NULL auto_increment,
457
+ # account_id bigint default NULL,
484
458
  # name varchar default NULL,
485
459
  # PRIMARY KEY (id)
486
460
  # )
487
461
  #
488
462
  # CREATE TABLE accounts (
489
- # id int NOT NULL auto_increment,
463
+ # id bigint NOT NULL auto_increment,
490
464
  # name varchar default NULL,
491
465
  # PRIMARY KEY (id)
492
466
  # )
@@ -553,9 +527,8 @@ module ActiveRecord
553
527
  # has_many :birthday_events, ->(user) { where(starts_on: user.birthday) }, class_name: 'Event'
554
528
  # end
555
529
  #
556
- # Note: Joining, eager loading and preloading of these associations is not fully possible.
530
+ # Note: Joining, eager loading and preloading of these associations is not possible.
557
531
  # These operations happen before instance creation and the scope will be called with a +nil+ argument.
558
- # This can lead to unexpected behavior and is deprecated.
559
532
  #
560
533
  # == Association callbacks
561
534
  #
@@ -846,7 +819,7 @@ module ActiveRecord
846
819
  # project.milestones # fetches milestones from the database
847
820
  # project.milestones.size # uses the milestone cache
848
821
  # project.milestones.empty? # uses the milestone cache
849
- # project.milestones(true).size # fetches milestones from the database
822
+ # project.milestones.reload.size # fetches milestones from the database
850
823
  # project.milestones # uses the milestone cache
851
824
  #
852
825
  # == Eager loading of associations
@@ -1088,12 +1061,6 @@ module ActiveRecord
1088
1061
  # belongs_to :dungeon, inverse_of: :evil_wizard
1089
1062
  # end
1090
1063
  #
1091
- # There are limitations to <tt>:inverse_of</tt> support:
1092
- #
1093
- # * does not work with <tt>:through</tt> associations.
1094
- # * does not work with <tt>:polymorphic</tt> associations.
1095
- # * inverse associations for #belongs_to associations #has_many are ignored.
1096
- #
1097
1064
  # For more information, see the documentation for the +:inverse_of+ option.
1098
1065
  #
1099
1066
  # == Deleting from associations
@@ -1187,9 +1154,9 @@ module ActiveRecord
1187
1154
  # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1188
1155
  # <tt>has_many :clients</tt> would add among others <tt>clients.empty?</tt>.
1189
1156
  #
1190
- # [collection(force_reload = false)]
1191
- # Returns an array of all the associated objects.
1192
- # An empty array is returned if none are found.
1157
+ # [collection]
1158
+ # Returns a Relation of all the associated objects.
1159
+ # An empty Relation is returned if none are found.
1193
1160
  # [collection<<(object, ...)]
1194
1161
  # Adds one or more objects to the collection by setting their foreign keys to the collection's primary key.
1195
1162
  # Note that this operation instantly fires update SQL without waiting for the save or update call on the
@@ -1246,6 +1213,9 @@ module ActiveRecord
1246
1213
  # [collection.create!(attributes = {})]
1247
1214
  # Does the same as <tt>collection.create</tt>, but raises ActiveRecord::RecordInvalid
1248
1215
  # if the record is invalid.
1216
+ # [collection.reload]
1217
+ # Returns a Relation of all of the associated objects, forcing a database read.
1218
+ # An empty Relation is returned if none are found.
1249
1219
  #
1250
1220
  # === Example
1251
1221
  #
@@ -1265,6 +1235,7 @@ module ActiveRecord
1265
1235
  # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>)
1266
1236
  # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>)
1267
1237
  # * <tt>Firm#clients.create!</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save!</tt>)
1238
+ # * <tt>Firm#clients.reload</tt>
1268
1239
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1269
1240
  #
1270
1241
  # === Scopes
@@ -1276,7 +1247,7 @@ module ActiveRecord
1276
1247
  # Scope examples:
1277
1248
  # has_many :comments, -> { where(author_id: 1) }
1278
1249
  # has_many :employees, -> { joins(:address) }
1279
- # has_many :posts, ->(post) { where("max_post_length > ?", post.length) }
1250
+ # has_many :posts, ->(blog) { where("max_post_length > ?", blog.max_post_length) }
1280
1251
  #
1281
1252
  # === Extensions
1282
1253
  #
@@ -1302,6 +1273,9 @@ module ActiveRecord
1302
1273
  # Specify the foreign key used for the association. By default this is guessed to be the name
1303
1274
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_many
1304
1275
  # association will use "person_id" as the default <tt>:foreign_key</tt>.
1276
+ #
1277
+ # If you are going to modify the association (rather than just read from it), then it is
1278
+ # a good idea to set the <tt>:inverse_of</tt> option.
1305
1279
  # [:foreign_type]
1306
1280
  # Specify the column used to store the associated object's type, if this is a polymorphic
1307
1281
  # association. By default this is guessed to be the name of the polymorphic association
@@ -1375,8 +1349,7 @@ module ActiveRecord
1375
1349
  # <tt>:autosave</tt> to <tt>true</tt>.
1376
1350
  # [:inverse_of]
1377
1351
  # Specifies the name of the #belongs_to association on the associated object
1378
- # that is the inverse of this #has_many association. Does not work in combination
1379
- # with <tt>:through</tt> or <tt>:as</tt> options.
1352
+ # that is the inverse of this #has_many association.
1380
1353
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1381
1354
  # [:extend]
1382
1355
  # Specifies a module or array of modules that will be extended into the association object returned.
@@ -1392,7 +1365,7 @@ module ActiveRecord
1392
1365
  # has_many :tags, as: :taggable
1393
1366
  # has_many :reports, -> { readonly }
1394
1367
  # has_many :subscribers, through: :subscriptions, source: :user
1395
- def has_many(name, scope = nil, options = {}, &extension)
1368
+ def has_many(name, scope = nil, **options, &extension)
1396
1369
  reflection = Builder::HasMany.build(self, name, scope, options, &extension)
1397
1370
  Reflection.add_reflection self, name, reflection
1398
1371
  end
@@ -1407,7 +1380,7 @@ module ActiveRecord
1407
1380
  # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1408
1381
  # <tt>has_one :manager</tt> would add among others <tt>manager.nil?</tt>.
1409
1382
  #
1410
- # [association(force_reload = false)]
1383
+ # [association]
1411
1384
  # Returns the associated object. +nil+ is returned if none is found.
1412
1385
  # [association=(associate)]
1413
1386
  # Assigns the associate object, extracts the primary key, sets it as the foreign key,
@@ -1424,6 +1397,8 @@ module ActiveRecord
1424
1397
  # [create_association!(attributes = {})]
1425
1398
  # Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
1426
1399
  # if the record is invalid.
1400
+ # [reload_association]
1401
+ # Returns the associated object, forcing a database read.
1427
1402
  #
1428
1403
  # === Example
1429
1404
  #
@@ -1433,6 +1408,7 @@ module ActiveRecord
1433
1408
  # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>)
1434
1409
  # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>)
1435
1410
  # * <tt>Account#create_beneficiary!</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save!; b</tt>)
1411
+ # * <tt>Account#reload_beneficiary</tt>
1436
1412
  #
1437
1413
  # === Scopes
1438
1414
  #
@@ -1443,7 +1419,7 @@ module ActiveRecord
1443
1419
  # Scope examples:
1444
1420
  # has_one :author, -> { where(comment_id: 1) }
1445
1421
  # has_one :employer, -> { joins(:company) }
1446
- # has_one :dob, ->(dob) { where("Date.new(2000, 01, 01) > ?", dob) }
1422
+ # has_one :latest_post, ->(blog) { where("created_at > ?", blog.enabled_at) }
1447
1423
  #
1448
1424
  # === Options
1449
1425
  #
@@ -1469,6 +1445,9 @@ module ActiveRecord
1469
1445
  # Specify the foreign key used for the association. By default this is guessed to be the name
1470
1446
  # of this class in lower-case and "_id" suffixed. So a Person class that makes a #has_one association
1471
1447
  # will use "person_id" as the default <tt>:foreign_key</tt>.
1448
+ #
1449
+ # If you are going to modify the association (rather than just read from it), then it is
1450
+ # a good idea to set the <tt>:inverse_of</tt> option.
1472
1451
  # [:foreign_type]
1473
1452
  # Specify the column used to store the associated object's type, if this is a polymorphic
1474
1453
  # association. By default this is guessed to be the name of the polymorphic association
@@ -1484,6 +1463,9 @@ module ActiveRecord
1484
1463
  # <tt>:primary_key</tt>, and <tt>:foreign_key</tt> are ignored, as the association uses the
1485
1464
  # source reflection. You can only use a <tt>:through</tt> query through a #has_one
1486
1465
  # or #belongs_to association on the join model.
1466
+ #
1467
+ # If you are going to modify the association (rather than just read from it), then it is
1468
+ # a good idea to set the <tt>:inverse_of</tt> option.
1487
1469
  # [:source]
1488
1470
  # Specifies the source association name used by #has_one <tt>:through</tt> queries.
1489
1471
  # Only use it if the name cannot be inferred from the association.
@@ -1504,8 +1486,7 @@ module ActiveRecord
1504
1486
  # <tt>:autosave</tt> to <tt>true</tt>.
1505
1487
  # [:inverse_of]
1506
1488
  # Specifies the name of the #belongs_to association on the associated object
1507
- # that is the inverse of this #has_one association. Does not work in combination
1508
- # with <tt>:through</tt> or <tt>:as</tt> options.
1489
+ # that is the inverse of this #has_one association.
1509
1490
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1510
1491
  # [:required]
1511
1492
  # When set to +true+, the association will also have its presence validated.
@@ -1523,7 +1504,7 @@ module ActiveRecord
1523
1504
  # has_one :club, through: :membership
1524
1505
  # has_one :primary_address, -> { where(primary: true) }, through: :addressables, source: :addressable
1525
1506
  # has_one :credit_card, required: true
1526
- def has_one(name, scope = nil, options = {})
1507
+ def has_one(name, scope = nil, **options)
1527
1508
  reflection = Builder::HasOne.build(self, name, scope, options)
1528
1509
  Reflection.add_reflection self, name, reflection
1529
1510
  end
@@ -1539,7 +1520,7 @@ module ActiveRecord
1539
1520
  # +association+ is a placeholder for the symbol passed as the +name+ argument, so
1540
1521
  # <tt>belongs_to :author</tt> would add among others <tt>author.nil?</tt>.
1541
1522
  #
1542
- # [association(force_reload = false)]
1523
+ # [association]
1543
1524
  # Returns the associated object. +nil+ is returned if none is found.
1544
1525
  # [association=(associate)]
1545
1526
  # Assigns the associate object, extracts the primary key, and sets it as the foreign key.
@@ -1553,6 +1534,8 @@ module ActiveRecord
1553
1534
  # [create_association!(attributes = {})]
1554
1535
  # Does the same as <tt>create_association</tt>, but raises ActiveRecord::RecordInvalid
1555
1536
  # if the record is invalid.
1537
+ # [reload_association]
1538
+ # Returns the associated object, forcing a database read.
1556
1539
  #
1557
1540
  # === Example
1558
1541
  #
@@ -1562,6 +1545,7 @@ module ActiveRecord
1562
1545
  # * <tt>Post#build_author</tt> (similar to <tt>post.author = Author.new</tt>)
1563
1546
  # * <tt>Post#create_author</tt> (similar to <tt>post.author = Author.new; post.author.save; post.author</tt>)
1564
1547
  # * <tt>Post#create_author!</tt> (similar to <tt>post.author = Author.new; post.author.save!; post.author</tt>)
1548
+ # * <tt>Post#reload_author</tt>
1565
1549
  # The declaration can also include an +options+ hash to specialize the behavior of the association.
1566
1550
  #
1567
1551
  # === Scopes
@@ -1573,7 +1557,7 @@ module ActiveRecord
1573
1557
  # Scope examples:
1574
1558
  # belongs_to :firm, -> { where(id: 2) }
1575
1559
  # belongs_to :user, -> { joins(:friends) }
1576
- # belongs_to :level, ->(level) { where("game_level > ?", level.current) }
1560
+ # belongs_to :level, ->(game) { where("game_level > ?", game.current_level) }
1577
1561
  #
1578
1562
  # === Options
1579
1563
  #
@@ -1587,6 +1571,9 @@ module ActiveRecord
1587
1571
  # association will use "person_id" as the default <tt>:foreign_key</tt>. Similarly,
1588
1572
  # <tt>belongs_to :favorite_person, class_name: "Person"</tt> will use a foreign key
1589
1573
  # of "favorite_person_id".
1574
+ #
1575
+ # If you are going to modify the association (rather than just read from it), then it is
1576
+ # a good idea to set the <tt>:inverse_of</tt> option.
1590
1577
  # [:foreign_type]
1591
1578
  # Specify the column used to store the associated object's type, if this is a polymorphic
1592
1579
  # association. By default this is guessed to be the name of the association with a "_type"
@@ -1636,8 +1623,7 @@ module ActiveRecord
1636
1623
  # +after_commit+ and +after_rollback+ callbacks are executed.
1637
1624
  # [:inverse_of]
1638
1625
  # Specifies the name of the #has_one or #has_many association on the associated
1639
- # object that is the inverse of this #belongs_to association. Does not work in
1640
- # combination with the <tt>:polymorphic</tt> options.
1626
+ # object that is the inverse of this #belongs_to association.
1641
1627
  # See ActiveRecord::Associations::ClassMethods's overview on Bi-directional associations for more detail.
1642
1628
  # [:optional]
1643
1629
  # When set to +true+, the association will not have its presence validated.
@@ -1664,7 +1650,7 @@ module ActiveRecord
1664
1650
  # belongs_to :company, touch: :employees_last_updated_at
1665
1651
  # belongs_to :user, optional: true
1666
1652
  # belongs_to :account, default: -> { company.account }
1667
- def belongs_to(name, scope = nil, options = {})
1653
+ def belongs_to(name, scope = nil, **options)
1668
1654
  reflection = Builder::BelongsTo.build(self, name, scope, options)
1669
1655
  Reflection.add_reflection self, name, reflection
1670
1656
  end
@@ -1701,9 +1687,9 @@ module ActiveRecord
1701
1687
  # +collection+ is a placeholder for the symbol passed as the +name+ argument, so
1702
1688
  # <tt>has_and_belongs_to_many :categories</tt> would add among others <tt>categories.empty?</tt>.
1703
1689
  #
1704
- # [collection(force_reload = false)]
1705
- # Returns an array of all the associated objects.
1706
- # An empty array is returned if none are found.
1690
+ # [collection]
1691
+ # Returns a Relation of all the associated objects.
1692
+ # An empty Relation is returned if none are found.
1707
1693
  # [collection<<(object, ...)]
1708
1694
  # Adds one or more objects to the collection by creating associations in the join table
1709
1695
  # (<tt>collection.push</tt> and <tt>collection.concat</tt> are aliases to this method).
@@ -1741,6 +1727,9 @@ module ActiveRecord
1741
1727
  # Returns a new object of the collection type that has been instantiated
1742
1728
  # with +attributes+, linked to this object through the join table, and that has already been
1743
1729
  # saved (if it passed the validation).
1730
+ # [collection.reload]
1731
+ # Returns a Relation of all of the associated objects, forcing a database read.
1732
+ # An empty Relation is returned if none are found.
1744
1733
  #
1745
1734
  # === Example
1746
1735
  #
@@ -1759,6 +1748,7 @@ module ActiveRecord
1759
1748
  # * <tt>Developer#projects.exists?(...)</tt>
1760
1749
  # * <tt>Developer#projects.build</tt> (similar to <tt>Project.new("developer_id" => id)</tt>)
1761
1750
  # * <tt>Developer#projects.create</tt> (similar to <tt>c = Project.new("developer_id" => id); c.save; c</tt>)
1751
+ # * <tt>Developer#projects.reload</tt>
1762
1752
  # The declaration may include an +options+ hash to specialize the behavior of the association.
1763
1753
  #
1764
1754
  # === Scopes
@@ -1769,9 +1759,8 @@ module ActiveRecord
1769
1759
  #
1770
1760
  # Scope examples:
1771
1761
  # has_and_belongs_to_many :projects, -> { includes(:milestones, :manager) }
1772
- # has_and_belongs_to_many :categories, ->(category) {
1773
- # where("default_category = ?", category.name)
1774
- # }
1762
+ # has_and_belongs_to_many :categories, ->(post) {
1763
+ # where("default_category = ?", post.default_category)
1775
1764
  #
1776
1765
  # === Extensions
1777
1766
  #
@@ -1803,6 +1792,9 @@ module ActiveRecord
1803
1792
  # of this class in lower-case and "_id" suffixed. So a Person class that makes
1804
1793
  # a #has_and_belongs_to_many association to Project will use "person_id" as the
1805
1794
  # default <tt>:foreign_key</tt>.
1795
+ #
1796
+ # If you are going to modify the association (rather than just read from it), then it is
1797
+ # a good idea to set the <tt>:inverse_of</tt> option.
1806
1798
  # [:association_foreign_key]
1807
1799
  # Specify the foreign key used for the association on the receiving side of the association.
1808
1800
  # By default this is guessed to be the name of the associated class in lower-case and "_id" suffixed.
@@ -1831,7 +1823,7 @@ module ActiveRecord
1831
1823
 
1832
1824
  builder = Builder::HasAndBelongsToMany.new name, self, options
1833
1825
 
1834
- join_model = ActiveSupport::Deprecation.silence { builder.through_model }
1826
+ join_model = builder.through_model
1835
1827
 
1836
1828
  const_set join_model.name, join_model
1837
1829
  private_constant join_model.name
@@ -1860,7 +1852,7 @@ module ActiveRecord
1860
1852
  hm_options[k] = options[k] if options.key? k
1861
1853
  end
1862
1854
 
1863
- ActiveSupport::Deprecation.silence { has_many name, scope, hm_options, &extension }
1855
+ has_many name, scope, hm_options, &extension
1864
1856
  _reflections[name.to_s].parent_reflection = habtm_reflection
1865
1857
  end
1866
1858
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_model/forbidden_attributes_protection"
2
4
 
3
5
  module ActiveRecord
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeDecorators # :nodoc:
3
5
  extend ActiveSupport::Concern
4
6
 
5
7
  included do
6
- class_attribute :attribute_type_decorations, instance_accessor: false # :internal:
7
- self.attribute_type_decorations = TypeDecorator.new
8
+ class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
8
9
  end
9
10
 
10
11
  module ClassMethods # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  # = Active Record Attribute Methods Before Type Cast