activerecord 6.1.4.1 → 7.0.1

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 (237) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1132 -936
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/active_record/aggregations.rb +1 -1
  6. data/lib/active_record/association_relation.rb +0 -10
  7. data/lib/active_record/associations/association.rb +33 -17
  8. data/lib/active_record/associations/association_scope.rb +1 -3
  9. data/lib/active_record/associations/belongs_to_association.rb +15 -4
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
  11. data/lib/active_record/associations/builder/association.rb +8 -2
  12. data/lib/active_record/associations/builder/belongs_to.rb +19 -6
  13. data/lib/active_record/associations/builder/collection_association.rb +10 -3
  14. data/lib/active_record/associations/builder/has_many.rb +3 -2
  15. data/lib/active_record/associations/builder/has_one.rb +2 -1
  16. data/lib/active_record/associations/builder/singular_association.rb +2 -2
  17. data/lib/active_record/associations/collection_association.rb +34 -27
  18. data/lib/active_record/associations/collection_proxy.rb +8 -3
  19. data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
  20. data/lib/active_record/associations/has_many_association.rb +1 -1
  21. data/lib/active_record/associations/has_many_through_association.rb +2 -1
  22. data/lib/active_record/associations/has_one_association.rb +10 -7
  23. data/lib/active_record/associations/has_one_through_association.rb +1 -1
  24. data/lib/active_record/associations/join_dependency.rb +6 -2
  25. data/lib/active_record/associations/preloader/association.rb +187 -55
  26. data/lib/active_record/associations/preloader/batch.rb +48 -0
  27. data/lib/active_record/associations/preloader/branch.rb +147 -0
  28. data/lib/active_record/associations/preloader/through_association.rb +49 -13
  29. data/lib/active_record/associations/preloader.rb +39 -113
  30. data/lib/active_record/associations/singular_association.rb +8 -2
  31. data/lib/active_record/associations/through_association.rb +3 -3
  32. data/lib/active_record/associations.rb +118 -90
  33. data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
  34. data/lib/active_record/attribute_assignment.rb +1 -1
  35. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
  36. data/lib/active_record/attribute_methods/dirty.rb +49 -16
  37. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  38. data/lib/active_record/attribute_methods/query.rb +2 -2
  39. data/lib/active_record/attribute_methods/read.rb +7 -5
  40. data/lib/active_record/attribute_methods/serialization.rb +66 -12
  41. data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
  42. data/lib/active_record/attribute_methods/write.rb +7 -10
  43. data/lib/active_record/attribute_methods.rb +13 -14
  44. data/lib/active_record/attributes.rb +24 -35
  45. data/lib/active_record/autosave_association.rb +6 -21
  46. data/lib/active_record/base.rb +19 -1
  47. data/lib/active_record/callbacks.rb +2 -2
  48. data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
  49. data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
  50. data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
  56. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
  57. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +34 -9
  58. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +78 -22
  59. data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
  60. data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
  61. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +97 -81
  62. data/lib/active_record/connection_adapters/column.rb +4 -0
  63. data/lib/active_record/connection_adapters/mysql/database_statements.rb +37 -23
  64. data/lib/active_record/connection_adapters/mysql/quoting.rb +35 -21
  65. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +5 -1
  66. data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
  67. data/lib/active_record/connection_adapters/pool_config.rb +7 -7
  68. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
  69. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -12
  70. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
  71. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
  72. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
  73. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
  74. data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
  75. data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
  76. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
  77. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  78. data/lib/active_record/connection_adapters/postgresql/quoting.rb +50 -50
  79. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +32 -0
  80. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
  81. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
  82. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
  83. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +29 -18
  84. data/lib/active_record/connection_adapters/postgresql_adapter.rb +205 -105
  85. data/lib/active_record/connection_adapters/schema_cache.rb +29 -4
  86. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +27 -19
  87. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +28 -16
  88. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +16 -14
  89. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +89 -30
  90. data/lib/active_record/connection_adapters.rb +6 -5
  91. data/lib/active_record/connection_handling.rb +47 -53
  92. data/lib/active_record/core.rb +122 -132
  93. data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
  94. data/lib/active_record/database_configurations/database_config.rb +12 -9
  95. data/lib/active_record/database_configurations/hash_config.rb +63 -5
  96. data/lib/active_record/database_configurations/url_config.rb +2 -2
  97. data/lib/active_record/database_configurations.rb +16 -32
  98. data/lib/active_record/delegated_type.rb +52 -11
  99. data/lib/active_record/destroy_association_async_job.rb +1 -1
  100. data/lib/active_record/disable_joins_association_relation.rb +39 -0
  101. data/lib/active_record/dynamic_matchers.rb +1 -1
  102. data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
  103. data/lib/active_record/encryption/cipher.rb +53 -0
  104. data/lib/active_record/encryption/config.rb +44 -0
  105. data/lib/active_record/encryption/configurable.rb +61 -0
  106. data/lib/active_record/encryption/context.rb +35 -0
  107. data/lib/active_record/encryption/contexts.rb +72 -0
  108. data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
  109. data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
  110. data/lib/active_record/encryption/encryptable_record.rb +208 -0
  111. data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
  112. data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
  113. data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
  114. data/lib/active_record/encryption/encryptor.rb +155 -0
  115. data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
  116. data/lib/active_record/encryption/errors.rb +15 -0
  117. data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
  118. data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
  119. data/lib/active_record/encryption/key.rb +28 -0
  120. data/lib/active_record/encryption/key_generator.rb +42 -0
  121. data/lib/active_record/encryption/key_provider.rb +46 -0
  122. data/lib/active_record/encryption/message.rb +33 -0
  123. data/lib/active_record/encryption/message_serializer.rb +90 -0
  124. data/lib/active_record/encryption/null_encryptor.rb +21 -0
  125. data/lib/active_record/encryption/properties.rb +76 -0
  126. data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
  127. data/lib/active_record/encryption/scheme.rb +99 -0
  128. data/lib/active_record/encryption.rb +55 -0
  129. data/lib/active_record/enum.rb +49 -42
  130. data/lib/active_record/errors.rb +67 -4
  131. data/lib/active_record/explain_registry.rb +11 -6
  132. data/lib/active_record/fixture_set/file.rb +15 -1
  133. data/lib/active_record/fixture_set/table_row.rb +41 -6
  134. data/lib/active_record/fixture_set/table_rows.rb +4 -4
  135. data/lib/active_record/fixtures.rb +17 -20
  136. data/lib/active_record/future_result.rb +139 -0
  137. data/lib/active_record/gem_version.rb +4 -4
  138. data/lib/active_record/inheritance.rb +55 -17
  139. data/lib/active_record/insert_all.rb +80 -14
  140. data/lib/active_record/integration.rb +4 -3
  141. data/lib/active_record/internal_metadata.rb +3 -5
  142. data/lib/active_record/legacy_yaml_adapter.rb +2 -39
  143. data/lib/active_record/locking/optimistic.rb +10 -9
  144. data/lib/active_record/locking/pessimistic.rb +9 -3
  145. data/lib/active_record/log_subscriber.rb +14 -3
  146. data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
  147. data/lib/active_record/middleware/database_selector.rb +8 -3
  148. data/lib/active_record/middleware/shard_selector.rb +60 -0
  149. data/lib/active_record/migration/command_recorder.rb +4 -4
  150. data/lib/active_record/migration/compatibility.rb +107 -3
  151. data/lib/active_record/migration/join_table.rb +1 -1
  152. data/lib/active_record/migration.rb +109 -79
  153. data/lib/active_record/model_schema.rb +45 -58
  154. data/lib/active_record/nested_attributes.rb +13 -12
  155. data/lib/active_record/no_touching.rb +3 -3
  156. data/lib/active_record/null_relation.rb +2 -6
  157. data/lib/active_record/persistence.rb +219 -52
  158. data/lib/active_record/query_cache.rb +2 -2
  159. data/lib/active_record/query_logs.rb +138 -0
  160. data/lib/active_record/querying.rb +15 -5
  161. data/lib/active_record/railtie.rb +127 -17
  162. data/lib/active_record/railties/controller_runtime.rb +1 -1
  163. data/lib/active_record/railties/databases.rake +66 -129
  164. data/lib/active_record/readonly_attributes.rb +11 -0
  165. data/lib/active_record/reflection.rb +67 -50
  166. data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
  167. data/lib/active_record/relation/batches.rb +3 -3
  168. data/lib/active_record/relation/calculations.rb +43 -38
  169. data/lib/active_record/relation/delegation.rb +6 -6
  170. data/lib/active_record/relation/finder_methods.rb +31 -35
  171. data/lib/active_record/relation/merger.rb +20 -13
  172. data/lib/active_record/relation/predicate_builder.rb +1 -6
  173. data/lib/active_record/relation/query_attribute.rb +5 -11
  174. data/lib/active_record/relation/query_methods.rb +243 -61
  175. data/lib/active_record/relation/record_fetch_warning.rb +7 -9
  176. data/lib/active_record/relation/spawn_methods.rb +2 -2
  177. data/lib/active_record/relation/where_clause.rb +10 -19
  178. data/lib/active_record/relation.rb +184 -84
  179. data/lib/active_record/result.rb +17 -7
  180. data/lib/active_record/runtime_registry.rb +9 -13
  181. data/lib/active_record/sanitization.rb +11 -7
  182. data/lib/active_record/schema_dumper.rb +10 -3
  183. data/lib/active_record/schema_migration.rb +4 -4
  184. data/lib/active_record/scoping/default.rb +61 -12
  185. data/lib/active_record/scoping/named.rb +3 -11
  186. data/lib/active_record/scoping.rb +64 -34
  187. data/lib/active_record/serialization.rb +1 -1
  188. data/lib/active_record/signed_id.rb +1 -1
  189. data/lib/active_record/suppressor.rb +11 -15
  190. data/lib/active_record/tasks/database_tasks.rb +120 -58
  191. data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
  192. data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -12
  193. data/lib/active_record/test_databases.rb +1 -1
  194. data/lib/active_record/test_fixtures.rb +4 -4
  195. data/lib/active_record/timestamp.rb +3 -4
  196. data/lib/active_record/transactions.rb +9 -14
  197. data/lib/active_record/translation.rb +2 -2
  198. data/lib/active_record/type/adapter_specific_registry.rb +32 -7
  199. data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
  200. data/lib/active_record/type/internal/timezone.rb +2 -2
  201. data/lib/active_record/type/serialized.rb +1 -1
  202. data/lib/active_record/type/type_map.rb +17 -20
  203. data/lib/active_record/type.rb +1 -2
  204. data/lib/active_record/validations/associated.rb +1 -1
  205. data/lib/active_record/validations/uniqueness.rb +1 -1
  206. data/lib/active_record.rb +204 -28
  207. data/lib/arel/attributes/attribute.rb +0 -8
  208. data/lib/arel/crud.rb +28 -22
  209. data/lib/arel/delete_manager.rb +18 -4
  210. data/lib/arel/filter_predications.rb +9 -0
  211. data/lib/arel/insert_manager.rb +2 -3
  212. data/lib/arel/nodes/casted.rb +1 -1
  213. data/lib/arel/nodes/delete_statement.rb +12 -13
  214. data/lib/arel/nodes/filter.rb +10 -0
  215. data/lib/arel/nodes/function.rb +1 -0
  216. data/lib/arel/nodes/insert_statement.rb +2 -2
  217. data/lib/arel/nodes/select_core.rb +2 -2
  218. data/lib/arel/nodes/select_statement.rb +2 -2
  219. data/lib/arel/nodes/update_statement.rb +8 -3
  220. data/lib/arel/nodes.rb +1 -0
  221. data/lib/arel/predications.rb +11 -3
  222. data/lib/arel/select_manager.rb +10 -4
  223. data/lib/arel/table.rb +0 -1
  224. data/lib/arel/tree_manager.rb +0 -12
  225. data/lib/arel/update_manager.rb +18 -4
  226. data/lib/arel/visitors/dot.rb +80 -90
  227. data/lib/arel/visitors/mysql.rb +8 -2
  228. data/lib/arel/visitors/postgresql.rb +0 -10
  229. data/lib/arel/visitors/to_sql.rb +58 -2
  230. data/lib/arel.rb +2 -1
  231. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
  232. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
  233. data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
  234. data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
  235. data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
  236. data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
  237. metadata +59 -14
@@ -37,7 +37,11 @@ module ActiveRecord
37
37
 
38
38
  return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
39
39
 
40
- name = "#{payload[:name]} (#{event.duration.round(1)}ms)"
40
+ name = if payload[:async]
41
+ "ASYNC #{payload[:name]} (#{payload[:lock_wait].round(1)}ms) (db time #{event.duration.round(1)}ms)"
42
+ else
43
+ "#{payload[:name]} (#{event.duration.round(1)}ms)"
44
+ end
41
45
  name = "CACHE #{name}" if payload[:cached]
42
46
  sql = payload[:sql]
43
47
  binds = nil
@@ -47,7 +51,10 @@ module ActiveRecord
47
51
 
48
52
  binds = []
49
53
  payload[:binds].each_with_index do |attr, i|
50
- binds << render_bind(attr, casted_params[i])
54
+ attribute_name = attr.respond_to?(:name) ? attr.name : attr[i].name
55
+ filtered_params = filter(attribute_name, casted_params[i])
56
+
57
+ binds << render_bind(attr, filtered_params)
51
58
  end
52
59
  binds = binds.inspect
53
60
  binds.prepend(" ")
@@ -115,7 +122,7 @@ module ActiveRecord
115
122
  def debug(progname = nil, &block)
116
123
  return unless super
117
124
 
118
- if ActiveRecord::Base.verbose_query_logs
125
+ if ActiveRecord.verbose_query_logs
119
126
  log_query_source
120
127
  end
121
128
  end
@@ -131,6 +138,10 @@ module ActiveRecord
131
138
  def extract_query_source_location(locations)
132
139
  backtrace_cleaner.clean(locations.lazy).first
133
140
  end
141
+
142
+ def filter(name, value)
143
+ ActiveRecord::Base.inspection_filter.filter_param(name, value)
144
+ end
134
145
  end
135
146
  end
136
147
 
@@ -50,23 +50,19 @@ module ActiveRecord
50
50
 
51
51
  private
52
52
  def read_from_primary(&blk)
53
- ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role, prevent_writes: true) do
54
- instrumenter.instrument("database_selector.active_record.read_from_primary") do
55
- yield
56
- end
53
+ ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: true) do
54
+ instrumenter.instrument("database_selector.active_record.read_from_primary", &blk)
57
55
  end
58
56
  end
59
57
 
60
58
  def read_from_replica(&blk)
61
- ActiveRecord::Base.connected_to(role: ActiveRecord::Base.reading_role, prevent_writes: true) do
62
- instrumenter.instrument("database_selector.active_record.read_from_replica") do
63
- yield
64
- end
59
+ ActiveRecord::Base.connected_to(role: ActiveRecord.reading_role, prevent_writes: true) do
60
+ instrumenter.instrument("database_selector.active_record.read_from_replica", &blk)
65
61
  end
66
62
  end
67
63
 
68
- def write_to_primary(&blk)
69
- ActiveRecord::Base.connected_to(role: ActiveRecord::Base.writing_role, prevent_writes: false) do
64
+ def write_to_primary
65
+ ActiveRecord::Base.connected_to(role: ActiveRecord.writing_role, prevent_writes: false) do
70
66
  instrumenter.instrument("database_selector.active_record.wrote_to_primary") do
71
67
  yield
72
68
  ensure
@@ -22,9 +22,14 @@ module ActiveRecord
22
22
  # To use the DatabaseSelector in your application with default settings add
23
23
  # the following options to your environment config:
24
24
  #
25
- # config.active_record.database_selector = { delay: 2.seconds }
26
- # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
27
- # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
25
+ # # This require is only necessary when using `rails new app --minimal`
26
+ # require "active_support/core_ext/integer/time"
27
+ #
28
+ # class Application < Rails::Application
29
+ # config.active_record.database_selector = { delay: 2.seconds }
30
+ # config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
31
+ # config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
32
+ # end
28
33
  #
29
34
  # New applications will include these lines commented out in the production.rb.
30
35
  #
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Middleware
5
+ # The ShardSelector Middleware provides a framework for automatically
6
+ # swapping shards. Rails provides a basic framework to determine which
7
+ # shard to switch to and allows for applications to write custom strategies
8
+ # for swapping if needed.
9
+ #
10
+ # The ShardSelector takes a set of options (currently only `lock` is supported)
11
+ # that can be used by the middleware to alter behavior. `lock` is
12
+ # true by default and will prohibit the request from switching shards once
13
+ # inside the block. If `lock` is false, then shard swapping will be allowed.
14
+ # For tenant based sharding, `lock` should always be true to prevent application
15
+ # code from mistakenly switching between tenants.
16
+ #
17
+ # Options can be set in the config:
18
+ #
19
+ # config.active_record.shard_selector = { lock: true }
20
+ #
21
+ # Applications must also provide the code for the resolver as it depends on application
22
+ # specific models. An example resolver would look like this:
23
+ #
24
+ # config.active_record.shard_resolver = ->(request) {
25
+ # subdomain = request.subdomain
26
+ # tenant = Tenant.find_by_subdomain!(subdomain)
27
+ # tenant.shard
28
+ # }
29
+ class ShardSelector
30
+ def initialize(app, resolver, options = {})
31
+ @app = app
32
+ @resolver = resolver
33
+ @options = options
34
+ end
35
+
36
+ attr_reader :resolver, :options
37
+
38
+ def call(env)
39
+ request = ActionDispatch::Request.new(env)
40
+
41
+ shard = selected_shard(request)
42
+
43
+ set_shard(shard) do
44
+ @app.call(env)
45
+ end
46
+ end
47
+
48
+ private
49
+ def selected_shard(request)
50
+ resolver.call(request)
51
+ end
52
+
53
+ def set_shard(shard, &block)
54
+ ActiveRecord::Base.connected_to(shard: shard.to_sym) do
55
+ ActiveRecord::Base.prohibit_shard_swapping(options.fetch(:lock, true), &block)
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -112,7 +112,7 @@ module ActiveRecord
112
112
  record(:"#{method}", args, &block) # record(:create_table, args, &block)
113
113
  end # end
114
114
  EOV
115
- ruby2_keywords(method) if respond_to?(:ruby2_keywords, true)
115
+ ruby2_keywords(method)
116
116
  end
117
117
  alias :add_belongs_to :add_reference
118
118
  alias :remove_belongs_to :remove_reference
@@ -154,9 +154,9 @@ module ActiveRecord
154
154
 
155
155
  include StraightReversions
156
156
 
157
- def invert_transaction(args)
157
+ def invert_transaction(args, &block)
158
158
  sub_recorder = CommandRecorder.new(delegate)
159
- sub_recorder.revert { yield }
159
+ sub_recorder.revert(&block)
160
160
 
161
161
  invertions_proc = proc {
162
162
  sub_recorder.replay(self)
@@ -286,7 +286,7 @@ module ActiveRecord
286
286
  super
287
287
  end
288
288
  end
289
- ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
289
+ ruby2_keywords(:method_missing)
290
290
  end
291
291
  end
292
292
  end
@@ -13,7 +13,77 @@ module ActiveRecord
13
13
  const_get(name)
14
14
  end
15
15
 
16
- V6_1 = Current
16
+ # This file exists to ensure that old migrations run the same way they did before a Rails upgrade.
17
+ # e.g. if you write a migration on Rails 6.1, then upgrade to Rails 7, the migration should do the same thing to your
18
+ # database as it did when you were running Rails 6.1
19
+ #
20
+ # "Current" is an alias for `ActiveRecord::Migration`, it represents the current Rails version.
21
+ # New migration functionality that will never be backward compatible should be added directly to `ActiveRecord::Migration`.
22
+ #
23
+ # There are classes for each prior Rails version. Each class descends from the *next* Rails version, so:
24
+ # 6.1 < 7.0
25
+ # 5.2 < 6.0 < 6.1 < 7.0
26
+ #
27
+ # If you are introducing new migration functionality that should only apply from Rails 7 onward, then you should
28
+ # find the class that immediately precedes it (6.1), and override the relevant migration methods to undo your changes.
29
+ #
30
+ # For example, Rails 6 added a default value for the `precision` option on datetime columns. So in this file, the `V5_2`
31
+ # class sets the value of `precision` to `nil` if it's not explicitly provided. This way, the default value will not apply
32
+ # for migrations written for 5.2, but will for migrations written for 6.0.
33
+ V7_0 = Current
34
+
35
+ class V6_1 < V7_0
36
+ class PostgreSQLCompat
37
+ def self.compatible_timestamp_type(type, connection)
38
+ if connection.adapter_name == "PostgreSQL"
39
+ # For Rails <= 6.1, :datetime was aliased to :timestamp
40
+ # See: https://github.com/rails/rails/blob/v6.1.3.2/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb#L108
41
+ # From Rails 7 onwards, you can define what :datetime resolves to (the default is still :timestamp)
42
+ # See `ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.datetime_type`
43
+ type.to_sym == :datetime ? :timestamp : type
44
+ else
45
+ type
46
+ end
47
+ end
48
+ end
49
+
50
+ def add_column(table_name, column_name, type, **options)
51
+ if type == :datetime
52
+ options[:precision] ||= nil
53
+ end
54
+
55
+ type = PostgreSQLCompat.compatible_timestamp_type(type, connection)
56
+ super
57
+ end
58
+
59
+ def create_table(table_name, **options)
60
+ if block_given?
61
+ super { |t| yield compatible_table_definition(t) }
62
+ else
63
+ super
64
+ end
65
+ end
66
+
67
+ module TableDefinition
68
+ def new_column_definition(name, type, **options)
69
+ type = PostgreSQLCompat.compatible_timestamp_type(type, @conn)
70
+ super
71
+ end
72
+
73
+ def column(name, type, index: nil, **options)
74
+ options[:precision] ||= nil
75
+ super
76
+ end
77
+ end
78
+
79
+ private
80
+ def compatible_table_definition(t)
81
+ class << t
82
+ prepend TableDefinition
83
+ end
84
+ t
85
+ end
86
+ end
17
87
 
18
88
  class V6_0 < V6_1
19
89
  class ReferenceDefinition < ConnectionAdapters::ReferenceDefinition
@@ -22,6 +92,22 @@ module ActiveRecord
22
92
  end
23
93
  end
24
94
 
95
+ module SQLite3
96
+ module TableDefinition
97
+ def references(*args, **options)
98
+ args.each do |ref_name|
99
+ ReferenceDefinition.new(ref_name, type: :integer, **options).add_to(self)
100
+ end
101
+ end
102
+ alias :belongs_to :references
103
+
104
+ def column(name, type, index: nil, **options)
105
+ options[:precision] ||= nil
106
+ super
107
+ end
108
+ end
109
+ end
110
+
25
111
  module TableDefinition
26
112
  def references(*args, **options)
27
113
  args.each do |ref_name|
@@ -29,6 +115,11 @@ module ActiveRecord
29
115
  end
30
116
  end
31
117
  alias :belongs_to :references
118
+
119
+ def column(name, type, index: nil, **options)
120
+ options[:precision] ||= nil
121
+ super
122
+ end
32
123
  end
33
124
 
34
125
  def create_table(table_name, **options)
@@ -56,8 +147,13 @@ module ActiveRecord
56
147
  end
57
148
 
58
149
  def add_reference(table_name, ref_name, **options)
59
- ReferenceDefinition.new(ref_name, **options)
60
- .add_to(connection.update_table_definition(table_name, self))
150
+ if connection.adapter_name == "SQLite"
151
+ reference_definition = ReferenceDefinition.new(ref_name, type: :integer, **options)
152
+ else
153
+ reference_definition = ReferenceDefinition.new(ref_name, **options)
154
+ end
155
+
156
+ reference_definition.add_to(connection.update_table_definition(table_name, self))
61
157
  end
62
158
  alias :add_belongs_to :add_reference
63
159
 
@@ -65,6 +161,7 @@ module ActiveRecord
65
161
  def compatible_table_definition(t)
66
162
  class << t
67
163
  prepend TableDefinition
164
+ prepend SQLite3::TableDefinition
68
165
  end
69
166
  t
70
167
  end
@@ -76,6 +173,11 @@ module ActiveRecord
76
173
  options[:precision] ||= nil
77
174
  super
78
175
  end
176
+
177
+ def column(name, type, index: nil, **options)
178
+ options[:precision] ||= nil
179
+ super
180
+ end
79
181
  end
80
182
 
81
183
  module CommandRecorder
@@ -204,6 +306,8 @@ module ActiveRecord
204
306
  if type == :primary_key
205
307
  type = :integer
206
308
  options[:primary_key] = true
309
+ elsif type == :datetime
310
+ options[:precision] ||= nil
207
311
  end
208
312
  super
209
313
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module ActiveRecord
4
4
  class Migration
5
- module JoinTable #:nodoc:
5
+ module JoinTable # :nodoc:
6
6
  private
7
7
  def find_join_table_name(table_1, table_2, options = {})
8
8
  options.delete(:table_name) || join_table_name(table_1, table_2)