activerecord 5.2.8.1 → 6.0.0.beta1

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 (242) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +299 -816
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/aggregations.rb +4 -2
  7. data/lib/active_record/associations/association.rb +35 -19
  8. data/lib/active_record/associations/association_scope.rb +4 -6
  9. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  10. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  11. data/lib/active_record/associations/builder/belongs_to.rb +14 -50
  12. data/lib/active_record/associations/builder/collection_association.rb +3 -3
  13. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -38
  14. data/lib/active_record/associations/collection_association.rb +11 -25
  15. data/lib/active_record/associations/collection_proxy.rb +32 -6
  16. data/lib/active_record/associations/foreign_association.rb +7 -0
  17. data/lib/active_record/associations/has_many_association.rb +1 -1
  18. data/lib/active_record/associations/has_many_through_association.rb +25 -18
  19. data/lib/active_record/associations/has_one_association.rb +28 -30
  20. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  21. data/lib/active_record/associations/join_dependency/join_association.rb +11 -26
  22. data/lib/active_record/associations/join_dependency/join_part.rb +2 -2
  23. data/lib/active_record/associations/join_dependency.rb +15 -20
  24. data/lib/active_record/associations/preloader/association.rb +1 -2
  25. data/lib/active_record/associations/preloader.rb +32 -29
  26. data/lib/active_record/associations/singular_association.rb +2 -16
  27. data/lib/active_record/associations.rb +16 -12
  28. data/lib/active_record/attribute_assignment.rb +7 -10
  29. data/lib/active_record/attribute_methods/dirty.rb +64 -26
  30. data/lib/active_record/attribute_methods/primary_key.rb +8 -7
  31. data/lib/active_record/attribute_methods/read.rb +16 -48
  32. data/lib/active_record/attribute_methods/serialization.rb +1 -1
  33. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -1
  34. data/lib/active_record/attribute_methods/write.rb +15 -16
  35. data/lib/active_record/attribute_methods.rb +34 -56
  36. data/lib/active_record/autosave_association.rb +7 -21
  37. data/lib/active_record/base.rb +2 -2
  38. data/lib/active_record/callbacks.rb +3 -17
  39. data/lib/active_record/coders/yaml_column.rb +1 -13
  40. data/lib/active_record/collection_cache_key.rb +1 -1
  41. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +13 -36
  42. data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
  43. data/lib/active_record/connection_adapters/abstract/database_statements.rb +25 -84
  44. data/lib/active_record/connection_adapters/abstract/query_cache.rb +17 -14
  45. data/lib/active_record/connection_adapters/abstract/quoting.rb +5 -11
  46. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -11
  47. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +30 -13
  48. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +0 -2
  49. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -27
  50. data/lib/active_record/connection_adapters/abstract/transaction.rb +81 -52
  51. data/lib/active_record/connection_adapters/abstract_adapter.rb +95 -31
  52. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +65 -90
  53. data/lib/active_record/connection_adapters/connection_specification.rb +52 -42
  54. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +5 -9
  55. data/lib/active_record/connection_adapters/mysql/database_statements.rb +29 -7
  56. data/lib/active_record/connection_adapters/mysql/quoting.rb +1 -1
  57. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +3 -4
  58. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +65 -10
  59. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -4
  60. data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
  61. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +16 -1
  62. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
  63. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  64. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -1
  65. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -1
  66. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  67. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -1
  68. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  69. data/lib/active_record/connection_adapters/postgresql/quoting.rb +4 -4
  70. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +11 -36
  71. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +9 -2
  72. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +38 -20
  73. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -1
  74. data/lib/active_record/connection_adapters/postgresql_adapter.rb +75 -56
  75. data/lib/active_record/connection_adapters/schema_cache.rb +5 -0
  76. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +5 -5
  77. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +14 -9
  78. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +95 -62
  79. data/lib/active_record/connection_handling.rb +132 -26
  80. data/lib/active_record/core.rb +75 -52
  81. data/lib/active_record/counter_cache.rb +4 -29
  82. data/lib/active_record/database_configurations/database_config.rb +37 -0
  83. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  84. data/lib/active_record/database_configurations/url_config.rb +74 -0
  85. data/lib/active_record/database_configurations.rb +184 -0
  86. data/lib/active_record/enum.rb +22 -7
  87. data/lib/active_record/errors.rb +24 -21
  88. data/lib/active_record/explain.rb +1 -1
  89. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  90. data/lib/active_record/fixture_set/render_context.rb +17 -0
  91. data/lib/active_record/fixture_set/table_row.rb +153 -0
  92. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  93. data/lib/active_record/fixtures.rb +140 -472
  94. data/lib/active_record/gem_version.rb +4 -4
  95. data/lib/active_record/inheritance.rb +12 -2
  96. data/lib/active_record/integration.rb +56 -16
  97. data/lib/active_record/internal_metadata.rb +5 -1
  98. data/lib/active_record/locking/optimistic.rb +2 -2
  99. data/lib/active_record/locking/pessimistic.rb +3 -3
  100. data/lib/active_record/log_subscriber.rb +7 -26
  101. data/lib/active_record/migration/command_recorder.rb +35 -5
  102. data/lib/active_record/migration/compatibility.rb +34 -16
  103. data/lib/active_record/migration.rb +38 -37
  104. data/lib/active_record/model_schema.rb +30 -9
  105. data/lib/active_record/nested_attributes.rb +2 -2
  106. data/lib/active_record/no_touching.rb +7 -0
  107. data/lib/active_record/persistence.rb +18 -7
  108. data/lib/active_record/query_cache.rb +11 -4
  109. data/lib/active_record/querying.rb +19 -11
  110. data/lib/active_record/railtie.rb +71 -60
  111. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  112. data/lib/active_record/railties/controller_runtime.rb +30 -35
  113. data/lib/active_record/railties/databases.rake +94 -43
  114. data/lib/active_record/reflection.rb +60 -44
  115. data/lib/active_record/relation/batches.rb +13 -10
  116. data/lib/active_record/relation/calculations.rb +38 -28
  117. data/lib/active_record/relation/delegation.rb +4 -13
  118. data/lib/active_record/relation/finder_methods.rb +12 -25
  119. data/lib/active_record/relation/merger.rb +2 -6
  120. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  121. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  122. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  123. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  124. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  125. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  126. data/lib/active_record/relation/predicate_builder.rb +4 -6
  127. data/lib/active_record/relation/query_attribute.rb +15 -12
  128. data/lib/active_record/relation/query_methods.rb +29 -52
  129. data/lib/active_record/relation/where_clause.rb +4 -0
  130. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  131. data/lib/active_record/relation.rb +150 -69
  132. data/lib/active_record/result.rb +30 -11
  133. data/lib/active_record/sanitization.rb +2 -39
  134. data/lib/active_record/schema.rb +1 -10
  135. data/lib/active_record/schema_dumper.rb +12 -6
  136. data/lib/active_record/schema_migration.rb +4 -0
  137. data/lib/active_record/scoping/default.rb +10 -3
  138. data/lib/active_record/scoping/named.rb +10 -14
  139. data/lib/active_record/scoping.rb +9 -8
  140. data/lib/active_record/statement_cache.rb +32 -5
  141. data/lib/active_record/store.rb +39 -8
  142. data/lib/active_record/table_metadata.rb +1 -4
  143. data/lib/active_record/tasks/database_tasks.rb +89 -23
  144. data/lib/active_record/tasks/mysql_database_tasks.rb +2 -4
  145. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -7
  146. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -8
  147. data/lib/active_record/test_databases.rb +38 -0
  148. data/lib/active_record/test_fixtures.rb +224 -0
  149. data/lib/active_record/timestamp.rb +4 -6
  150. data/lib/active_record/transactions.rb +3 -22
  151. data/lib/active_record/translation.rb +1 -1
  152. data/lib/active_record/type/adapter_specific_registry.rb +1 -8
  153. data/lib/active_record/type.rb +3 -4
  154. data/lib/active_record/type_caster/connection.rb +1 -6
  155. data/lib/active_record/type_caster/map.rb +1 -4
  156. data/lib/active_record/validations/uniqueness.rb +13 -25
  157. data/lib/active_record.rb +2 -1
  158. data/lib/arel/alias_predication.rb +9 -0
  159. data/lib/arel/attributes/attribute.rb +37 -0
  160. data/lib/arel/attributes.rb +22 -0
  161. data/lib/arel/collectors/bind.rb +24 -0
  162. data/lib/arel/collectors/composite.rb +31 -0
  163. data/lib/arel/collectors/plain_string.rb +20 -0
  164. data/lib/arel/collectors/sql_string.rb +20 -0
  165. data/lib/arel/collectors/substitute_binds.rb +28 -0
  166. data/lib/arel/crud.rb +42 -0
  167. data/lib/arel/delete_manager.rb +18 -0
  168. data/lib/arel/errors.rb +9 -0
  169. data/lib/arel/expressions.rb +29 -0
  170. data/lib/arel/factory_methods.rb +49 -0
  171. data/lib/arel/insert_manager.rb +49 -0
  172. data/lib/arel/math.rb +45 -0
  173. data/lib/arel/nodes/and.rb +32 -0
  174. data/lib/arel/nodes/ascending.rb +23 -0
  175. data/lib/arel/nodes/binary.rb +52 -0
  176. data/lib/arel/nodes/bind_param.rb +36 -0
  177. data/lib/arel/nodes/case.rb +55 -0
  178. data/lib/arel/nodes/casted.rb +50 -0
  179. data/lib/arel/nodes/count.rb +12 -0
  180. data/lib/arel/nodes/delete_statement.rb +45 -0
  181. data/lib/arel/nodes/descending.rb +23 -0
  182. data/lib/arel/nodes/equality.rb +18 -0
  183. data/lib/arel/nodes/extract.rb +24 -0
  184. data/lib/arel/nodes/false.rb +16 -0
  185. data/lib/arel/nodes/full_outer_join.rb +8 -0
  186. data/lib/arel/nodes/function.rb +44 -0
  187. data/lib/arel/nodes/grouping.rb +8 -0
  188. data/lib/arel/nodes/in.rb +8 -0
  189. data/lib/arel/nodes/infix_operation.rb +80 -0
  190. data/lib/arel/nodes/inner_join.rb +8 -0
  191. data/lib/arel/nodes/insert_statement.rb +37 -0
  192. data/lib/arel/nodes/join_source.rb +20 -0
  193. data/lib/arel/nodes/matches.rb +18 -0
  194. data/lib/arel/nodes/named_function.rb +23 -0
  195. data/lib/arel/nodes/node.rb +50 -0
  196. data/lib/arel/nodes/node_expression.rb +13 -0
  197. data/lib/arel/nodes/outer_join.rb +8 -0
  198. data/lib/arel/nodes/over.rb +15 -0
  199. data/lib/arel/nodes/regexp.rb +16 -0
  200. data/lib/arel/nodes/right_outer_join.rb +8 -0
  201. data/lib/arel/nodes/select_core.rb +63 -0
  202. data/lib/arel/nodes/select_statement.rb +41 -0
  203. data/lib/arel/nodes/sql_literal.rb +16 -0
  204. data/lib/arel/nodes/string_join.rb +11 -0
  205. data/lib/arel/nodes/table_alias.rb +27 -0
  206. data/lib/arel/nodes/terminal.rb +16 -0
  207. data/lib/arel/nodes/true.rb +16 -0
  208. data/lib/arel/nodes/unary.rb +44 -0
  209. data/lib/arel/nodes/unary_operation.rb +20 -0
  210. data/lib/arel/nodes/unqualified_column.rb +22 -0
  211. data/lib/arel/nodes/update_statement.rb +41 -0
  212. data/lib/arel/nodes/values.rb +16 -0
  213. data/lib/arel/nodes/values_list.rb +24 -0
  214. data/lib/arel/nodes/window.rb +126 -0
  215. data/lib/arel/nodes/with.rb +11 -0
  216. data/lib/arel/nodes.rb +67 -0
  217. data/lib/arel/order_predications.rb +13 -0
  218. data/lib/arel/predications.rb +257 -0
  219. data/lib/arel/select_manager.rb +271 -0
  220. data/lib/arel/table.rb +110 -0
  221. data/lib/arel/tree_manager.rb +72 -0
  222. data/lib/arel/update_manager.rb +34 -0
  223. data/lib/arel/visitors/depth_first.rb +199 -0
  224. data/lib/arel/visitors/dot.rb +292 -0
  225. data/lib/arel/visitors/ibm_db.rb +21 -0
  226. data/lib/arel/visitors/informix.rb +56 -0
  227. data/lib/arel/visitors/mssql.rb +143 -0
  228. data/lib/arel/visitors/mysql.rb +83 -0
  229. data/lib/arel/visitors/oracle.rb +159 -0
  230. data/lib/arel/visitors/oracle12.rb +67 -0
  231. data/lib/arel/visitors/postgresql.rb +116 -0
  232. data/lib/arel/visitors/sqlite.rb +39 -0
  233. data/lib/arel/visitors/to_sql.rb +913 -0
  234. data/lib/arel/visitors/visitor.rb +42 -0
  235. data/lib/arel/visitors/where_sql.rb +23 -0
  236. data/lib/arel/visitors.rb +20 -0
  237. data/lib/arel/window_predications.rb +9 -0
  238. data/lib/arel.rb +44 -0
  239. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  240. data/lib/rails/generators/active_record/migration.rb +14 -1
  241. data/lib/rails/generators/active_record/model/model_generator.rb +1 -0
  242. metadata +107 -29
@@ -22,6 +22,14 @@ db_namespace = namespace :db do
22
22
  task all: :load_config do
23
23
  ActiveRecord::Tasks::DatabaseTasks.create_all
24
24
  end
25
+
26
+ ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
27
+ desc "Create #{spec_name} database for current environment"
28
+ task spec_name => :load_config do
29
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
30
+ ActiveRecord::Tasks::DatabaseTasks.create(db_config.config)
31
+ end
32
+ end
25
33
  end
26
34
 
27
35
  desc "Creates the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:create:all to create all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to creating the development and test databases."
@@ -33,6 +41,14 @@ db_namespace = namespace :db do
33
41
  task all: [:load_config, :check_protected_environments] do
34
42
  ActiveRecord::Tasks::DatabaseTasks.drop_all
35
43
  end
44
+
45
+ ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
46
+ desc "Drop #{spec_name} database for current environment"
47
+ task spec_name => [:load_config, :check_protected_environments] do
48
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
49
+ ActiveRecord::Tasks::DatabaseTasks.drop(db_config.config)
50
+ end
51
+ end
36
52
  end
37
53
 
38
54
  desc "Drops the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:drop:all to drop all databases in the config). Without RAILS_ENV or when RAILS_ENV is development, it defaults to dropping the development and test databases."
@@ -57,7 +73,10 @@ db_namespace = namespace :db do
57
73
 
58
74
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
59
75
  task migrate: :load_config do
60
- ActiveRecord::Tasks::DatabaseTasks.migrate
76
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
77
+ ActiveRecord::Base.establish_connection(db_config.config)
78
+ ActiveRecord::Tasks::DatabaseTasks.migrate
79
+ end
61
80
  db_namespace["_dump"].invoke
62
81
  end
63
82
 
@@ -77,6 +96,15 @@ db_namespace = namespace :db do
77
96
  end
78
97
 
79
98
  namespace :migrate do
99
+ ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
100
+ desc "Migrate #{spec_name} database for current environment"
101
+ task spec_name => :load_config do
102
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
103
+ ActiveRecord::Base.establish_connection(db_config.config)
104
+ ActiveRecord::Tasks::DatabaseTasks.migrate
105
+ end
106
+ end
107
+
80
108
  # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
81
109
  task redo: :load_config do
82
110
  raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
@@ -121,18 +149,21 @@ db_namespace = namespace :db do
121
149
 
122
150
  desc "Display status of migrations"
123
151
  task status: :load_config do
124
- unless ActiveRecord::SchemaMigration.table_exists?
125
- abort "Schema migrations table does not exist yet."
152
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
153
+ ActiveRecord::Base.establish_connection(db_config.config)
154
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
126
155
  end
156
+ end
127
157
 
128
- # output
129
- puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
130
- puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
131
- puts "-" * 50
132
- ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
133
- puts "#{status.center(8)} #{version.ljust(14)} #{name}"
158
+ namespace :status do
159
+ ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name|
160
+ desc "Display status of migrations for #{spec_name} database"
161
+ task spec_name => :load_config do
162
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
163
+ ActiveRecord::Base.establish_connection(db_config.config)
164
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
165
+ end
134
166
  end
135
- puts
136
167
  end
137
168
  end
138
169
 
@@ -160,11 +191,9 @@ db_namespace = namespace :db do
160
191
 
161
192
  # desc "Retrieves the collation for the current environment's database"
162
193
  task collation: :load_config do
163
- begin
164
- puts ActiveRecord::Tasks::DatabaseTasks.collation_current
165
- rescue NoMethodError
166
- $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
167
- end
194
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
195
+ rescue NoMethodError
196
+ $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
168
197
  end
169
198
 
170
199
  desc "Retrieves the current schema version number"
@@ -189,7 +218,7 @@ db_namespace = namespace :db do
189
218
  task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed]
190
219
 
191
220
  desc "Loads the seed data from db/seeds.rb"
192
- task :seed do
221
+ task seed: :load_config do
193
222
  db_namespace["abort_if_pending_migrations"].invoke
194
223
  ActiveRecord::Tasks::DatabaseTasks.load_seed
195
224
  end
@@ -246,10 +275,14 @@ db_namespace = namespace :db do
246
275
  desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
247
276
  task dump: :load_config do
248
277
  require "active_record/schema_dumper"
249
- filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema.rb")
250
- File.open(filename, "w:utf-8") do |file|
251
- ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
278
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
279
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :ruby)
280
+ File.open(filename, "w:utf-8") do |file|
281
+ ActiveRecord::Base.establish_connection(db_config.config)
282
+ ActiveRecord::SchemaDumper.dump(ActiveRecord::Base.connection, file)
283
+ end
252
284
  end
285
+
253
286
  db_namespace["schema:dump"].reenable
254
287
  end
255
288
 
@@ -265,33 +298,41 @@ db_namespace = namespace :db do
265
298
  namespace :cache do
266
299
  desc "Creates a db/schema_cache.yml file."
267
300
  task dump: :load_config do
268
- conn = ActiveRecord::Base.connection
269
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
270
- ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(conn, filename)
301
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
302
+ ActiveRecord::Base.establish_connection(db_config.config)
303
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
304
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
305
+ ActiveRecord::Base.connection,
306
+ filename,
307
+ )
308
+ end
271
309
  end
272
310
 
273
311
  desc "Clears a db/schema_cache.yml file."
274
312
  task clear: :load_config do
275
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
276
- rm_f filename, verbose: false
313
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
314
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
315
+ rm_f filename, verbose: false
316
+ end
277
317
  end
278
318
  end
279
-
280
319
  end
281
320
 
282
321
  namespace :structure do
283
322
  desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
284
323
  task dump: :load_config do
285
- filename = ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "structure.sql")
286
- current_config = ActiveRecord::Tasks::DatabaseTasks.current_config
287
- ActiveRecord::Tasks::DatabaseTasks.structure_dump(current_config, filename)
288
-
289
- if ActiveRecord::SchemaMigration.table_exists?
290
- File.open(filename, "a") do |f|
291
- f.puts ActiveRecord::Base.connection.dump_schema_information
292
- f.print "\n"
324
+ ActiveRecord::Base.configurations.configs_for(env_name: Rails.env).each do |db_config|
325
+ ActiveRecord::Base.establish_connection(db_config.config)
326
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :sql)
327
+ ActiveRecord::Tasks::DatabaseTasks.structure_dump(db_config.config, filename)
328
+ if ActiveRecord::SchemaMigration.table_exists?
329
+ File.open(filename, "a") do |f|
330
+ f.puts ActiveRecord::Base.connection.dump_schema_information
331
+ f.print "\n"
332
+ end
293
333
  end
294
334
  end
335
+
295
336
  db_namespace["structure:dump"].reenable
296
337
  end
297
338
 
@@ -318,25 +359,31 @@ db_namespace = namespace :db do
318
359
 
319
360
  # desc "Recreate the test database from an existent schema.rb file"
320
361
  task load_schema: %w(db:test:purge) do
321
- begin
322
- should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
323
- ActiveRecord::Schema.verbose = false
324
- ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :ruby, ENV["SCHEMA"], "test"
325
- ensure
326
- if should_reconnect
327
- ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations[ActiveRecord::Tasks::DatabaseTasks.env])
328
- end
362
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
363
+ ActiveRecord::Schema.verbose = false
364
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
365
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :ruby)
366
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, :ruby, filename, "test")
367
+ end
368
+ ensure
369
+ if should_reconnect
370
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.default_hash(ActiveRecord::Tasks::DatabaseTasks.env))
329
371
  end
330
372
  end
331
373
 
332
374
  # desc "Recreate the test database from an existent structure.sql file"
333
375
  task load_structure: %w(db:test:purge) do
334
- ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :sql, ENV["SCHEMA"], "test"
376
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
377
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :sql)
378
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, :sql, filename, "test")
379
+ end
335
380
  end
336
381
 
337
382
  # desc "Empty the test database"
338
383
  task purge: %w(load_config check_protected_environments) do
339
- ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations["test"]
384
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
385
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config.config)
386
+ end
340
387
  end
341
388
 
342
389
  # desc 'Load the test schema'
@@ -360,6 +407,10 @@ namespace :railties do
360
407
  if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first)
361
408
  railties[railtie.railtie_name] = path
362
409
  end
410
+
411
+ unless ENV["MIGRATIONS_PATH"].blank?
412
+ railties[railtie.railtie_name] = railtie.root + ENV["MIGRATIONS_PATH"]
413
+ end
363
414
  end
364
415
 
365
416
  on_skip = Proc.new do |name, migration|
@@ -13,33 +13,37 @@ module ActiveRecord
13
13
  class_attribute :aggregate_reflections, instance_writer: false, default: {}
14
14
  end
15
15
 
16
- def self.create(macro, name, scope, options, ar)
17
- klass = \
18
- case macro
19
- when :composed_of
20
- AggregateReflection
21
- when :has_many
22
- HasManyReflection
23
- when :has_one
24
- HasOneReflection
25
- when :belongs_to
26
- BelongsToReflection
27
- else
28
- raise "Unsupported Macro: #{macro}"
29
- end
16
+ class << self
17
+ def create(macro, name, scope, options, ar)
18
+ reflection = reflection_class_for(macro).new(name, scope, options, ar)
19
+ options[:through] ? ThroughReflection.new(reflection) : reflection
20
+ end
30
21
 
31
- reflection = klass.new(name, scope, options, ar)
32
- options[:through] ? ThroughReflection.new(reflection) : reflection
33
- end
22
+ def add_reflection(ar, name, reflection)
23
+ ar.clear_reflections_cache
24
+ name = name.to_s
25
+ ar._reflections = ar._reflections.except(name).merge!(name => reflection)
26
+ end
34
27
 
35
- def self.add_reflection(ar, name, reflection)
36
- ar.clear_reflections_cache
37
- name = name.to_s
38
- ar._reflections = ar._reflections.except(name).merge!(name => reflection)
39
- end
28
+ def add_aggregate_reflection(ar, name, reflection)
29
+ ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
30
+ end
40
31
 
41
- def self.add_aggregate_reflection(ar, name, reflection)
42
- ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
32
+ private
33
+ def reflection_class_for(macro)
34
+ case macro
35
+ when :composed_of
36
+ AggregateReflection
37
+ when :has_many
38
+ HasManyReflection
39
+ when :has_one
40
+ HasOneReflection
41
+ when :belongs_to
42
+ BelongsToReflection
43
+ else
44
+ raise "Unsupported Macro: #{macro}"
45
+ end
46
+ end
43
47
  end
44
48
 
45
49
  # \Reflection enables the ability to examine the associations and aggregations of
@@ -174,22 +178,26 @@ module ActiveRecord
174
178
  scope ? [scope] : []
175
179
  end
176
180
 
177
- def join_scope(table, foreign_table, foreign_klass)
178
- predicate_builder = predicate_builder(table)
179
- scope_chain_items = join_scopes(table, predicate_builder)
180
- klass_scope = klass_join_scope(table, predicate_builder)
181
-
181
+ def build_join_constraint(table, foreign_table)
182
182
  key = join_keys.key
183
183
  foreign_key = join_keys.foreign_key
184
184
 
185
- klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
185
+ constraint = table[key].eq(foreign_table[foreign_key])
186
186
 
187
- if type
188
- klass_scope.where!(type => foreign_klass.polymorphic_name)
187
+ if klass.finder_needs_type_condition?
188
+ table.create_and([constraint, klass.send(:type_condition, table)])
189
+ else
190
+ constraint
189
191
  end
192
+ end
190
193
 
191
- if klass.finder_needs_type_condition?
192
- klass_scope.where!(klass.send(:type_condition, table))
194
+ def join_scope(table, foreign_klass)
195
+ predicate_builder = predicate_builder(table)
196
+ scope_chain_items = join_scopes(table, predicate_builder)
197
+ klass_scope = klass_join_scope(table, predicate_builder)
198
+
199
+ if type
200
+ klass_scope.where!(type => foreign_klass.polymorphic_name)
193
201
  end
194
202
 
195
203
  scope_chain_items.inject(klass_scope, &:merge!)
@@ -413,7 +421,7 @@ module ActiveRecord
413
421
  class AssociationReflection < MacroReflection #:nodoc:
414
422
  def compute_class(name)
415
423
  if polymorphic?
416
- raise ArgumentError, "Polymorphic association does not support to compute class."
424
+ raise ArgumentError, "Polymorphic associations do not support computing the class."
417
425
  end
418
426
  active_record.send(:compute_type, name)
419
427
  end
@@ -604,9 +612,21 @@ module ActiveRecord
604
612
 
605
613
  # returns either +nil+ or the inverse association name that it finds.
606
614
  def automatic_inverse_of
607
- if can_find_inverse_of_automatically?(self)
608
- inverse_name = ActiveSupport::Inflector.underscore(options[:as] || active_record.name.demodulize).to_sym
615
+ return unless can_find_inverse_of_automatically?(self)
616
+
617
+ inverse_name_candidates =
618
+ if options[:as]
619
+ [options[:as]]
620
+ else
621
+ active_record_name = active_record.name.demodulize
622
+ [active_record_name, ActiveSupport::Inflector.pluralize(active_record_name)]
623
+ end
609
624
 
625
+ inverse_name_candidates.map! do |candidate|
626
+ ActiveSupport::Inflector.underscore(candidate).to_sym
627
+ end
628
+
629
+ inverse_name_candidates.detect do |inverse_name|
610
630
  begin
611
631
  reflection = klass._reflect_on_association(inverse_name)
612
632
  rescue NameError
@@ -615,9 +635,7 @@ module ActiveRecord
615
635
  reflection = false
616
636
  end
617
637
 
618
- if valid_inverse_reflection?(reflection)
619
- return inverse_name
620
- end
638
+ valid_inverse_reflection?(reflection)
621
639
  end
622
640
  end
623
641
 
@@ -961,16 +979,14 @@ module ActiveRecord
961
979
  collect_join_reflections(seed + [self])
962
980
  end
963
981
 
964
- # TODO Change this to private once we've dropped Ruby 2.2 support.
965
- # Workaround for Ruby 2.2 "private attribute?" warning.
966
982
  protected
967
- attr_reader :delegate_reflection
968
-
969
983
  def actual_source_reflection # FIXME: this is a horrible name
970
984
  source_reflection.actual_source_reflection
971
985
  end
972
986
 
973
987
  private
988
+ attr_reader :delegate_reflection
989
+
974
990
  def collect_join_reflections(seed)
975
991
  a = source_reflection.add_as_source seed
976
992
  if options[:source_type]
@@ -251,25 +251,28 @@ module ActiveRecord
251
251
  end
252
252
  end
253
253
 
254
- attr = Relation::QueryAttribute.new(primary_key, primary_key_offset, klass.type_for_attribute(primary_key))
255
- batch_relation = relation.where(arel_attribute(primary_key).gt(Arel::Nodes::BindParam.new(attr)))
254
+ batch_relation = relation.where(
255
+ bind_attribute(primary_key, primary_key_offset) { |attr, bind| attr.gt(bind) }
256
+ )
256
257
  end
257
258
  end
258
259
 
259
260
  private
260
261
 
261
262
  def apply_limits(relation, start, finish)
262
- if start
263
- attr = Relation::QueryAttribute.new(primary_key, start, klass.type_for_attribute(primary_key))
264
- relation = relation.where(arel_attribute(primary_key).gteq(Arel::Nodes::BindParam.new(attr)))
265
- end
266
- if finish
267
- attr = Relation::QueryAttribute.new(primary_key, finish, klass.type_for_attribute(primary_key))
268
- relation = relation.where(arel_attribute(primary_key).lteq(Arel::Nodes::BindParam.new(attr)))
269
- end
263
+ relation = apply_start_limit(relation, start) if start
264
+ relation = apply_finish_limit(relation, finish) if finish
270
265
  relation
271
266
  end
272
267
 
268
+ def apply_start_limit(relation, start)
269
+ relation.where(bind_attribute(primary_key, start) { |attr, bind| attr.gteq(bind) })
270
+ end
271
+
272
+ def apply_finish_limit(relation, finish)
273
+ relation.where(bind_attribute(primary_key, finish) { |attr, bind| attr.lteq(bind) })
274
+ end
275
+
273
276
  def batch_order
274
277
  arel_attribute(primary_key).asc
275
278
  end
@@ -41,15 +41,13 @@ module ActiveRecord
41
41
  def count(column_name = nil)
42
42
  if block_given?
43
43
  unless column_name.nil?
44
- ActiveSupport::Deprecation.warn \
45
- "When `count' is called with a block, it ignores other arguments. " \
46
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
44
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
47
45
  end
48
46
 
49
- return super()
47
+ super()
48
+ else
49
+ calculate(:count, column_name)
50
50
  end
51
-
52
- calculate(:count, column_name)
53
51
  end
54
52
 
55
53
  # Calculates the average value on a given column. Returns +nil+ if there's
@@ -86,15 +84,13 @@ module ActiveRecord
86
84
  def sum(column_name = nil)
87
85
  if block_given?
88
86
  unless column_name.nil?
89
- ActiveSupport::Deprecation.warn \
90
- "When `sum' is called with a block, it ignores other arguments. " \
91
- "This behavior is now deprecated and will result in an ArgumentError in Rails 6.0."
87
+ raise ArgumentError, "Column name argument is not supported when a block is passed."
92
88
  end
93
89
 
94
- return super()
90
+ super()
91
+ else
92
+ calculate(:sum, column_name)
95
93
  end
96
-
97
- calculate(:sum, column_name)
98
94
  end
99
95
 
100
96
  # This calculates aggregate values in the given column. Methods for #count, #sum, #average,
@@ -133,12 +129,11 @@ module ActiveRecord
133
129
  relation = apply_join_dependency
134
130
 
135
131
  if operation.to_s.downcase == "count"
136
- unless distinct_value || distinct_select?(column_name || select_for_count)
137
- relation.distinct!
138
- relation.select_values = [ klass.primary_key || table[Arel.star] ]
139
- end
132
+ relation.distinct!
140
133
  # PostgreSQL: ORDER BY expressions must appear in SELECT list when using DISTINCT
141
- relation.order_values = []
134
+ if (column_name == :all || column_name.nil?) && select_values.empty?
135
+ relation.order_values = []
136
+ end
142
137
  end
143
138
 
144
139
  relation.calculate(operation, column_name)
@@ -191,14 +186,34 @@ module ActiveRecord
191
186
  relation = apply_join_dependency
192
187
  relation.pluck(*column_names)
193
188
  else
194
- klass.enforce_raw_sql_whitelist(column_names)
189
+ disallow_raw_sql!(column_names)
195
190
  relation = spawn
196
- relation.select_values = column_names
191
+ relation.select_values = column_names.map { |cn|
192
+ @klass.has_attribute?(cn) || @klass.attribute_alias?(cn) ? arel_attribute(cn) : cn
193
+ }
197
194
  result = skip_query_cache_if_necessary { klass.connection.select_all(relation.arel, nil) }
198
195
  result.cast_values(klass.attribute_types)
199
196
  end
200
197
  end
201
198
 
199
+ # Pick the value(s) from the named column(s) in the current relation.
200
+ # This is short-hand for <tt>relation.limit(1).pluck(*column_names).first</tt>, and is primarily useful
201
+ # when you have a relation that's already narrowed down to a single row.
202
+ #
203
+ # Just like #pluck, #pick will only load the actual value, not the entire record object, so it's also
204
+ # more efficient. The value is, again like with pluck, typecast by the column type.
205
+ #
206
+ # Person.where(id: 1).pick(:name)
207
+ # # SELECT people.name FROM people WHERE id = 1 LIMIT 1
208
+ # # => 'David'
209
+ #
210
+ # Person.where(id: 1).pick(:name, :email_address)
211
+ # # SELECT people.name, people.email_address FROM people WHERE id = 1 LIMIT 1
212
+ # # => [ 'David', 'david@loudthinking.com' ]
213
+ def pick(*column_names)
214
+ limit(1).pluck(*column_names).first
215
+ end
216
+
202
217
  # Pluck all the ID's for the relation using the table's primary key
203
218
  #
204
219
  # Person.ids # SELECT people.id FROM people
@@ -208,6 +223,7 @@ module ActiveRecord
208
223
  end
209
224
 
210
225
  private
226
+
211
227
  def has_include?(column_name)
212
228
  eager_loading? || (includes_values.present? && column_name && column_name != :all)
213
229
  end
@@ -222,12 +238,10 @@ module ActiveRecord
222
238
  if operation == "count"
223
239
  column_name ||= select_for_count
224
240
  if column_name == :all
225
- if !distinct
226
- distinct = distinct_select?(select_for_count) if group_values.empty?
227
- elsif group_values.any? || select_values.empty? && order_values.empty?
241
+ if distinct && (group_values.any? || select_values.empty? && order_values.empty?)
228
242
  column_name = primary_key
229
243
  end
230
- elsif distinct_select?(column_name)
244
+ elsif column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
231
245
  distinct = nil
232
246
  end
233
247
  end
@@ -239,10 +253,6 @@ module ActiveRecord
239
253
  end
240
254
  end
241
255
 
242
- def distinct_select?(column_name)
243
- column_name.is_a?(::String) && /\bDISTINCT[\s(]/i.match?(column_name)
244
- end
245
-
246
256
  def aggregate_column(column_name)
247
257
  return column_name if Arel::Expressions === column_name
248
258
 
@@ -387,7 +397,7 @@ module ActiveRecord
387
397
  case operation
388
398
  when "count" then value.to_i
389
399
  when "sum" then type.deserialize(value || 0)
390
- when "average" then value && value.respond_to?(:to_d) ? value.to_d : value
400
+ when "average" then value&.respond_to?(:to_d) ? value.to_d : value
391
401
  else type.deserialize(value)
392
402
  end
393
403
  end
@@ -18,7 +18,7 @@ module ActiveRecord
18
18
  include ClassSpecificRelation
19
19
  }
20
20
  include_relation_methods(delegate)
21
- mangled_name = klass.name.gsub("::".freeze, "_".freeze)
21
+ mangled_name = klass.name.gsub("::", "_")
22
22
  const_set mangled_name, delegate
23
23
  private_constant mangled_name
24
24
 
@@ -33,7 +33,7 @@ module ActiveRecord
33
33
 
34
34
  protected
35
35
  def include_relation_methods(delegate)
36
- superclass.include_relation_methods(delegate) unless base_class == self
36
+ superclass.include_relation_methods(delegate) unless base_class?
37
37
  delegate.include generated_relation_methods
38
38
  end
39
39
 
@@ -54,7 +54,7 @@ module ActiveRecord
54
54
  end
55
55
  RUBY
56
56
  else
57
- generated_relation_methods.send(:define_method, method) do |*args, &block|
57
+ generated_relation_methods.define_method(method) do |*args, &block|
58
58
  scoping { klass.public_send(method, *args, &block) }
59
59
  end
60
60
  end
@@ -68,7 +68,7 @@ module ActiveRecord
68
68
  # may vary depending on the klass of a relation, so we create a subclass of Relation
69
69
  # for each different klass, and the delegations are compiled into that subclass only.
70
70
 
71
- delegate :to_xml, :encode_with, :length, :each, :uniq, :join,
71
+ delegate :to_xml, :encode_with, :length, :each, :join,
72
72
  :[], :&, :|, :+, :-, :sample, :reverse, :rotate, :compact, :in_groups, :in_groups_of,
73
73
  :to_sentence, :to_formatted_s, :as_json,
74
74
  :shuffle, :split, :slice, :index, :rindex, to: :records
@@ -112,15 +112,6 @@ module ActiveRecord
112
112
  if @klass.respond_to?(method)
113
113
  self.class.delegate_to_scoped_klass(method)
114
114
  scoping { @klass.public_send(method, *args, &block) }
115
- elsif @delegate_to_klass && @klass.respond_to?(method, true)
116
- ActiveSupport::Deprecation.warn \
117
- "Delegating missing #{method} method to #{@klass}. " \
118
- "Accessibility of private/protected class methods in :scope is deprecated and will be removed in Rails 6.0."
119
- @klass.send(method, *args, &block)
120
- elsif arel.respond_to?(method)
121
- ActiveSupport::Deprecation.warn \
122
- "Delegating #{method} to arel is deprecated and will be removed in Rails 6.0."
123
- arel.public_send(method, *args, &block)
124
115
  else
125
116
  super
126
117
  end