activerecord 5.2.4.4 → 6.0.0

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

Potentially problematic release.


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

Files changed (268) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +611 -590
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +4 -2
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record.rb +9 -2
  7. data/lib/active_record/aggregations.rb +4 -2
  8. data/lib/active_record/associations.rb +19 -14
  9. data/lib/active_record/associations/association.rb +52 -19
  10. data/lib/active_record/associations/association_scope.rb +4 -6
  11. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  12. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  13. data/lib/active_record/associations/builder/association.rb +14 -18
  14. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  15. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
  17. data/lib/active_record/associations/builder/has_many.rb +2 -0
  18. data/lib/active_record/associations/builder/has_one.rb +35 -1
  19. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  20. data/lib/active_record/associations/collection_association.rb +6 -21
  21. data/lib/active_record/associations/collection_proxy.rb +12 -15
  22. data/lib/active_record/associations/foreign_association.rb +7 -0
  23. data/lib/active_record/associations/has_many_association.rb +2 -10
  24. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  25. data/lib/active_record/associations/has_one_association.rb +28 -30
  26. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  27. data/lib/active_record/associations/join_dependency.rb +24 -28
  28. data/lib/active_record/associations/join_dependency/join_association.rb +9 -10
  29. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  30. data/lib/active_record/associations/preloader.rb +40 -32
  31. data/lib/active_record/associations/preloader/association.rb +38 -36
  32. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  33. data/lib/active_record/associations/singular_association.rb +2 -16
  34. data/lib/active_record/attribute_assignment.rb +7 -10
  35. data/lib/active_record/attribute_methods.rb +28 -100
  36. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -1
  37. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  38. data/lib/active_record/attribute_methods/primary_key.rb +15 -22
  39. data/lib/active_record/attribute_methods/query.rb +2 -3
  40. data/lib/active_record/attribute_methods/read.rb +15 -53
  41. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  42. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  43. data/lib/active_record/attribute_methods/write.rb +17 -24
  44. data/lib/active_record/attributes.rb +13 -0
  45. data/lib/active_record/autosave_association.rb +5 -9
  46. data/lib/active_record/base.rb +2 -3
  47. data/lib/active_record/callbacks.rb +5 -19
  48. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +94 -16
  49. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  50. data/lib/active_record/connection_adapters/abstract/database_statements.rb +95 -123
  51. data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -8
  52. data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
  53. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +19 -12
  54. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +76 -48
  55. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  56. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +132 -53
  57. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -56
  58. data/lib/active_record/connection_adapters/abstract_adapter.rb +180 -47
  59. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +128 -194
  60. data/lib/active_record/connection_adapters/column.rb +17 -13
  61. data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
  62. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  63. data/lib/active_record/connection_adapters/mysql/database_statements.rb +73 -13
  64. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  65. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
  66. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  67. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  68. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +129 -13
  69. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  70. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -9
  71. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  72. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +20 -1
  73. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  74. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  75. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
  76. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
  77. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  78. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
  79. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  81. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +6 -3
  82. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  83. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +12 -1
  84. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  85. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +55 -53
  86. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  87. data/lib/active_record/connection_adapters/postgresql_adapter.rb +160 -74
  88. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  89. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  90. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
  91. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -6
  92. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +42 -11
  93. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +125 -141
  94. data/lib/active_record/connection_handling.rb +149 -27
  95. data/lib/active_record/core.rb +100 -60
  96. data/lib/active_record/counter_cache.rb +4 -29
  97. data/lib/active_record/database_configurations.rb +233 -0
  98. data/lib/active_record/database_configurations/database_config.rb +37 -0
  99. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  100. data/lib/active_record/database_configurations/url_config.rb +79 -0
  101. data/lib/active_record/dynamic_matchers.rb +1 -1
  102. data/lib/active_record/enum.rb +37 -7
  103. data/lib/active_record/errors.rb +15 -7
  104. data/lib/active_record/explain.rb +1 -1
  105. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  106. data/lib/active_record/fixture_set/render_context.rb +17 -0
  107. data/lib/active_record/fixture_set/table_row.rb +153 -0
  108. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  109. data/lib/active_record/fixtures.rb +145 -472
  110. data/lib/active_record/gem_version.rb +4 -4
  111. data/lib/active_record/inheritance.rb +13 -3
  112. data/lib/active_record/insert_all.rb +179 -0
  113. data/lib/active_record/integration.rb +68 -16
  114. data/lib/active_record/internal_metadata.rb +10 -2
  115. data/lib/active_record/locking/optimistic.rb +5 -6
  116. data/lib/active_record/locking/pessimistic.rb +3 -3
  117. data/lib/active_record/log_subscriber.rb +7 -26
  118. data/lib/active_record/middleware/database_selector.rb +75 -0
  119. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  120. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  121. data/lib/active_record/migration.rb +100 -81
  122. data/lib/active_record/migration/command_recorder.rb +50 -6
  123. data/lib/active_record/migration/compatibility.rb +76 -49
  124. data/lib/active_record/model_schema.rb +30 -9
  125. data/lib/active_record/nested_attributes.rb +2 -2
  126. data/lib/active_record/no_touching.rb +7 -0
  127. data/lib/active_record/persistence.rb +228 -24
  128. data/lib/active_record/query_cache.rb +11 -4
  129. data/lib/active_record/querying.rb +32 -20
  130. data/lib/active_record/railtie.rb +80 -43
  131. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  132. data/lib/active_record/railties/controller_runtime.rb +30 -35
  133. data/lib/active_record/railties/databases.rake +196 -46
  134. data/lib/active_record/reflection.rb +32 -30
  135. data/lib/active_record/relation.rb +310 -80
  136. data/lib/active_record/relation/batches.rb +13 -10
  137. data/lib/active_record/relation/calculations.rb +53 -47
  138. data/lib/active_record/relation/delegation.rb +26 -43
  139. data/lib/active_record/relation/finder_methods.rb +13 -26
  140. data/lib/active_record/relation/merger.rb +11 -20
  141. data/lib/active_record/relation/predicate_builder.rb +4 -6
  142. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  143. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  144. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  145. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  146. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  147. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  148. data/lib/active_record/relation/query_attribute.rb +13 -8
  149. data/lib/active_record/relation/query_methods.rb +189 -63
  150. data/lib/active_record/relation/spawn_methods.rb +1 -1
  151. data/lib/active_record/relation/where_clause.rb +14 -10
  152. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  153. data/lib/active_record/result.rb +30 -11
  154. data/lib/active_record/sanitization.rb +32 -40
  155. data/lib/active_record/schema.rb +2 -11
  156. data/lib/active_record/schema_dumper.rb +22 -7
  157. data/lib/active_record/schema_migration.rb +5 -1
  158. data/lib/active_record/scoping.rb +8 -8
  159. data/lib/active_record/scoping/default.rb +4 -5
  160. data/lib/active_record/scoping/named.rb +19 -15
  161. data/lib/active_record/statement_cache.rb +30 -3
  162. data/lib/active_record/store.rb +87 -8
  163. data/lib/active_record/table_metadata.rb +10 -17
  164. data/lib/active_record/tasks/database_tasks.rb +194 -25
  165. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -5
  166. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
  167. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
  168. data/lib/active_record/test_databases.rb +23 -0
  169. data/lib/active_record/test_fixtures.rb +224 -0
  170. data/lib/active_record/timestamp.rb +39 -25
  171. data/lib/active_record/touch_later.rb +4 -2
  172. data/lib/active_record/transactions.rb +57 -66
  173. data/lib/active_record/translation.rb +1 -1
  174. data/lib/active_record/type.rb +3 -4
  175. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  176. data/lib/active_record/type_caster/connection.rb +15 -14
  177. data/lib/active_record/type_caster/map.rb +1 -4
  178. data/lib/active_record/validations.rb +1 -0
  179. data/lib/active_record/validations/uniqueness.rb +15 -27
  180. data/lib/arel.rb +51 -0
  181. data/lib/arel/alias_predication.rb +9 -0
  182. data/lib/arel/attributes.rb +22 -0
  183. data/lib/arel/attributes/attribute.rb +37 -0
  184. data/lib/arel/collectors/bind.rb +24 -0
  185. data/lib/arel/collectors/composite.rb +31 -0
  186. data/lib/arel/collectors/plain_string.rb +20 -0
  187. data/lib/arel/collectors/sql_string.rb +20 -0
  188. data/lib/arel/collectors/substitute_binds.rb +28 -0
  189. data/lib/arel/crud.rb +42 -0
  190. data/lib/arel/delete_manager.rb +18 -0
  191. data/lib/arel/errors.rb +9 -0
  192. data/lib/arel/expressions.rb +29 -0
  193. data/lib/arel/factory_methods.rb +49 -0
  194. data/lib/arel/insert_manager.rb +49 -0
  195. data/lib/arel/math.rb +45 -0
  196. data/lib/arel/nodes.rb +68 -0
  197. data/lib/arel/nodes/and.rb +32 -0
  198. data/lib/arel/nodes/ascending.rb +23 -0
  199. data/lib/arel/nodes/binary.rb +52 -0
  200. data/lib/arel/nodes/bind_param.rb +36 -0
  201. data/lib/arel/nodes/case.rb +55 -0
  202. data/lib/arel/nodes/casted.rb +50 -0
  203. data/lib/arel/nodes/comment.rb +29 -0
  204. data/lib/arel/nodes/count.rb +12 -0
  205. data/lib/arel/nodes/delete_statement.rb +45 -0
  206. data/lib/arel/nodes/descending.rb +23 -0
  207. data/lib/arel/nodes/equality.rb +18 -0
  208. data/lib/arel/nodes/extract.rb +24 -0
  209. data/lib/arel/nodes/false.rb +16 -0
  210. data/lib/arel/nodes/full_outer_join.rb +8 -0
  211. data/lib/arel/nodes/function.rb +44 -0
  212. data/lib/arel/nodes/grouping.rb +8 -0
  213. data/lib/arel/nodes/in.rb +8 -0
  214. data/lib/arel/nodes/infix_operation.rb +80 -0
  215. data/lib/arel/nodes/inner_join.rb +8 -0
  216. data/lib/arel/nodes/insert_statement.rb +37 -0
  217. data/lib/arel/nodes/join_source.rb +20 -0
  218. data/lib/arel/nodes/matches.rb +18 -0
  219. data/lib/arel/nodes/named_function.rb +23 -0
  220. data/lib/arel/nodes/node.rb +50 -0
  221. data/lib/arel/nodes/node_expression.rb +13 -0
  222. data/lib/arel/nodes/outer_join.rb +8 -0
  223. data/lib/arel/nodes/over.rb +15 -0
  224. data/lib/arel/nodes/regexp.rb +16 -0
  225. data/lib/arel/nodes/right_outer_join.rb +8 -0
  226. data/lib/arel/nodes/select_core.rb +67 -0
  227. data/lib/arel/nodes/select_statement.rb +41 -0
  228. data/lib/arel/nodes/sql_literal.rb +16 -0
  229. data/lib/arel/nodes/string_join.rb +11 -0
  230. data/lib/arel/nodes/table_alias.rb +27 -0
  231. data/lib/arel/nodes/terminal.rb +16 -0
  232. data/lib/arel/nodes/true.rb +16 -0
  233. data/lib/arel/nodes/unary.rb +45 -0
  234. data/lib/arel/nodes/unary_operation.rb +20 -0
  235. data/lib/arel/nodes/unqualified_column.rb +22 -0
  236. data/lib/arel/nodes/update_statement.rb +41 -0
  237. data/lib/arel/nodes/values_list.rb +9 -0
  238. data/lib/arel/nodes/window.rb +126 -0
  239. data/lib/arel/nodes/with.rb +11 -0
  240. data/lib/arel/order_predications.rb +13 -0
  241. data/lib/arel/predications.rb +257 -0
  242. data/lib/arel/select_manager.rb +271 -0
  243. data/lib/arel/table.rb +110 -0
  244. data/lib/arel/tree_manager.rb +72 -0
  245. data/lib/arel/update_manager.rb +34 -0
  246. data/lib/arel/visitors.rb +20 -0
  247. data/lib/arel/visitors/depth_first.rb +204 -0
  248. data/lib/arel/visitors/dot.rb +297 -0
  249. data/lib/arel/visitors/ibm_db.rb +34 -0
  250. data/lib/arel/visitors/informix.rb +62 -0
  251. data/lib/arel/visitors/mssql.rb +157 -0
  252. data/lib/arel/visitors/mysql.rb +83 -0
  253. data/lib/arel/visitors/oracle.rb +159 -0
  254. data/lib/arel/visitors/oracle12.rb +66 -0
  255. data/lib/arel/visitors/postgresql.rb +110 -0
  256. data/lib/arel/visitors/sqlite.rb +39 -0
  257. data/lib/arel/visitors/to_sql.rb +889 -0
  258. data/lib/arel/visitors/visitor.rb +46 -0
  259. data/lib/arel/visitors/where_sql.rb +23 -0
  260. data/lib/arel/window_predications.rb +9 -0
  261. data/lib/rails/generators/active_record/migration.rb +14 -1
  262. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  263. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  264. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  265. data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
  266. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  267. metadata +108 -26
  268. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -73,7 +73,7 @@ module ActiveRecord
73
73
  # `skip_time_zone_conversion_for_attributes` would not be picked up.
74
74
  subclass.class_eval do
75
75
  matcher = ->(name, type) { create_time_zone_conversion_attribute?(name, type) }
76
- decorate_matching_attribute_types(matcher, :_time_zone_conversion) do |type|
76
+ decorate_matching_attribute_types(matcher, "_time_zone_conversion") do |type|
77
77
  TimeZoneConverter.new(type)
78
78
  end
79
79
  end
@@ -13,19 +13,16 @@ module ActiveRecord
13
13
  private
14
14
 
15
15
  def define_method_attribute=(name)
16
- safe_name = name.unpack("h*".freeze).first
17
- ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
18
- sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
19
-
20
- generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
21
- def __temp__#{safe_name}=(value)
22
- name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
23
- #{sync_with_transaction_state}
24
- _write_attribute(name, value)
25
- end
26
- alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
27
- undef_method :__temp__#{safe_name}=
28
- STR
16
+ ActiveModel::AttributeMethods::AttrNames.define_attribute_accessor_method(
17
+ generated_attribute_methods, name, writer: true,
18
+ ) do |temp_method_name, attr_name_expr|
19
+ generated_attribute_methods.module_eval <<-RUBY, __FILE__, __LINE__ + 1
20
+ def #{temp_method_name}(value)
21
+ name = #{attr_name_expr}
22
+ _write_attribute(name, value)
23
+ end
24
+ RUBY
25
+ end
29
26
  end
30
27
  end
31
28
 
@@ -33,33 +30,29 @@ module ActiveRecord
33
30
  # specified +value+. Empty strings for Integer and Float columns are
34
31
  # turned into +nil+.
35
32
  def write_attribute(attr_name, value)
36
- name = if self.class.attribute_alias?(attr_name)
37
- self.class.attribute_alias(attr_name).to_s
38
- else
39
- attr_name.to_s
40
- end
33
+ name = attr_name.to_s
34
+ name = self.class.attribute_aliases[name] || name
41
35
 
42
- primary_key = self.class.primary_key
43
- name = primary_key if name == "id".freeze && primary_key
44
- sync_with_transaction_state if name == primary_key
36
+ name = @primary_key if name == "id" && @primary_key
45
37
  _write_attribute(name, value)
46
38
  end
47
39
 
48
40
  # This method exists to avoid the expensive primary_key check internally, without
49
41
  # breaking compatibility with the write_attribute API
50
42
  def _write_attribute(attr_name, value) # :nodoc:
43
+ sync_with_transaction_state if @transaction_state&.finalized?
51
44
  @attributes.write_from_user(attr_name.to_s, value)
52
45
  value
53
46
  end
54
47
 
55
48
  private
56
49
  def write_attribute_without_type_cast(attr_name, value)
57
- name = attr_name.to_s
58
- @attributes.write_cast_value(name, value)
50
+ sync_with_transaction_state if @transaction_state&.finalized?
51
+ @attributes.write_cast_value(attr_name.to_s, value)
59
52
  value
60
53
  end
61
54
 
62
- # Handle *= for method_missing.
55
+ # Dispatch target for <tt>*=</tt> attribute methods.
63
56
  def attribute=(attribute_name, value)
64
57
  _write_attribute(attribute_name, value)
65
58
  end
@@ -41,6 +41,9 @@ module ActiveRecord
41
41
  # +range+ (PostgreSQL only) specifies that the type should be a range (see the
42
42
  # examples below).
43
43
  #
44
+ # When using a symbol for +cast_type+, extra options are forwarded to the
45
+ # constructor of the type object.
46
+ #
44
47
  # ==== Examples
45
48
  #
46
49
  # The type detected by Active Record can be overridden.
@@ -112,6 +115,16 @@ module ActiveRecord
112
115
  # my_float_range: 1.0..3.5
113
116
  # }
114
117
  #
118
+ # Passing options to the type constructor
119
+ #
120
+ # # app/models/my_model.rb
121
+ # class MyModel < ActiveRecord::Base
122
+ # attribute :small_int, :integer, limit: 2
123
+ # end
124
+ #
125
+ # MyModel.create(small_int: 65537)
126
+ # # => Error: 65537 is out of range for the limit of two bytes
127
+ #
115
128
  # ==== Creating Custom Types
116
129
  #
117
130
  # Users may also define their own custom types, as long as they respond
@@ -149,7 +149,7 @@ module ActiveRecord
149
149
  private
150
150
 
151
151
  def define_non_cyclic_method(name, &block)
152
- return if method_defined?(name)
152
+ return if instance_methods(false).include?(name)
153
153
  define_method(name) do |*args|
154
154
  result = true; @_already_called ||= {}
155
155
  # Loop prevention for validation of associations
@@ -272,7 +272,7 @@ module ActiveRecord
272
272
  # or saved. If +autosave+ is +false+ only new records will be returned,
273
273
  # unless the parent is/was a new record itself.
274
274
  def associated_records_to_validate_or_save(association, new_record, autosave)
275
- if new_record || custom_validation_context?
275
+ if new_record
276
276
  association && association.target
277
277
  elsif autosave
278
278
  association.target.find_all(&:changed_for_autosave?)
@@ -304,7 +304,7 @@ module ActiveRecord
304
304
  def validate_single_association(reflection)
305
305
  association = association_instance_get(reflection.name)
306
306
  record = association && association.reader
307
- association_valid?(reflection, record) if record && (record.changed_for_autosave? || custom_validation_context?)
307
+ association_valid?(reflection, record) if record && record.changed_for_autosave?
308
308
  end
309
309
 
310
310
  # Validate the associated records if <tt>:validate</tt> or
@@ -324,7 +324,7 @@ module ActiveRecord
324
324
  def association_valid?(reflection, record, index = nil)
325
325
  return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
326
326
 
327
- context = validation_context if custom_validation_context?
327
+ context = validation_context unless [:create, :update].include?(validation_context)
328
328
 
329
329
  unless valid = record.valid?(context)
330
330
  if reflection.options[:autosave]
@@ -416,7 +416,7 @@ module ActiveRecord
416
416
  saved = record.save(validate: false)
417
417
  end
418
418
 
419
- raise ActiveRecord::Rollback unless saved
419
+ raise(RecordInvalid.new(association.owner)) unless saved
420
420
  end
421
421
  end
422
422
  end
@@ -499,10 +499,6 @@ module ActiveRecord
499
499
  end
500
500
  end
501
501
 
502
- def custom_validation_context?
503
- validation_context && [:create, :update].exclude?(validation_context)
504
- end
505
-
506
502
  def _ensure_no_duplicate_errors
507
503
  errors.messages.each_key do |attribute|
508
504
  errors[attribute].uniq!
@@ -9,7 +9,6 @@ require "active_support/core_ext/module/attribute_accessors"
9
9
  require "active_support/core_ext/array/extract_options"
10
10
  require "active_support/core_ext/hash/deep_merge"
11
11
  require "active_support/core_ext/hash/slice"
12
- require "active_support/core_ext/hash/transform_values"
13
12
  require "active_support/core_ext/string/behavior"
14
13
  require "active_support/core_ext/kernel/singleton_class"
15
14
  require "active_support/core_ext/module/introspection"
@@ -23,6 +22,7 @@ require "active_record/explain_subscriber"
23
22
  require "active_record/relation/delegation"
24
23
  require "active_record/attributes"
25
24
  require "active_record/type_caster"
25
+ require "active_record/database_configurations"
26
26
 
27
27
  module ActiveRecord #:nodoc:
28
28
  # = Active Record
@@ -288,7 +288,7 @@ module ActiveRecord #:nodoc:
288
288
  extend Explain
289
289
  extend Enum
290
290
  extend Delegation::DelegateCache
291
- extend CollectionCacheKey
291
+ extend Aggregations::ClassMethods
292
292
 
293
293
  include Core
294
294
  include Persistence
@@ -314,7 +314,6 @@ module ActiveRecord #:nodoc:
314
314
  include ActiveModel::SecurePassword
315
315
  include AutosaveAssociation
316
316
  include NestedAttributes
317
- include Aggregations
318
317
  include Transactions
319
318
  include TouchLater
320
319
  include NoTouching
@@ -75,21 +75,7 @@ module ActiveRecord
75
75
  # end
76
76
  #
77
77
  # Now, when <tt>Topic#destroy</tt> is run only +destroy_author+ is called. When <tt>Reply#destroy</tt> is
78
- # run, both +destroy_author+ and +destroy_readers+ are called. Contrast this to the following situation
79
- # where the +before_destroy+ method is overridden:
80
- #
81
- # class Topic < ActiveRecord::Base
82
- # def before_destroy() destroy_author end
83
- # end
84
- #
85
- # class Reply < Topic
86
- # def before_destroy() destroy_readers end
87
- # end
88
- #
89
- # In that case, <tt>Reply#destroy</tt> would only run +destroy_readers+ and _not_ +destroy_author+.
90
- # So, use the callback macros when you want to ensure that a certain callback is called for the entire
91
- # hierarchy, and use the regular overwritable methods when you want to leave it up to each descendant
92
- # to decide whether they want to call +super+ and trigger the inherited callbacks.
78
+ # run, both +destroy_author+ and +destroy_readers+ are called.
93
79
  #
94
80
  # *IMPORTANT:* In order for inheritance to work for the callback queues, you must specify the
95
81
  # callbacks before specifying the associations. Otherwise, you might trigger the loading of a
@@ -109,7 +95,7 @@ module ActiveRecord
109
95
  #
110
96
  # private
111
97
  # def delete_parents
112
- # self.class.delete_all "parent_id = #{id}"
98
+ # self.class.delete_by(parent_id: id)
113
99
  # end
114
100
  # end
115
101
  #
@@ -142,7 +128,7 @@ module ActiveRecord
142
128
  # end
143
129
  # end
144
130
  #
145
- # So you specify the object you want messaged on a given callback. When that callback is triggered, the object has
131
+ # So you specify the object you want to be messaged on a given callback. When that callback is triggered, the object has
146
132
  # a method by the name of the callback messaged. You can make these callbacks more flexible by passing in other
147
133
  # initialization data such as the name of the attribute to work with:
148
134
  #
@@ -338,7 +324,7 @@ module ActiveRecord
338
324
 
339
325
  private
340
326
 
341
- def create_or_update(*)
327
+ def create_or_update(**)
342
328
  _run_save_callbacks { super }
343
329
  end
344
330
 
@@ -346,7 +332,7 @@ module ActiveRecord
346
332
  _run_create_callbacks { super }
347
333
  end
348
334
 
349
- def _update_record(*)
335
+ def _update_record
350
336
  _run_update_callbacks { super }
351
337
  end
352
338
  end
@@ -3,6 +3,7 @@
3
3
  require "thread"
4
4
  require "concurrent/map"
5
5
  require "monitor"
6
+ require "weakref"
6
7
 
7
8
  module ActiveRecord
8
9
  # Raised when a connection could not be obtained within the connection
@@ -19,6 +20,26 @@ module ActiveRecord
19
20
  end
20
21
 
21
22
  module ConnectionAdapters
23
+ module AbstractPool # :nodoc:
24
+ def get_schema_cache(connection)
25
+ @schema_cache ||= SchemaCache.new(connection)
26
+ @schema_cache.connection = connection
27
+ @schema_cache
28
+ end
29
+
30
+ def set_schema_cache(cache)
31
+ @schema_cache = cache
32
+ end
33
+ end
34
+
35
+ class NullPool # :nodoc:
36
+ include ConnectionAdapters::AbstractPool
37
+
38
+ def initialize
39
+ @schema_cache = nil
40
+ end
41
+ end
42
+
22
43
  # Connection pool base class for managing Active Record database
23
44
  # connections.
24
45
  #
@@ -185,7 +206,7 @@ module ActiveRecord
185
206
  def wait_poll(timeout)
186
207
  @num_waiting += 1
187
208
 
188
- t0 = Time.now
209
+ t0 = Concurrent.monotonic_time
189
210
  elapsed = 0
190
211
  loop do
191
212
  ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
@@ -194,7 +215,7 @@ module ActiveRecord
194
215
 
195
216
  return remove if any?
196
217
 
197
- elapsed = Time.now - t0
218
+ elapsed = Concurrent.monotonic_time - t0
198
219
  if elapsed >= timeout
199
220
  msg = "could not obtain a connection from the pool within %0.3f seconds (waited %0.3f seconds); all pooled connections were in use" %
200
221
  [timeout, elapsed]
@@ -294,20 +315,48 @@ module ActiveRecord
294
315
  @frequency = frequency
295
316
  end
296
317
 
318
+ @mutex = Mutex.new
319
+ @pools = {}
320
+
321
+ class << self
322
+ def register_pool(pool, frequency) # :nodoc:
323
+ @mutex.synchronize do
324
+ unless @pools.key?(frequency)
325
+ @pools[frequency] = []
326
+ spawn_thread(frequency)
327
+ end
328
+ @pools[frequency] << WeakRef.new(pool)
329
+ end
330
+ end
331
+
332
+ private
333
+
334
+ def spawn_thread(frequency)
335
+ Thread.new(frequency) do |t|
336
+ loop do
337
+ sleep t
338
+ @mutex.synchronize do
339
+ @pools[frequency].select!(&:weakref_alive?)
340
+ @pools[frequency].each do |p|
341
+ p.reap
342
+ p.flush
343
+ rescue WeakRef::RefError
344
+ end
345
+ end
346
+ end
347
+ end
348
+ end
349
+ end
350
+
297
351
  def run
298
352
  return unless frequency && frequency > 0
299
- Thread.new(frequency, pool) { |t, p|
300
- loop do
301
- sleep t
302
- p.reap
303
- p.flush
304
- end
305
- }
353
+ self.class.register_pool(pool, frequency)
306
354
  end
307
355
  end
308
356
 
309
357
  include MonitorMixin
310
358
  include QueryCache::ConnectionPoolConfiguration
359
+ include ConnectionAdapters::AbstractPool
311
360
 
312
361
  attr_accessor :automatic_reconnect, :checkout_timeout, :schema_cache
313
362
  attr_reader :spec, :size, :reaper
@@ -705,13 +754,13 @@ module ActiveRecord
705
754
  end
706
755
 
707
756
  newly_checked_out = []
708
- timeout_time = Time.now + (@checkout_timeout * 2)
757
+ timeout_time = Concurrent.monotonic_time + (@checkout_timeout * 2)
709
758
 
710
759
  @available.with_a_bias_for(Thread.current) do
711
760
  loop do
712
761
  synchronize do
713
762
  return if collected_conns.size == @connections.size && @now_connecting == 0
714
- remaining_timeout = timeout_time - Time.now
763
+ remaining_timeout = timeout_time - Concurrent.monotonic_time
715
764
  remaining_timeout = 0 if remaining_timeout < 0
716
765
  conn = checkout_for_exclusive_access(remaining_timeout)
717
766
  collected_conns << conn
@@ -750,7 +799,7 @@ module ActiveRecord
750
799
  # this block can't be easily moved into attempt_to_checkout_all_existing_connections's
751
800
  # rescue block, because doing so would put it outside of synchronize section, without
752
801
  # being in a critical section thread_report might become inaccurate
753
- msg = "could not obtain ownership of all database connections in #{checkout_timeout} seconds".dup
802
+ msg = +"could not obtain ownership of all database connections in #{checkout_timeout} seconds"
754
803
 
755
804
  thread_report = []
756
805
  @connections.each do |conn|
@@ -828,7 +877,7 @@ module ActiveRecord
828
877
 
829
878
  def new_connection
830
879
  Base.send(spec.adapter_method, spec.config).tap do |conn|
831
- conn.schema_cache = schema_cache.dup if schema_cache
880
+ conn.check_version
832
881
  end
833
882
  end
834
883
 
@@ -965,6 +1014,26 @@ module ActiveRecord
965
1014
  ObjectSpace.define_finalizer self, ConnectionHandler.unowned_pool_finalizer(@owner_to_pool)
966
1015
  end
967
1016
 
1017
+ def prevent_writes # :nodoc:
1018
+ Thread.current[:prevent_writes]
1019
+ end
1020
+
1021
+ def prevent_writes=(prevent_writes) # :nodoc:
1022
+ Thread.current[:prevent_writes] = prevent_writes
1023
+ end
1024
+
1025
+ # Prevent writing to the database regardless of role.
1026
+ #
1027
+ # In some cases you may want to prevent writes to the database
1028
+ # even if you are on a database that can write. `while_preventing_writes`
1029
+ # will prevent writes to the database for the duration of the block.
1030
+ def while_preventing_writes(enabled = true)
1031
+ original, self.prevent_writes = self.prevent_writes, enabled
1032
+ yield
1033
+ ensure
1034
+ self.prevent_writes = original
1035
+ end
1036
+
968
1037
  def connection_pool_list
969
1038
  owner_to_pool.values.compact
970
1039
  end
@@ -1029,15 +1098,24 @@ module ActiveRecord
1029
1098
  # for (not necessarily the current class).
1030
1099
  def retrieve_connection(spec_name) #:nodoc:
1031
1100
  pool = retrieve_connection_pool(spec_name)
1032
- raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found." unless pool
1101
+
1102
+ unless pool
1103
+ # multiple database application
1104
+ if ActiveRecord::Base.connection_handler != ActiveRecord::Base.default_connection_handler
1105
+ raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found for the '#{ActiveRecord::Base.current_role}' role."
1106
+ else
1107
+ raise ConnectionNotEstablished, "No connection pool with '#{spec_name}' found."
1108
+ end
1109
+ end
1110
+
1033
1111
  pool.connection
1034
1112
  end
1035
1113
 
1036
1114
  # Returns true if a connection that's accessible to this class has
1037
1115
  # already been opened.
1038
1116
  def connected?(spec_name)
1039
- conn = retrieve_connection_pool(spec_name)
1040
- conn && conn.connected?
1117
+ pool = retrieve_connection_pool(spec_name)
1118
+ pool && pool.connected?
1041
1119
  end
1042
1120
 
1043
1121
  # Remove the connection for this class. This will close the active
@@ -1,22 +1,30 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/deprecation"
4
+
3
5
  module ActiveRecord
4
6
  module ConnectionAdapters # :nodoc:
5
7
  module DatabaseLimits
8
+ def max_identifier_length # :nodoc:
9
+ 64
10
+ end
11
+
6
12
  # Returns the maximum length of a table alias.
7
13
  def table_alias_length
8
- 255
14
+ max_identifier_length
9
15
  end
10
16
 
11
17
  # Returns the maximum length of a column name.
12
18
  def column_name_length
13
- 64
19
+ max_identifier_length
14
20
  end
21
+ deprecate :column_name_length
15
22
 
16
23
  # Returns the maximum length of a table name.
17
24
  def table_name_length
18
- 64
25
+ max_identifier_length
19
26
  end
27
+ deprecate :table_name_length
20
28
 
21
29
  # Returns the maximum allowed length for an index name. This
22
30
  # limit is enforced by \Rails and is less than or equal to
@@ -29,23 +37,26 @@ module ActiveRecord
29
37
 
30
38
  # Returns the maximum length of an index name.
31
39
  def index_name_length
32
- 64
40
+ max_identifier_length
33
41
  end
34
42
 
35
43
  # Returns the maximum number of columns per table.
36
44
  def columns_per_table
37
45
  1024
38
46
  end
47
+ deprecate :columns_per_table
39
48
 
40
49
  # Returns the maximum number of indexes per table.
41
50
  def indexes_per_table
42
51
  16
43
52
  end
53
+ deprecate :indexes_per_table
44
54
 
45
55
  # Returns the maximum number of columns in a multicolumn index.
46
56
  def columns_per_multicolumn_index
47
57
  16
48
58
  end
59
+ deprecate :columns_per_multicolumn_index
49
60
 
50
61
  # Returns the maximum number of elements in an IN (x,y,z) clause.
51
62
  # +nil+ means no limit.
@@ -57,11 +68,13 @@ module ActiveRecord
57
68
  def sql_query_length
58
69
  1048575
59
70
  end
71
+ deprecate :sql_query_length
60
72
 
61
73
  # Returns maximum number of joins in a single query.
62
74
  def joins_per_query
63
75
  256
64
76
  end
77
+ deprecate :joins_per_query
65
78
 
66
79
  private
67
80
  def bind_params_length