activerecord 6.0.0 → 6.1.3

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 (270) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +1045 -575
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  5. data/lib/active_record.rb +7 -13
  6. data/lib/active_record/aggregations.rb +5 -6
  7. data/lib/active_record/association_relation.rb +30 -10
  8. data/lib/active_record/associations.rb +120 -13
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +49 -29
  11. data/lib/active_record/associations/association_scope.rb +19 -15
  12. data/lib/active_record/associations/belongs_to_association.rb +22 -8
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -3
  14. data/lib/active_record/associations/builder/association.rb +32 -5
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -7
  16. data/lib/active_record/associations/builder/collection_association.rb +5 -4
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +0 -3
  18. data/lib/active_record/associations/builder/has_many.rb +6 -2
  19. data/lib/active_record/associations/builder/has_one.rb +11 -14
  20. data/lib/active_record/associations/builder/singular_association.rb +1 -1
  21. data/lib/active_record/associations/collection_association.rb +25 -8
  22. data/lib/active_record/associations/collection_proxy.rb +14 -7
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +24 -3
  25. data/lib/active_record/associations/has_many_through_association.rb +10 -4
  26. data/lib/active_record/associations/has_one_association.rb +15 -1
  27. data/lib/active_record/associations/join_dependency.rb +77 -42
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -16
  29. data/lib/active_record/associations/join_dependency/join_part.rb +3 -3
  30. data/lib/active_record/associations/preloader.rb +13 -8
  31. data/lib/active_record/associations/preloader/association.rb +51 -25
  32. data/lib/active_record/associations/preloader/through_association.rb +2 -2
  33. data/lib/active_record/associations/singular_association.rb +1 -1
  34. data/lib/active_record/associations/through_association.rb +1 -1
  35. data/lib/active_record/attribute_assignment.rb +10 -9
  36. data/lib/active_record/attribute_methods.rb +64 -54
  37. data/lib/active_record/attribute_methods/before_type_cast.rb +13 -10
  38. data/lib/active_record/attribute_methods/dirty.rb +3 -13
  39. data/lib/active_record/attribute_methods/primary_key.rb +6 -4
  40. data/lib/active_record/attribute_methods/query.rb +3 -6
  41. data/lib/active_record/attribute_methods/read.rb +8 -12
  42. data/lib/active_record/attribute_methods/serialization.rb +11 -6
  43. data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
  44. data/lib/active_record/attribute_methods/write.rb +12 -21
  45. data/lib/active_record/attributes.rb +33 -9
  46. data/lib/active_record/autosave_association.rb +63 -44
  47. data/lib/active_record/base.rb +2 -14
  48. data/lib/active_record/callbacks.rb +153 -24
  49. data/lib/active_record/coders/yaml_column.rb +1 -2
  50. data/lib/active_record/connection_adapters.rb +50 -0
  51. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +202 -138
  52. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -44
  53. data/lib/active_record/connection_adapters/abstract/database_statements.rb +87 -38
  54. data/lib/active_record/connection_adapters/abstract/query_cache.rb +5 -10
  55. data/lib/active_record/connection_adapters/abstract/quoting.rb +34 -34
  56. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  57. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +152 -116
  58. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +141 -52
  59. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +3 -3
  60. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +267 -105
  61. data/lib/active_record/connection_adapters/abstract/transaction.rb +82 -35
  62. data/lib/active_record/connection_adapters/abstract_adapter.rb +74 -77
  63. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -115
  64. data/lib/active_record/connection_adapters/column.rb +15 -1
  65. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  66. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +31 -0
  67. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  68. data/lib/active_record/connection_adapters/mysql/database_statements.rb +30 -36
  69. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
  70. data/lib/active_record/connection_adapters/mysql/quoting.rb +18 -3
  71. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +32 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +8 -0
  73. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +5 -2
  74. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +17 -13
  75. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +10 -1
  76. data/lib/active_record/connection_adapters/mysql2_adapter.rb +31 -13
  77. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  78. data/lib/active_record/connection_adapters/pool_manager.rb +43 -0
  79. data/lib/active_record/connection_adapters/postgresql/column.rb +24 -1
  80. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +21 -56
  81. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
  82. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +0 -1
  83. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
  84. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +0 -1
  88. data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +24 -6
  95. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  96. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +11 -2
  97. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
  99. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +7 -3
  100. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +1 -1
  101. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  102. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +72 -54
  103. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +8 -0
  104. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  105. data/lib/active_record/connection_adapters/postgresql_adapter.rb +83 -65
  106. data/lib/active_record/connection_adapters/schema_cache.rb +98 -15
  107. data/lib/active_record/connection_adapters/sql_type_metadata.rb +10 -0
  108. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +38 -12
  109. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +1 -2
  110. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
  111. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +38 -5
  112. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +61 -57
  113. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  114. data/lib/active_record/connection_handling.rb +219 -81
  115. data/lib/active_record/core.rb +253 -67
  116. data/lib/active_record/counter_cache.rb +4 -1
  117. data/lib/active_record/database_configurations.rb +124 -85
  118. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  119. data/lib/active_record/database_configurations/database_config.rb +52 -9
  120. data/lib/active_record/database_configurations/hash_config.rb +54 -8
  121. data/lib/active_record/database_configurations/url_config.rb +15 -41
  122. data/lib/active_record/delegated_type.rb +209 -0
  123. data/lib/active_record/destroy_association_async_job.rb +36 -0
  124. data/lib/active_record/dynamic_matchers.rb +2 -3
  125. data/lib/active_record/enum.rb +82 -38
  126. data/lib/active_record/errors.rb +47 -12
  127. data/lib/active_record/explain.rb +9 -5
  128. data/lib/active_record/explain_subscriber.rb +1 -1
  129. data/lib/active_record/fixture_set/file.rb +10 -17
  130. data/lib/active_record/fixture_set/model_metadata.rb +1 -2
  131. data/lib/active_record/fixture_set/render_context.rb +1 -1
  132. data/lib/active_record/fixture_set/table_row.rb +2 -3
  133. data/lib/active_record/fixture_set/table_rows.rb +0 -1
  134. data/lib/active_record/fixtures.rb +58 -12
  135. data/lib/active_record/gem_version.rb +2 -2
  136. data/lib/active_record/inheritance.rb +40 -21
  137. data/lib/active_record/insert_all.rb +39 -10
  138. data/lib/active_record/integration.rb +3 -5
  139. data/lib/active_record/internal_metadata.rb +16 -7
  140. data/lib/active_record/legacy_yaml_adapter.rb +7 -3
  141. data/lib/active_record/locking/optimistic.rb +33 -18
  142. data/lib/active_record/locking/pessimistic.rb +6 -2
  143. data/lib/active_record/log_subscriber.rb +28 -9
  144. data/lib/active_record/middleware/database_selector.rb +4 -2
  145. data/lib/active_record/middleware/database_selector/resolver.rb +14 -14
  146. data/lib/active_record/middleware/database_selector/resolver/session.rb +3 -0
  147. data/lib/active_record/migration.rb +115 -85
  148. data/lib/active_record/migration/command_recorder.rb +53 -45
  149. data/lib/active_record/migration/compatibility.rb +71 -20
  150. data/lib/active_record/migration/join_table.rb +0 -1
  151. data/lib/active_record/model_schema.rb +120 -15
  152. data/lib/active_record/nested_attributes.rb +2 -5
  153. data/lib/active_record/no_touching.rb +1 -1
  154. data/lib/active_record/null_relation.rb +0 -1
  155. data/lib/active_record/persistence.rb +50 -46
  156. data/lib/active_record/query_cache.rb +15 -5
  157. data/lib/active_record/querying.rb +12 -7
  158. data/lib/active_record/railtie.rb +65 -45
  159. data/lib/active_record/railties/console_sandbox.rb +2 -4
  160. data/lib/active_record/railties/databases.rake +277 -97
  161. data/lib/active_record/readonly_attributes.rb +4 -0
  162. data/lib/active_record/reflection.rb +77 -63
  163. data/lib/active_record/relation.rb +107 -67
  164. data/lib/active_record/relation/batches.rb +38 -32
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
  166. data/lib/active_record/relation/calculations.rb +102 -45
  167. data/lib/active_record/relation/delegation.rb +9 -7
  168. data/lib/active_record/relation/finder_methods.rb +55 -17
  169. data/lib/active_record/relation/from_clause.rb +5 -1
  170. data/lib/active_record/relation/merger.rb +27 -26
  171. data/lib/active_record/relation/predicate_builder.rb +59 -40
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +8 -9
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +4 -5
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +10 -6
  175. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  176. data/lib/active_record/relation/query_methods.rb +343 -180
  177. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  178. data/lib/active_record/relation/spawn_methods.rb +8 -8
  179. data/lib/active_record/relation/where_clause.rb +107 -61
  180. data/lib/active_record/result.rb +41 -34
  181. data/lib/active_record/runtime_registry.rb +2 -2
  182. data/lib/active_record/sanitization.rb +6 -17
  183. data/lib/active_record/schema_dumper.rb +34 -4
  184. data/lib/active_record/schema_migration.rb +2 -8
  185. data/lib/active_record/scoping.rb +0 -1
  186. data/lib/active_record/scoping/default.rb +0 -1
  187. data/lib/active_record/scoping/named.rb +7 -18
  188. data/lib/active_record/secure_token.rb +16 -8
  189. data/lib/active_record/serialization.rb +5 -3
  190. data/lib/active_record/signed_id.rb +116 -0
  191. data/lib/active_record/statement_cache.rb +20 -4
  192. data/lib/active_record/store.rb +3 -3
  193. data/lib/active_record/suppressor.rb +2 -2
  194. data/lib/active_record/table_metadata.rb +42 -36
  195. data/lib/active_record/tasks/database_tasks.rb +140 -113
  196. data/lib/active_record/tasks/mysql_database_tasks.rb +34 -36
  197. data/lib/active_record/tasks/postgresql_database_tasks.rb +24 -27
  198. data/lib/active_record/tasks/sqlite_database_tasks.rb +13 -10
  199. data/lib/active_record/test_databases.rb +5 -4
  200. data/lib/active_record/test_fixtures.rb +38 -16
  201. data/lib/active_record/timestamp.rb +4 -7
  202. data/lib/active_record/touch_later.rb +20 -21
  203. data/lib/active_record/transactions.rb +26 -73
  204. data/lib/active_record/type.rb +8 -2
  205. data/lib/active_record/type/adapter_specific_registry.rb +2 -5
  206. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  207. data/lib/active_record/type/serialized.rb +6 -3
  208. data/lib/active_record/type/time.rb +10 -0
  209. data/lib/active_record/type/type_map.rb +0 -1
  210. data/lib/active_record/type/unsigned_integer.rb +0 -1
  211. data/lib/active_record/type_caster/connection.rb +0 -1
  212. data/lib/active_record/type_caster/map.rb +8 -5
  213. data/lib/active_record/validations.rb +3 -3
  214. data/lib/active_record/validations/associated.rb +1 -2
  215. data/lib/active_record/validations/numericality.rb +35 -0
  216. data/lib/active_record/validations/uniqueness.rb +24 -4
  217. data/lib/arel.rb +15 -12
  218. data/lib/arel/attributes/attribute.rb +4 -0
  219. data/lib/arel/collectors/bind.rb +5 -0
  220. data/lib/arel/collectors/composite.rb +8 -0
  221. data/lib/arel/collectors/sql_string.rb +7 -0
  222. data/lib/arel/collectors/substitute_binds.rb +7 -0
  223. data/lib/arel/nodes.rb +3 -1
  224. data/lib/arel/nodes/binary.rb +82 -8
  225. data/lib/arel/nodes/bind_param.rb +8 -0
  226. data/lib/arel/nodes/casted.rb +21 -9
  227. data/lib/arel/nodes/equality.rb +6 -9
  228. data/lib/arel/nodes/grouping.rb +3 -0
  229. data/lib/arel/nodes/homogeneous_in.rb +72 -0
  230. data/lib/arel/nodes/in.rb +8 -1
  231. data/lib/arel/nodes/infix_operation.rb +13 -1
  232. data/lib/arel/nodes/join_source.rb +1 -1
  233. data/lib/arel/nodes/node.rb +7 -6
  234. data/lib/arel/nodes/ordering.rb +27 -0
  235. data/lib/arel/nodes/sql_literal.rb +3 -0
  236. data/lib/arel/nodes/table_alias.rb +7 -3
  237. data/lib/arel/nodes/unary.rb +0 -1
  238. data/lib/arel/predications.rb +17 -24
  239. data/lib/arel/select_manager.rb +1 -2
  240. data/lib/arel/table.rb +13 -5
  241. data/lib/arel/visitors.rb +0 -7
  242. data/lib/arel/visitors/dot.rb +14 -3
  243. data/lib/arel/visitors/mysql.rb +11 -1
  244. data/lib/arel/visitors/postgresql.rb +15 -5
  245. data/lib/arel/visitors/sqlite.rb +0 -1
  246. data/lib/arel/visitors/to_sql.rb +89 -79
  247. data/lib/arel/visitors/visitor.rb +0 -1
  248. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  249. data/lib/rails/generators/active_record/migration.rb +6 -2
  250. data/lib/rails/generators/active_record/migration/migration_generator.rb +1 -0
  251. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +2 -0
  252. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -4
  253. data/lib/rails/generators/active_record/model/model_generator.rb +38 -2
  254. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  255. metadata +30 -27
  256. data/lib/active_record/attribute_decorators.rb +0 -90
  257. data/lib/active_record/connection_adapters/connection_specification.rb +0 -297
  258. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -29
  259. data/lib/active_record/define_callbacks.rb +0 -22
  260. data/lib/active_record/railties/collection_cache_association_loading.rb +0 -34
  261. data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -18
  262. data/lib/active_record/relation/where_clause_factory.rb +0 -33
  263. data/lib/arel/attributes.rb +0 -22
  264. data/lib/arel/visitors/depth_first.rb +0 -204
  265. data/lib/arel/visitors/ibm_db.rb +0 -34
  266. data/lib/arel/visitors/informix.rb +0 -62
  267. data/lib/arel/visitors/mssql.rb +0 -157
  268. data/lib/arel/visitors/oracle.rb +0 -159
  269. data/lib/arel/visitors/oracle12.rb +0 -66
  270. data/lib/arel/visitors/where_sql.rb +0 -23
@@ -7,30 +7,29 @@ module ActiveRecord
7
7
 
8
8
  delegate :connection, :establish_connection, to: ActiveRecord::Base
9
9
 
10
- def initialize(configuration)
11
- @configuration = configuration
10
+ def self.using_database_configurations?
11
+ true
12
+ end
13
+
14
+ def initialize(db_config)
15
+ @db_config = db_config
16
+ @configuration_hash = db_config.configuration_hash
12
17
  end
13
18
 
14
19
  def create
15
- establish_connection configuration_without_database
16
- connection.create_database configuration["database"], creation_options
17
- establish_connection configuration
18
- rescue ActiveRecord::StatementInvalid => error
19
- if connection.error_number(error.cause) == ER_DB_CREATE_EXISTS
20
- raise DatabaseAlreadyExists
21
- else
22
- raise
23
- end
20
+ establish_connection(configuration_hash_without_database)
21
+ connection.create_database(db_config.database, creation_options)
22
+ establish_connection(db_config)
24
23
  end
25
24
 
26
25
  def drop
27
- establish_connection configuration
28
- connection.drop_database configuration["database"]
26
+ establish_connection(db_config)
27
+ connection.drop_database(db_config.database)
29
28
  end
30
29
 
31
30
  def purge
32
- establish_connection configuration
33
- connection.recreate_database configuration["database"], creation_options
31
+ establish_connection(db_config)
32
+ connection.recreate_database(db_config.database, creation_options)
34
33
  end
35
34
 
36
35
  def charset
@@ -50,10 +49,10 @@ module ActiveRecord
50
49
 
51
50
  ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
52
51
  if ignore_tables.any?
53
- args += ignore_tables.map { |table| "--ignore-table=#{configuration['database']}.#{table}" }
52
+ args += ignore_tables.map { |table| "--ignore-table=#{db_config.database}.#{table}" }
54
53
  end
55
54
 
56
- args.concat(["#{configuration['database']}"])
55
+ args.concat([db_config.database.to_s])
57
56
  args.unshift(*extra_flags) if extra_flags
58
57
 
59
58
  run_cmd("mysqldump", args, "dumping")
@@ -62,41 +61,40 @@ module ActiveRecord
62
61
  def structure_load(filename, extra_flags)
63
62
  args = prepare_command_options
64
63
  args.concat(["--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}])
65
- args.concat(["--database", "#{configuration['database']}"])
64
+ args.concat(["--database", db_config.database.to_s])
66
65
  args.unshift(*extra_flags) if extra_flags
67
66
 
68
67
  run_cmd("mysql", args, "loading")
69
68
  end
70
69
 
71
70
  private
71
+ attr_reader :db_config, :configuration_hash
72
72
 
73
- attr_reader :configuration
74
-
75
- def configuration_without_database
76
- configuration.merge("database" => nil)
73
+ def configuration_hash_without_database
74
+ configuration_hash.merge(database: nil)
77
75
  end
78
76
 
79
77
  def creation_options
80
78
  Hash.new.tap do |options|
81
- options[:charset] = configuration["encoding"] if configuration.include? "encoding"
82
- options[:collation] = configuration["collation"] if configuration.include? "collation"
79
+ options[:charset] = configuration_hash[:encoding] if configuration_hash.include?(:encoding)
80
+ options[:collation] = configuration_hash[:collation] if configuration_hash.include?(:collation)
83
81
  end
84
82
  end
85
83
 
86
84
  def prepare_command_options
87
85
  args = {
88
- "host" => "--host",
89
- "port" => "--port",
90
- "socket" => "--socket",
91
- "username" => "--user",
92
- "password" => "--password",
93
- "encoding" => "--default-character-set",
94
- "sslca" => "--ssl-ca",
95
- "sslcert" => "--ssl-cert",
96
- "sslcapath" => "--ssl-capath",
97
- "sslcipher" => "--ssl-cipher",
98
- "sslkey" => "--ssl-key"
99
- }.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
86
+ host: "--host",
87
+ port: "--port",
88
+ socket: "--socket",
89
+ username: "--user",
90
+ password: "--password",
91
+ encoding: "--default-character-set",
92
+ sslca: "--ssl-ca",
93
+ sslcert: "--ssl-cert",
94
+ sslcapath: "--ssl-capath",
95
+ sslcipher: "--ssl-cipher",
96
+ sslkey: "--ssl-key"
97
+ }.map { |opt, arg| "#{arg}=#{configuration_hash[opt]}" if configuration_hash[opt] }.compact
100
98
 
101
99
  args
102
100
  end
@@ -12,26 +12,24 @@ module ActiveRecord
12
12
  delegate :connection, :establish_connection, :clear_active_connections!,
13
13
  to: ActiveRecord::Base
14
14
 
15
- def initialize(configuration)
16
- @configuration = configuration
15
+ def self.using_database_configurations?
16
+ true
17
+ end
18
+
19
+ def initialize(db_config)
20
+ @db_config = db_config
21
+ @configuration_hash = db_config.configuration_hash
17
22
  end
18
23
 
19
24
  def create(master_established = false)
20
25
  establish_master_connection unless master_established
21
- connection.create_database configuration["database"],
22
- configuration.merge("encoding" => encoding)
23
- establish_connection configuration
24
- rescue ActiveRecord::StatementInvalid => error
25
- if error.cause.is_a?(PG::DuplicateDatabase)
26
- raise DatabaseAlreadyExists
27
- else
28
- raise
29
- end
26
+ connection.create_database(db_config.database, configuration_hash.merge(encoding: encoding))
27
+ establish_connection(db_config)
30
28
  end
31
29
 
32
30
  def drop
33
31
  establish_master_connection
34
- connection.drop_database configuration["database"]
32
+ connection.drop_database(db_config.database)
35
33
  end
36
34
 
37
35
  def charset
@@ -54,14 +52,14 @@ module ActiveRecord
54
52
  search_path = \
55
53
  case ActiveRecord::Base.dump_schemas
56
54
  when :schema_search_path
57
- configuration["schema_search_path"]
55
+ configuration_hash[:schema_search_path]
58
56
  when :all
59
57
  nil
60
58
  when String
61
59
  ActiveRecord::Base.dump_schemas
62
60
  end
63
61
 
64
- args = ["-s", "-x", "-O", "-f", filename]
62
+ args = ["--schema-only", "--no-privileges", "--no-owner", "--file", filename]
65
63
  args.concat(Array(extra_flags)) if extra_flags
66
64
  unless search_path.blank?
67
65
  args += search_path.split(",").map do |part|
@@ -74,7 +72,7 @@ module ActiveRecord
74
72
  args += ignore_tables.flat_map { |table| ["-T", table] }
75
73
  end
76
74
 
77
- args << configuration["database"]
75
+ args << db_config.database
78
76
  run_cmd("pg_dump", args, "dumping")
79
77
  remove_sql_header_comments(filename)
80
78
  File.open(filename, "a") { |f| f << "SET search_path TO #{connection.schema_search_path};\n\n" }
@@ -82,32 +80,31 @@ module ActiveRecord
82
80
 
83
81
  def structure_load(filename, extra_flags)
84
82
  set_psql_env
85
- args = ["-v", ON_ERROR_STOP_1, "-q", "-X", "-f", filename]
83
+ args = ["--set", ON_ERROR_STOP_1, "--quiet", "--no-psqlrc", "--file", filename]
86
84
  args.concat(Array(extra_flags)) if extra_flags
87
- args << configuration["database"]
85
+ args << db_config.database
88
86
  run_cmd("psql", args, "loading")
89
87
  end
90
88
 
91
89
  private
92
-
93
- attr_reader :configuration
90
+ attr_reader :db_config, :configuration_hash
94
91
 
95
92
  def encoding
96
- configuration["encoding"] || DEFAULT_ENCODING
93
+ configuration_hash[:encoding] || DEFAULT_ENCODING
97
94
  end
98
95
 
99
96
  def establish_master_connection
100
- establish_connection configuration.merge(
101
- "database" => "postgres",
102
- "schema_search_path" => "public"
97
+ establish_connection configuration_hash.merge(
98
+ database: "postgres",
99
+ schema_search_path: "public"
103
100
  )
104
101
  end
105
102
 
106
103
  def set_psql_env
107
- ENV["PGHOST"] = configuration["host"] if configuration["host"]
108
- ENV["PGPORT"] = configuration["port"].to_s if configuration["port"]
109
- ENV["PGPASSWORD"] = configuration["password"].to_s if configuration["password"]
110
- ENV["PGUSER"] = configuration["username"].to_s if configuration["username"]
104
+ ENV["PGHOST"] = db_config.host if db_config.host
105
+ ENV["PGPORT"] = configuration_hash[:port].to_s if configuration_hash[:port]
106
+ ENV["PGPASSWORD"] = configuration_hash[:password].to_s if configuration_hash[:password]
107
+ ENV["PGUSER"] = configuration_hash[:username].to_s if configuration_hash[:username]
111
108
  end
112
109
 
113
110
  def run_cmd(cmd, args, action)
@@ -5,20 +5,25 @@ module ActiveRecord
5
5
  class SQLiteDatabaseTasks # :nodoc:
6
6
  delegate :connection, :establish_connection, to: ActiveRecord::Base
7
7
 
8
- def initialize(configuration, root = ActiveRecord::Tasks::DatabaseTasks.root)
9
- @configuration, @root = configuration, root
8
+ def self.using_database_configurations?
9
+ true
10
+ end
11
+
12
+ def initialize(db_config, root = ActiveRecord::Tasks::DatabaseTasks.root)
13
+ @db_config = db_config
14
+ @root = root
10
15
  end
11
16
 
12
17
  def create
13
- raise DatabaseAlreadyExists if File.exist?(configuration["database"])
18
+ raise DatabaseAlreadyExists if File.exist?(db_config.database)
14
19
 
15
- establish_connection configuration
20
+ establish_connection(db_config)
16
21
  connection
17
22
  end
18
23
 
19
24
  def drop
20
25
  require "pathname"
21
- path = Pathname.new configuration["database"]
26
+ path = Pathname.new(db_config.database)
22
27
  file = path.absolute? ? path.to_s : File.join(root, path)
23
28
 
24
29
  FileUtils.rm(file)
@@ -40,7 +45,7 @@ module ActiveRecord
40
45
  def structure_dump(filename, extra_flags)
41
46
  args = []
42
47
  args.concat(Array(extra_flags)) if extra_flags
43
- args << configuration["database"]
48
+ args << db_config.database
44
49
 
45
50
  ignore_tables = ActiveRecord::SchemaDumper.ignore_tables
46
51
  if ignore_tables.any?
@@ -53,14 +58,12 @@ module ActiveRecord
53
58
  end
54
59
 
55
60
  def structure_load(filename, extra_flags)
56
- dbfile = configuration["database"]
57
61
  flags = extra_flags.join(" ") if extra_flags
58
- `sqlite3 #{flags} #{dbfile} < "#{filename}"`
62
+ `sqlite3 #{flags} #{db_config.database} < "#{filename}"`
59
63
  end
60
64
 
61
65
  private
62
-
63
- attr_reader :configuration, :root
66
+ attr_reader :db_config, :root
64
67
 
65
68
  def run_cmd(cmd, args, out)
66
69
  fail run_cmd_error(cmd, args) unless Kernel.system(cmd, *args, out: out)
@@ -5,18 +5,19 @@ require "active_support/testing/parallelization"
5
5
  module ActiveRecord
6
6
  module TestDatabases # :nodoc:
7
7
  ActiveSupport::Testing::Parallelization.after_fork_hook do |i|
8
- create_and_load_schema(i, env_name: Rails.env)
8
+ create_and_load_schema(i, env_name: ActiveRecord::ConnectionHandling::DEFAULT_ENV.call)
9
9
  end
10
10
 
11
11
  def self.create_and_load_schema(i, env_name:)
12
12
  old, ENV["VERBOSE"] = ENV["VERBOSE"], "false"
13
13
 
14
14
  ActiveRecord::Base.configurations.configs_for(env_name: env_name).each do |db_config|
15
- db_config.config["database"] += "-#{i}"
16
- ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config.config, ActiveRecord::Base.schema_format, nil, env_name, db_config.spec_name)
15
+ db_config._database = "#{db_config.database}-#{i}"
16
+
17
+ ActiveRecord::Tasks::DatabaseTasks.reconstruct_from_schema(db_config, ActiveRecord::Base.schema_format, nil)
17
18
  end
18
19
  ensure
19
- ActiveRecord::Base.establish_connection(Rails.env.to_sym)
20
+ ActiveRecord::Base.establish_connection
20
21
  ENV["VERBOSE"] = old
21
22
  end
22
23
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require "active_support/core_ext/enumerable"
4
+
3
5
  module ActiveRecord
4
6
  module TestFixtures
5
7
  extend ActiveSupport::Concern
@@ -21,7 +23,6 @@ module ActiveRecord
21
23
  class_attribute :use_transactional_tests, default: true
22
24
  class_attribute :use_instantiated_fixtures, default: false # true, false, or :no_instances
23
25
  class_attribute :pre_loaded_fixtures, default: false
24
- class_attribute :config, default: ActiveRecord::Base
25
26
  class_attribute :lock_threads, default: true
26
27
  end
27
28
 
@@ -41,8 +42,9 @@ module ActiveRecord
41
42
  def fixtures(*fixture_set_names)
42
43
  if fixture_set_names.first == :all
43
44
  raise StandardError, "No fixture path found. Please set `#{self}.fixture_path`." if fixture_path.blank?
44
- fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"].uniq
45
- fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
45
+ fixture_set_names = Dir[::File.join(fixture_path, "{**,*}/*.{yml}")].uniq
46
+ fixture_set_names.reject! { |f| f.start_with?(file_fixture_path.to_s) } if defined?(file_fixture_path) && file_fixture_path
47
+ fixture_set_names.map! { |f| f[fixture_path.to_s.size..-5].delete_prefix("/") }
46
48
  else
47
49
  fixture_set_names = fixture_set_names.flatten.map(&:to_s)
48
50
  end
@@ -97,7 +99,7 @@ module ActiveRecord
97
99
 
98
100
  def run_in_transaction?
99
101
  use_transactional_tests &&
100
- !self.class.uses_transaction?(method_name)
102
+ !self.class.uses_transaction?(name)
101
103
  end
102
104
 
103
105
  def setup_fixtures(config = ActiveRecord::Base)
@@ -129,10 +131,12 @@ module ActiveRecord
129
131
  # When connections are established in the future, begin a transaction too
130
132
  @connection_subscriber = ActiveSupport::Notifications.subscribe("!connection.active_record") do |_, _, _, _, payload|
131
133
  spec_name = payload[:spec_name] if payload.key?(:spec_name)
134
+ shard = payload[:shard] if payload.key?(:shard)
135
+ setup_shared_connection_pool
132
136
 
133
137
  if spec_name
134
138
  begin
135
- connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name)
139
+ connection = ActiveRecord::Base.connection_handler.retrieve_connection(spec_name, shard: shard)
136
140
  rescue ConnectionNotEstablished
137
141
  connection = nil
138
142
  end
@@ -179,7 +183,6 @@ module ActiveRecord
179
183
  end
180
184
 
181
185
  private
182
-
183
186
  # Shares the writing connection pool with connections on
184
187
  # other handlers.
185
188
  #
@@ -187,22 +190,41 @@ module ActiveRecord
187
190
  # need to share a connection pool so that the reading connection
188
191
  # can see data in the open transaction on the writing connection.
189
192
  def setup_shared_connection_pool
190
- writing_handler = ActiveRecord::Base.connection_handler
191
-
192
- ActiveRecord::Base.connection_handlers.values.each do |handler|
193
- if handler != writing_handler
194
- handler.connection_pool_list.each do |pool|
195
- name = pool.spec.name
196
- writing_connection = writing_handler.retrieve_connection_pool(name)
197
- handler.send(:owner_to_pool)[name] = writing_connection
193
+ if ActiveRecord::Base.legacy_connection_handling
194
+ writing_handler = ActiveRecord::Base.connection_handlers[ActiveRecord::Base.writing_role]
195
+
196
+ ActiveRecord::Base.connection_handlers.values.each do |handler|
197
+ if handler != writing_handler
198
+ handler.connection_pool_names.each do |name|
199
+ writing_pool_manager = writing_handler.send(:owner_to_pool_manager)[name]
200
+ return unless writing_pool_manager
201
+
202
+ pool_manager = handler.send(:owner_to_pool_manager)[name]
203
+ pool_manager.shard_names.each do |shard_name|
204
+ writing_pool_config = writing_pool_manager.get_pool_config(nil, shard_name)
205
+ pool_manager.set_pool_config(nil, shard_name, writing_pool_config)
206
+ end
207
+ end
208
+ end
209
+ end
210
+ else
211
+ handler = ActiveRecord::Base.connection_handler
212
+
213
+ handler.connection_pool_names.each do |name|
214
+ pool_manager = handler.send(:owner_to_pool_manager)[name]
215
+ pool_manager.shard_names.each do |shard_name|
216
+ writing_pool_config = pool_manager.get_pool_config(ActiveRecord::Base.writing_role, shard_name)
217
+ pool_manager.role_names.each do |role|
218
+ next unless pool_manager.get_pool_config(role, shard_name)
219
+ pool_manager.set_pool_config(role, shard_name, writing_pool_config)
220
+ end
198
221
  end
199
222
  end
200
223
  end
201
224
  end
202
225
 
203
226
  def load_fixtures(config)
204
- fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
205
- Hash[fixtures.map { |f| [f.name, f] }]
227
+ ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config).index_by(&:name)
206
228
  end
207
229
 
208
230
  def instantiate_fixtures
@@ -80,11 +80,11 @@ module ActiveRecord
80
80
 
81
81
  private
82
82
  def timestamp_attributes_for_create
83
- ["created_at", "created_on"]
83
+ ["created_at", "created_on"].map! { |name| attribute_aliases[name] || name }
84
84
  end
85
85
 
86
86
  def timestamp_attributes_for_update
87
- ["updated_at", "updated_on"]
87
+ ["updated_at", "updated_on"].map! { |name| attribute_aliases[name] || name }
88
88
  end
89
89
 
90
90
  def reload_schema_from_cache
@@ -96,15 +96,12 @@ module ActiveRecord
96
96
  end
97
97
 
98
98
  private
99
-
100
99
  def _create_record
101
100
  if record_timestamps
102
101
  current_time = current_time_from_proper_timezone
103
102
 
104
103
  all_timestamp_attributes_in_model.each do |column|
105
- if !attribute_present?(column)
106
- _write_attribute(column, current_time)
107
- end
104
+ _write_attribute(column, current_time) unless _read_attribute(column)
108
105
  end
109
106
  end
110
107
 
@@ -160,7 +157,7 @@ module ActiveRecord
160
157
  def clear_timestamp_attributes
161
158
  all_timestamp_attributes_in_model.each do |attribute_name|
162
159
  self[attribute_name] = nil
163
- clear_attribute_changes([attribute_name])
160
+ clear_attribute_change(attribute_name)
164
161
  end
165
162
  end
166
163
  end