activerecord 5.2.6 → 6.0.5

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 (294) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +928 -559
  3. data/MIT-LICENSE +3 -1
  4. data/README.rdoc +5 -3
  5. data/examples/performance.rb +1 -1
  6. data/lib/active_record/advisory_lock_base.rb +18 -0
  7. data/lib/active_record/aggregations.rb +4 -3
  8. data/lib/active_record/association_relation.rb +10 -8
  9. data/lib/active_record/associations/alias_tracker.rb +0 -1
  10. data/lib/active_record/associations/association.rb +55 -19
  11. data/lib/active_record/associations/association_scope.rb +11 -7
  12. data/lib/active_record/associations/belongs_to_association.rb +36 -42
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -4
  14. data/lib/active_record/associations/builder/association.rb +14 -18
  15. data/lib/active_record/associations/builder/belongs_to.rb +19 -52
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -13
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -40
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +35 -1
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +19 -23
  22. data/lib/active_record/associations/collection_proxy.rb +14 -17
  23. data/lib/active_record/associations/foreign_association.rb +7 -0
  24. data/lib/active_record/associations/has_many_association.rb +2 -11
  25. data/lib/active_record/associations/has_many_through_association.rb +14 -14
  26. data/lib/active_record/associations/has_one_association.rb +28 -30
  27. data/lib/active_record/associations/has_one_through_association.rb +5 -5
  28. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  29. data/lib/active_record/associations/join_dependency/join_part.rb +4 -4
  30. data/lib/active_record/associations/join_dependency.rb +47 -30
  31. data/lib/active_record/associations/preloader/association.rb +61 -41
  32. data/lib/active_record/associations/preloader/through_association.rb +48 -39
  33. data/lib/active_record/associations/preloader.rb +44 -33
  34. data/lib/active_record/associations/singular_association.rb +2 -16
  35. data/lib/active_record/associations/through_association.rb +1 -1
  36. data/lib/active_record/associations.rb +21 -16
  37. data/lib/active_record/attribute_assignment.rb +7 -11
  38. data/lib/active_record/attribute_decorators.rb +0 -2
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +4 -2
  40. data/lib/active_record/attribute_methods/dirty.rb +111 -40
  41. data/lib/active_record/attribute_methods/primary_key.rb +15 -24
  42. data/lib/active_record/attribute_methods/query.rb +2 -3
  43. data/lib/active_record/attribute_methods/read.rb +15 -54
  44. data/lib/active_record/attribute_methods/serialization.rb +1 -2
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +1 -3
  46. data/lib/active_record/attribute_methods/write.rb +17 -25
  47. data/lib/active_record/attribute_methods.rb +28 -100
  48. data/lib/active_record/attributes.rb +13 -1
  49. data/lib/active_record/autosave_association.rb +12 -14
  50. data/lib/active_record/base.rb +2 -3
  51. data/lib/active_record/callbacks.rb +6 -21
  52. data/lib/active_record/coders/yaml_column.rb +0 -1
  53. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +109 -18
  54. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -4
  55. data/lib/active_record/connection_adapters/abstract/database_statements.rb +102 -124
  56. data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -9
  57. data/lib/active_record/connection_adapters/abstract/quoting.rb +68 -17
  58. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +20 -14
  59. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +105 -72
  60. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +1 -3
  61. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +175 -79
  62. data/lib/active_record/connection_adapters/abstract/transaction.rb +96 -57
  63. data/lib/active_record/connection_adapters/abstract_adapter.rb +197 -43
  64. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +149 -217
  65. data/lib/active_record/connection_adapters/column.rb +17 -13
  66. data/lib/active_record/connection_adapters/connection_specification.rb +54 -45
  67. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +6 -10
  68. data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
  69. data/lib/active_record/connection_adapters/mysql/database_statements.rb +70 -14
  70. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +0 -1
  71. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -7
  72. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +4 -6
  73. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +40 -32
  74. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +14 -6
  75. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +139 -19
  76. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +6 -10
  77. data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -10
  78. data/lib/active_record/connection_adapters/postgresql/column.rb +17 -31
  79. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +26 -1
  80. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
  81. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
  82. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +8 -0
  83. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
  84. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
  85. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +1 -2
  86. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +1 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
  89. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
  91. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  92. data/lib/active_record/connection_adapters/postgresql/quoting.rb +44 -7
  93. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +1 -1
  94. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -3
  95. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
  96. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
  97. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +63 -75
  98. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +24 -27
  99. data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
  100. data/lib/active_record/connection_adapters/postgresql_adapter.rb +168 -75
  101. data/lib/active_record/connection_adapters/schema_cache.rb +37 -14
  102. data/lib/active_record/connection_adapters/sql_type_metadata.rb +11 -8
  103. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  104. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
  105. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -12
  106. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +137 -147
  107. data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
  108. data/lib/active_record/connection_handling.rb +139 -26
  109. data/lib/active_record/core.rb +107 -66
  110. data/lib/active_record/counter_cache.rb +8 -30
  111. data/lib/active_record/database_configurations/database_config.rb +37 -0
  112. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  113. data/lib/active_record/database_configurations/url_config.rb +78 -0
  114. data/lib/active_record/database_configurations.rb +233 -0
  115. data/lib/active_record/dynamic_matchers.rb +3 -4
  116. data/lib/active_record/enum.rb +44 -7
  117. data/lib/active_record/errors.rb +15 -7
  118. data/lib/active_record/explain.rb +1 -2
  119. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  120. data/lib/active_record/fixture_set/render_context.rb +17 -0
  121. data/lib/active_record/fixture_set/table_row.rb +152 -0
  122. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  123. data/lib/active_record/fixtures.rb +144 -474
  124. data/lib/active_record/gem_version.rb +3 -3
  125. data/lib/active_record/inheritance.rb +13 -6
  126. data/lib/active_record/insert_all.rb +179 -0
  127. data/lib/active_record/integration.rb +68 -16
  128. data/lib/active_record/internal_metadata.rb +11 -3
  129. data/lib/active_record/locking/optimistic.rb +14 -7
  130. data/lib/active_record/locking/pessimistic.rb +3 -3
  131. data/lib/active_record/log_subscriber.rb +8 -27
  132. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  133. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  134. data/lib/active_record/middleware/database_selector.rb +74 -0
  135. data/lib/active_record/migration/command_recorder.rb +54 -22
  136. data/lib/active_record/migration/compatibility.rb +79 -52
  137. data/lib/active_record/migration/join_table.rb +0 -1
  138. data/lib/active_record/migration.rb +104 -85
  139. data/lib/active_record/model_schema.rb +62 -11
  140. data/lib/active_record/nested_attributes.rb +2 -4
  141. data/lib/active_record/no_touching.rb +9 -2
  142. data/lib/active_record/null_relation.rb +0 -1
  143. data/lib/active_record/persistence.rb +232 -29
  144. data/lib/active_record/query_cache.rb +11 -4
  145. data/lib/active_record/querying.rb +33 -21
  146. data/lib/active_record/railtie.rb +80 -43
  147. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  148. data/lib/active_record/railties/controller_runtime.rb +30 -35
  149. data/lib/active_record/railties/databases.rake +199 -46
  150. data/lib/active_record/reflection.rb +51 -51
  151. data/lib/active_record/relation/batches.rb +13 -11
  152. data/lib/active_record/relation/calculations.rb +55 -49
  153. data/lib/active_record/relation/delegation.rb +35 -50
  154. data/lib/active_record/relation/finder_methods.rb +23 -28
  155. data/lib/active_record/relation/from_clause.rb +4 -0
  156. data/lib/active_record/relation/merger.rb +12 -17
  157. data/lib/active_record/relation/predicate_builder/array_handler.rb +5 -4
  158. data/lib/active_record/relation/predicate_builder/association_query_value.rb +1 -4
  159. data/lib/active_record/relation/predicate_builder/base_handler.rb +1 -2
  160. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
  161. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +1 -4
  162. data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
  163. data/lib/active_record/relation/predicate_builder.rb +5 -11
  164. data/lib/active_record/relation/query_attribute.rb +13 -8
  165. data/lib/active_record/relation/query_methods.rb +232 -69
  166. data/lib/active_record/relation/spawn_methods.rb +1 -2
  167. data/lib/active_record/relation/where_clause.rb +14 -11
  168. data/lib/active_record/relation/where_clause_factory.rb +1 -2
  169. data/lib/active_record/relation.rb +326 -81
  170. data/lib/active_record/result.rb +30 -12
  171. data/lib/active_record/sanitization.rb +32 -40
  172. data/lib/active_record/schema.rb +2 -11
  173. data/lib/active_record/schema_dumper.rb +22 -7
  174. data/lib/active_record/schema_migration.rb +6 -2
  175. data/lib/active_record/scoping/default.rb +4 -6
  176. data/lib/active_record/scoping/named.rb +25 -16
  177. data/lib/active_record/scoping.rb +8 -9
  178. data/lib/active_record/statement_cache.rb +30 -3
  179. data/lib/active_record/store.rb +87 -8
  180. data/lib/active_record/suppressor.rb +2 -2
  181. data/lib/active_record/table_metadata.rb +23 -15
  182. data/lib/active_record/tasks/database_tasks.rb +194 -25
  183. data/lib/active_record/tasks/mysql_database_tasks.rb +5 -6
  184. data/lib/active_record/tasks/postgresql_database_tasks.rb +5 -8
  185. data/lib/active_record/tasks/sqlite_database_tasks.rb +2 -9
  186. data/lib/active_record/test_databases.rb +23 -0
  187. data/lib/active_record/test_fixtures.rb +243 -0
  188. data/lib/active_record/timestamp.rb +39 -26
  189. data/lib/active_record/touch_later.rb +5 -4
  190. data/lib/active_record/transactions.rb +64 -73
  191. data/lib/active_record/translation.rb +1 -1
  192. data/lib/active_record/type/adapter_specific_registry.rb +3 -13
  193. data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
  194. data/lib/active_record/type/serialized.rb +0 -1
  195. data/lib/active_record/type/time.rb +10 -0
  196. data/lib/active_record/type/type_map.rb +0 -1
  197. data/lib/active_record/type/unsigned_integer.rb +0 -1
  198. data/lib/active_record/type.rb +3 -5
  199. data/lib/active_record/type_caster/connection.rb +15 -14
  200. data/lib/active_record/type_caster/map.rb +1 -4
  201. data/lib/active_record/validations/associated.rb +0 -1
  202. data/lib/active_record/validations/uniqueness.rb +15 -27
  203. data/lib/active_record/validations.rb +3 -3
  204. data/lib/active_record.rb +10 -2
  205. data/lib/arel/alias_predication.rb +9 -0
  206. data/lib/arel/attributes/attribute.rb +37 -0
  207. data/lib/arel/attributes.rb +22 -0
  208. data/lib/arel/collectors/bind.rb +24 -0
  209. data/lib/arel/collectors/composite.rb +31 -0
  210. data/lib/arel/collectors/plain_string.rb +20 -0
  211. data/lib/arel/collectors/sql_string.rb +20 -0
  212. data/lib/arel/collectors/substitute_binds.rb +28 -0
  213. data/lib/arel/crud.rb +42 -0
  214. data/lib/arel/delete_manager.rb +18 -0
  215. data/lib/arel/errors.rb +9 -0
  216. data/lib/arel/expressions.rb +29 -0
  217. data/lib/arel/factory_methods.rb +49 -0
  218. data/lib/arel/insert_manager.rb +49 -0
  219. data/lib/arel/math.rb +45 -0
  220. data/lib/arel/nodes/and.rb +32 -0
  221. data/lib/arel/nodes/ascending.rb +23 -0
  222. data/lib/arel/nodes/binary.rb +52 -0
  223. data/lib/arel/nodes/bind_param.rb +36 -0
  224. data/lib/arel/nodes/case.rb +55 -0
  225. data/lib/arel/nodes/casted.rb +50 -0
  226. data/lib/arel/nodes/comment.rb +29 -0
  227. data/lib/arel/nodes/count.rb +12 -0
  228. data/lib/arel/nodes/delete_statement.rb +45 -0
  229. data/lib/arel/nodes/descending.rb +23 -0
  230. data/lib/arel/nodes/equality.rb +18 -0
  231. data/lib/arel/nodes/extract.rb +24 -0
  232. data/lib/arel/nodes/false.rb +16 -0
  233. data/lib/arel/nodes/full_outer_join.rb +8 -0
  234. data/lib/arel/nodes/function.rb +44 -0
  235. data/lib/arel/nodes/grouping.rb +8 -0
  236. data/lib/arel/nodes/in.rb +8 -0
  237. data/lib/arel/nodes/infix_operation.rb +80 -0
  238. data/lib/arel/nodes/inner_join.rb +8 -0
  239. data/lib/arel/nodes/insert_statement.rb +37 -0
  240. data/lib/arel/nodes/join_source.rb +20 -0
  241. data/lib/arel/nodes/matches.rb +18 -0
  242. data/lib/arel/nodes/named_function.rb +23 -0
  243. data/lib/arel/nodes/node.rb +50 -0
  244. data/lib/arel/nodes/node_expression.rb +13 -0
  245. data/lib/arel/nodes/outer_join.rb +8 -0
  246. data/lib/arel/nodes/over.rb +15 -0
  247. data/lib/arel/nodes/regexp.rb +16 -0
  248. data/lib/arel/nodes/right_outer_join.rb +8 -0
  249. data/lib/arel/nodes/select_core.rb +67 -0
  250. data/lib/arel/nodes/select_statement.rb +41 -0
  251. data/lib/arel/nodes/sql_literal.rb +16 -0
  252. data/lib/arel/nodes/string_join.rb +11 -0
  253. data/lib/arel/nodes/table_alias.rb +27 -0
  254. data/lib/arel/nodes/terminal.rb +16 -0
  255. data/lib/arel/nodes/true.rb +16 -0
  256. data/lib/arel/nodes/unary.rb +45 -0
  257. data/lib/arel/nodes/unary_operation.rb +20 -0
  258. data/lib/arel/nodes/unqualified_column.rb +22 -0
  259. data/lib/arel/nodes/update_statement.rb +41 -0
  260. data/lib/arel/nodes/values_list.rb +9 -0
  261. data/lib/arel/nodes/window.rb +126 -0
  262. data/lib/arel/nodes/with.rb +11 -0
  263. data/lib/arel/nodes.rb +68 -0
  264. data/lib/arel/order_predications.rb +13 -0
  265. data/lib/arel/predications.rb +256 -0
  266. data/lib/arel/select_manager.rb +271 -0
  267. data/lib/arel/table.rb +110 -0
  268. data/lib/arel/tree_manager.rb +72 -0
  269. data/lib/arel/update_manager.rb +34 -0
  270. data/lib/arel/visitors/depth_first.rb +203 -0
  271. data/lib/arel/visitors/dot.rb +296 -0
  272. data/lib/arel/visitors/ibm_db.rb +34 -0
  273. data/lib/arel/visitors/informix.rb +62 -0
  274. data/lib/arel/visitors/mssql.rb +156 -0
  275. data/lib/arel/visitors/mysql.rb +83 -0
  276. data/lib/arel/visitors/oracle.rb +158 -0
  277. data/lib/arel/visitors/oracle12.rb +65 -0
  278. data/lib/arel/visitors/postgresql.rb +109 -0
  279. data/lib/arel/visitors/sqlite.rb +38 -0
  280. data/lib/arel/visitors/to_sql.rb +888 -0
  281. data/lib/arel/visitors/visitor.rb +45 -0
  282. data/lib/arel/visitors/where_sql.rb +22 -0
  283. data/lib/arel/visitors.rb +20 -0
  284. data/lib/arel/window_predications.rb +9 -0
  285. data/lib/arel.rb +62 -0
  286. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
  287. data/lib/rails/generators/active_record/migration/migration_generator.rb +2 -5
  288. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +1 -1
  289. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +4 -2
  290. data/lib/rails/generators/active_record/migration.rb +14 -2
  291. data/lib/rails/generators/active_record/model/model_generator.rb +1 -1
  292. data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
  293. metadata +116 -29
  294. data/lib/active_record/collection_cache_key.rb +0 -53
@@ -2,6 +2,8 @@
2
2
 
3
3
  require "active_record"
4
4
 
5
+ databases = ActiveRecord::Tasks::DatabaseTasks.setup_initial_database_yaml
6
+
5
7
  db_namespace = namespace :db do
6
8
  desc "Set the environment value for the database"
7
9
  task "environment:set" => :load_config do
@@ -22,6 +24,14 @@ db_namespace = namespace :db do
22
24
  task all: :load_config do
23
25
  ActiveRecord::Tasks::DatabaseTasks.create_all
24
26
  end
27
+
28
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
29
+ desc "Create #{spec_name} database for current environment"
30
+ task spec_name => :load_config do
31
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
32
+ ActiveRecord::Tasks::DatabaseTasks.create(db_config.config)
33
+ end
34
+ end
25
35
  end
26
36
 
27
37
  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 +43,14 @@ db_namespace = namespace :db do
33
43
  task all: [:load_config, :check_protected_environments] do
34
44
  ActiveRecord::Tasks::DatabaseTasks.drop_all
35
45
  end
46
+
47
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
48
+ desc "Drop #{spec_name} database for current environment"
49
+ task spec_name => [:load_config, :check_protected_environments] do
50
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
51
+ ActiveRecord::Tasks::DatabaseTasks.drop(db_config.config)
52
+ end
53
+ end
36
54
  end
37
55
 
38
56
  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."
@@ -50,6 +68,11 @@ db_namespace = namespace :db do
50
68
  end
51
69
  end
52
70
 
71
+ # desc "Truncates tables of each database for current environment"
72
+ task truncate_all: [:load_config, :check_protected_environments] do
73
+ ActiveRecord::Tasks::DatabaseTasks.truncate_all
74
+ end
75
+
53
76
  # desc "Empty the database from DATABASE_URL or config/database.yml for the current RAILS_ENV (use db:purge:all to purge all databases in the config). Without RAILS_ENV it defaults to purging the development and test databases."
54
77
  task purge: [:load_config, :check_protected_environments] do
55
78
  ActiveRecord::Tasks::DatabaseTasks.purge_current
@@ -57,8 +80,14 @@ db_namespace = namespace :db do
57
80
 
58
81
  desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
59
82
  task migrate: :load_config do
60
- ActiveRecord::Tasks::DatabaseTasks.migrate
83
+ original_config = ActiveRecord::Base.connection_config
84
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
85
+ ActiveRecord::Base.establish_connection(db_config.config)
86
+ ActiveRecord::Tasks::DatabaseTasks.migrate
87
+ end
61
88
  db_namespace["_dump"].invoke
89
+ ensure
90
+ ActiveRecord::Base.establish_connection(original_config)
62
91
  end
63
92
 
64
93
  # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false
@@ -77,6 +106,15 @@ db_namespace = namespace :db do
77
106
  end
78
107
 
79
108
  namespace :migrate do
109
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
110
+ desc "Migrate #{spec_name} database for current environment"
111
+ task spec_name => :load_config do
112
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
113
+ ActiveRecord::Base.establish_connection(db_config.config)
114
+ ActiveRecord::Tasks::DatabaseTasks.migrate
115
+ end
116
+ end
117
+
80
118
  # desc 'Rollbacks the database one migration and re migrate up (options: STEP=x, VERSION=x).'
81
119
  task redo: :load_config do
82
120
  raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
@@ -95,6 +133,8 @@ db_namespace = namespace :db do
95
133
 
96
134
  # desc 'Runs the "up" for a given migration VERSION.'
97
135
  task up: :load_config do
136
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:up")
137
+
98
138
  raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
99
139
 
100
140
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
@@ -106,8 +146,29 @@ db_namespace = namespace :db do
106
146
  db_namespace["_dump"].invoke
107
147
  end
108
148
 
149
+ namespace :up do
150
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
151
+ task spec_name => :load_config do
152
+ raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
153
+
154
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
155
+
156
+ ActiveRecord::Base.establish_connection(db_config.config)
157
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
158
+ ActiveRecord::Base.connection.migration_context.run(
159
+ :up,
160
+ ActiveRecord::Tasks::DatabaseTasks.target_version
161
+ )
162
+
163
+ db_namespace["_dump"].invoke
164
+ end
165
+ end
166
+ end
167
+
109
168
  # desc 'Runs the "down" for a given migration VERSION.'
110
169
  task down: :load_config do
170
+ ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:migrate:down")
171
+
111
172
  raise "VERSION is required - To go down one migration, use db:rollback" if !ENV["VERSION"] || ENV["VERSION"].empty?
112
173
 
113
174
  ActiveRecord::Tasks::DatabaseTasks.check_target_version
@@ -119,20 +180,42 @@ db_namespace = namespace :db do
119
180
  db_namespace["_dump"].invoke
120
181
  end
121
182
 
183
+ namespace :down do
184
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
185
+ task spec_name => :load_config do
186
+ raise "VERSION is required" if !ENV["VERSION"] || ENV["VERSION"].empty?
187
+
188
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
189
+
190
+ ActiveRecord::Base.establish_connection(db_config.config)
191
+ ActiveRecord::Tasks::DatabaseTasks.check_target_version
192
+ ActiveRecord::Base.connection.migration_context.run(
193
+ :down,
194
+ ActiveRecord::Tasks::DatabaseTasks.target_version
195
+ )
196
+
197
+ db_namespace["_dump"].invoke
198
+ end
199
+ end
200
+ end
201
+
122
202
  desc "Display status of migrations"
123
203
  task status: :load_config do
124
- unless ActiveRecord::SchemaMigration.table_exists?
125
- abort "Schema migrations table does not exist yet."
204
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
205
+ ActiveRecord::Base.establish_connection(db_config.config)
206
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
126
207
  end
208
+ end
127
209
 
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}"
210
+ namespace :status do
211
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
212
+ desc "Display status of migrations for #{spec_name} database"
213
+ task spec_name => :load_config do
214
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
215
+ ActiveRecord::Base.establish_connection(db_config.config)
216
+ ActiveRecord::Tasks::DatabaseTasks.migrate_status
217
+ end
134
218
  end
135
- puts
136
219
  end
137
220
  end
138
221
 
@@ -160,11 +243,9 @@ db_namespace = namespace :db do
160
243
 
161
244
  # desc "Retrieves the collation for the current environment's database"
162
245
  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
246
+ puts ActiveRecord::Tasks::DatabaseTasks.collation_current
247
+ rescue NoMethodError
248
+ $stderr.puts "Sorry, your database adapter is not supported yet. Feel free to submit a patch."
168
249
  end
169
250
 
170
251
  desc "Retrieves the current schema version number"
@@ -174,7 +255,11 @@ db_namespace = namespace :db do
174
255
 
175
256
  # desc "Raises an error if there are pending migrations"
176
257
  task abort_if_pending_migrations: :load_config do
177
- pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
258
+ pending_migrations = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).flat_map do |db_config|
259
+ ActiveRecord::Base.establish_connection(db_config.config)
260
+
261
+ ActiveRecord::Base.connection.migration_context.open.pending_migrations
262
+ end
178
263
 
179
264
  if pending_migrations.any?
180
265
  puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
@@ -183,17 +268,74 @@ db_namespace = namespace :db do
183
268
  end
184
269
  abort %{Run `rails db:migrate` to update your database then try again.}
185
270
  end
271
+ ensure
272
+ ActiveRecord::Base.establish_connection(ActiveRecord::Tasks::DatabaseTasks.env.to_sym)
273
+ end
274
+
275
+ namespace :abort_if_pending_migrations do
276
+ ActiveRecord::Tasks::DatabaseTasks.for_each(databases) do |spec_name|
277
+ # desc "Raises an error if there are pending migrations for #{spec_name} database"
278
+ task spec_name => :load_config do
279
+ db_config = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env, spec_name: spec_name)
280
+ ActiveRecord::Base.establish_connection(db_config.config)
281
+
282
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
283
+
284
+ if pending_migrations.any?
285
+ puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
286
+ pending_migrations.each do |pending_migration|
287
+ puts " %4d %s" % [pending_migration.version, pending_migration.name]
288
+ end
289
+ abort %{Run `rails db:migrate:#{spec_name}` to update your database then try again.}
290
+ end
291
+ end
292
+ end
186
293
  end
187
294
 
188
295
  desc "Creates the database, loads the schema, and initializes with the seed data (use db:reset to also drop the database first)"
189
296
  task setup: ["db:schema:load_if_ruby", "db:structure:load_if_sql", :seed]
190
297
 
298
+ desc "Runs setup if database does not exist, or runs migrations if it does"
299
+ task prepare: :load_config do
300
+ seed = false
301
+
302
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
303
+ ActiveRecord::Base.establish_connection(db_config.config)
304
+
305
+ # Skipped when no database
306
+ ActiveRecord::Tasks::DatabaseTasks.migrate
307
+ if ActiveRecord::Base.dump_schema_after_migration
308
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, ActiveRecord::Base.schema_format, db_config.spec_name)
309
+ end
310
+
311
+ rescue ActiveRecord::NoDatabaseError
312
+ ActiveRecord::Tasks::DatabaseTasks.create_current(db_config.env_name, db_config.spec_name)
313
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(
314
+ db_config.config,
315
+ ActiveRecord::Base.schema_format,
316
+ nil,
317
+ db_config.env_name,
318
+ db_config.spec_name
319
+ )
320
+
321
+ seed = true
322
+ end
323
+
324
+ ActiveRecord::Base.establish_connection
325
+ ActiveRecord::Tasks::DatabaseTasks.load_seed if seed
326
+ end
327
+
191
328
  desc "Loads the seed data from db/seeds.rb"
192
- task :seed do
329
+ task seed: :load_config do
193
330
  db_namespace["abort_if_pending_migrations"].invoke
194
331
  ActiveRecord::Tasks::DatabaseTasks.load_seed
195
332
  end
196
333
 
334
+ namespace :seed do
335
+ desc "Truncates tables of each database for current environment and loads the seeds"
336
+ task replant: [:load_config, :truncate_all, :seed]
337
+ end
338
+
197
339
  namespace :fixtures do
198
340
  desc "Loads fixtures into the current environment's database. Load specific fixtures using FIXTURES=x,y. Load from subdirectory in test/fixtures using FIXTURES_DIR=z. Specify an alternative path (eg. spec/fixtures) using FIXTURES_PATH=spec/fixtures."
199
341
  task load: :load_config do
@@ -245,11 +387,11 @@ db_namespace = namespace :db do
245
387
  namespace :schema do
246
388
  desc "Creates a db/schema.rb file that is portable against any DB supported by Active Record"
247
389
  task dump: :load_config do
248
- 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)
390
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
391
+ ActiveRecord::Base.establish_connection(db_config.config)
392
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :ruby, db_config.spec_name)
252
393
  end
394
+
253
395
  db_namespace["schema:dump"].reenable
254
396
  end
255
397
 
@@ -265,33 +407,34 @@ db_namespace = namespace :db do
265
407
  namespace :cache do
266
408
  desc "Creates a db/schema_cache.yml file."
267
409
  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)
410
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
411
+ ActiveRecord::Base.establish_connection(db_config.config)
412
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
413
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
414
+ ActiveRecord::Base.connection,
415
+ filename,
416
+ )
417
+ end
271
418
  end
272
419
 
273
420
  desc "Clears a db/schema_cache.yml file."
274
421
  task clear: :load_config do
275
- filename = File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, "schema_cache.yml")
276
- rm_f filename, verbose: false
422
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
423
+ filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
424
+ rm_f filename, verbose: false
425
+ end
277
426
  end
278
427
  end
279
-
280
428
  end
281
429
 
282
430
  namespace :structure do
283
431
  desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql"
284
432
  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"
293
- end
433
+ ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
434
+ ActiveRecord::Base.establish_connection(db_config.config)
435
+ ActiveRecord::Tasks::DatabaseTasks.dump_schema(db_config.config, :sql, db_config.spec_name)
294
436
  end
437
+
295
438
  db_namespace["structure:dump"].reenable
296
439
  end
297
440
 
@@ -318,25 +461,31 @@ db_namespace = namespace :db do
318
461
 
319
462
  # desc "Recreate the test database from an existent schema.rb file"
320
463
  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
464
+ should_reconnect = ActiveRecord::Base.connection_pool.active_connection?
465
+ ActiveRecord::Schema.verbose = false
466
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
467
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :ruby)
468
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, :ruby, filename, "test")
469
+ end
470
+ ensure
471
+ if should_reconnect
472
+ ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations.default_hash(ActiveRecord::Tasks::DatabaseTasks.env))
329
473
  end
330
474
  end
331
475
 
332
476
  # desc "Recreate the test database from an existent structure.sql file"
333
477
  task load_structure: %w(db:test:purge) do
334
- ActiveRecord::Tasks::DatabaseTasks.load_schema ActiveRecord::Base.configurations["test"], :sql, ENV["SCHEMA"], "test"
478
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
479
+ filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(db_config.spec_name, :sql)
480
+ ActiveRecord::Tasks::DatabaseTasks.load_schema(db_config.config, :sql, filename, "test")
481
+ end
335
482
  end
336
483
 
337
484
  # desc "Empty the test database"
338
485
  task purge: %w(load_config check_protected_environments) do
339
- ActiveRecord::Tasks::DatabaseTasks.purge ActiveRecord::Base.configurations["test"]
486
+ ActiveRecord::Base.configurations.configs_for(env_name: "test").each do |db_config|
487
+ ActiveRecord::Tasks::DatabaseTasks.purge(db_config.config)
488
+ end
340
489
  end
341
490
 
342
491
  # desc 'Load the test schema'
@@ -360,6 +509,10 @@ namespace :railties do
360
509
  if railtie.respond_to?(:paths) && (path = railtie.paths["db/migrate"].first)
361
510
  railties[railtie.railtie_name] = path
362
511
  end
512
+
513
+ unless ENV["MIGRATIONS_PATH"].blank?
514
+ railties[railtie.railtie_name] = railtie.root + ENV["MIGRATIONS_PATH"]
515
+ end
363
516
  end
364
517
 
365
518
  on_skip = Proc.new do |name, migration|
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "active_support/core_ext/string/filters"
4
- require "concurrent/map"
5
4
 
6
5
  module ActiveRecord
7
6
  # = Active Record Reflection
@@ -13,33 +12,37 @@ module ActiveRecord
13
12
  class_attribute :aggregate_reflections, instance_writer: false, default: {}
14
13
  end
15
14
 
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
15
+ class << self
16
+ def create(macro, name, scope, options, ar)
17
+ reflection = reflection_class_for(macro).new(name, scope, options, ar)
18
+ options[:through] ? ThroughReflection.new(reflection) : reflection
19
+ end
30
20
 
31
- reflection = klass.new(name, scope, options, ar)
32
- options[:through] ? ThroughReflection.new(reflection) : reflection
33
- end
21
+ def add_reflection(ar, name, reflection)
22
+ ar.clear_reflections_cache
23
+ name = -name.to_s
24
+ ar._reflections = ar._reflections.except(name).merge!(name => reflection)
25
+ end
34
26
 
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
27
+ def add_aggregate_reflection(ar, name, reflection)
28
+ ar.aggregate_reflections = ar.aggregate_reflections.merge(-name.to_s => reflection)
29
+ end
40
30
 
41
- def self.add_aggregate_reflection(ar, name, reflection)
42
- ar.aggregate_reflections = ar.aggregate_reflections.merge(name.to_s => reflection)
31
+ private
32
+ def reflection_class_for(macro)
33
+ case macro
34
+ when :composed_of
35
+ AggregateReflection
36
+ when :has_many
37
+ HasManyReflection
38
+ when :has_one
39
+ HasOneReflection
40
+ when :belongs_to
41
+ BelongsToReflection
42
+ else
43
+ raise "Unsupported Macro: #{macro}"
44
+ end
45
+ end
43
46
  end
44
47
 
45
48
  # \Reflection enables the ability to examine the associations and aggregations of
@@ -179,25 +182,27 @@ module ActiveRecord
179
182
  scope_chain_items = join_scopes(table, predicate_builder)
180
183
  klass_scope = klass_join_scope(table, predicate_builder)
181
184
 
185
+ if type
186
+ klass_scope.where!(type => foreign_klass.polymorphic_name)
187
+ end
188
+
189
+ scope_chain_items.inject(klass_scope, &:merge!)
190
+
182
191
  key = join_keys.key
183
192
  foreign_key = join_keys.foreign_key
184
193
 
185
194
  klass_scope.where!(table[key].eq(foreign_table[foreign_key]))
186
195
 
187
- if type
188
- klass_scope.where!(type => foreign_klass.polymorphic_name)
189
- end
190
-
191
196
  if klass.finder_needs_type_condition?
192
197
  klass_scope.where!(klass.send(:type_condition, table))
193
198
  end
194
199
 
195
- scope_chain_items.inject(klass_scope, &:merge!)
200
+ klass_scope
196
201
  end
197
202
 
198
- def join_scopes(table, predicate_builder) # :nodoc:
203
+ def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
199
204
  if scope
200
- [scope_for(build_scope(table, predicate_builder))]
205
+ [scope_for(build_scope(table, predicate_builder, klass))]
201
206
  else
202
207
  []
203
208
  end
@@ -286,7 +291,7 @@ module ActiveRecord
286
291
  JoinKeys.new(join_primary_key(association_klass), join_foreign_key)
287
292
  end
288
293
 
289
- def build_scope(table, predicate_builder = predicate_builder(table))
294
+ def build_scope(table, predicate_builder = predicate_builder(table), klass = self.klass)
290
295
  Relation.create(
291
296
  klass,
292
297
  table: table,
@@ -413,7 +418,7 @@ module ActiveRecord
413
418
  class AssociationReflection < MacroReflection #:nodoc:
414
419
  def compute_class(name)
415
420
  if polymorphic?
416
- raise ArgumentError, "Polymorphic association does not support to compute class."
421
+ raise ArgumentError, "Polymorphic associations do not support computing the class."
417
422
  end
418
423
  active_record.send(:compute_type, name)
419
424
  end
@@ -426,19 +431,18 @@ module ActiveRecord
426
431
  @type = options[:as] && (options[:foreign_type] || "#{options[:as]}_type")
427
432
  @foreign_type = options[:polymorphic] && (options[:foreign_type] || "#{name}_type")
428
433
  @constructable = calculate_constructable(macro, options)
429
- @association_scope_cache = Concurrent::Map.new
430
434
 
431
435
  if options[:class_name] && options[:class_name].class == Class
432
436
  raise ArgumentError, "A class was passed to `:class_name` but we are expecting a string."
433
437
  end
434
438
  end
435
439
 
436
- def association_scope_cache(conn, owner, &block)
437
- key = conn.prepared_statements
440
+ def association_scope_cache(klass, owner, &block)
441
+ key = self
438
442
  if polymorphic?
439
443
  key = [key, owner._read_attribute(@foreign_type)]
440
444
  end
441
- @association_scope_cache.compute_if_absent(key) { StatementCache.create(conn, &block) }
445
+ klass.cached_find_by_statement(key, &block)
442
446
  end
443
447
 
444
448
  def constructable? # :nodoc:
@@ -473,7 +477,7 @@ module ActiveRecord
473
477
  def check_preloadable!
474
478
  return unless scope
475
479
 
476
- if scope.arity > 0
480
+ unless scope.arity == 0
477
481
  raise ArgumentError, <<-MSG.squish
478
482
  The association scope '#{name}' is instance dependent (the scope
479
483
  block takes an argument). Preloading instance dependent scopes is
@@ -504,7 +508,7 @@ module ActiveRecord
504
508
  # This is for clearing cache on the reflection. Useful for tests that need to compare
505
509
  # SQL queries on associations.
506
510
  def clear_association_scope_cache # :nodoc:
507
- @association_scope_cache.clear
511
+ klass.initialize_find_by_cache
508
512
  end
509
513
 
510
514
  def nested?
@@ -586,7 +590,6 @@ module ActiveRecord
586
590
  end
587
591
 
588
592
  private
589
-
590
593
  def calculate_constructable(macro, options)
591
594
  true
592
595
  end
@@ -616,7 +619,7 @@ module ActiveRecord
616
619
  end
617
620
 
618
621
  if valid_inverse_reflection?(reflection)
619
- return inverse_name
622
+ inverse_name
620
623
  end
621
624
  end
622
625
  end
@@ -700,7 +703,6 @@ module ActiveRecord
700
703
  end
701
704
 
702
705
  private
703
-
704
706
  def calculate_constructable(macro, options)
705
707
  !options[:through]
706
708
  end
@@ -835,8 +837,8 @@ module ActiveRecord
835
837
  source_reflection.scopes + super
836
838
  end
837
839
 
838
- def join_scopes(table, predicate_builder) # :nodoc:
839
- source_reflection.join_scopes(table, predicate_builder) + super
840
+ def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
841
+ source_reflection.join_scopes(table, predicate_builder, klass) + super
840
842
  end
841
843
 
842
844
  def has_scope?
@@ -961,16 +963,14 @@ module ActiveRecord
961
963
  collect_join_reflections(seed + [self])
962
964
  end
963
965
 
964
- # TODO Change this to private once we've dropped Ruby 2.2 support.
965
- # Workaround for Ruby 2.2 "private attribute?" warning.
966
966
  protected
967
- attr_reader :delegate_reflection
968
-
969
967
  def actual_source_reflection # FIXME: this is a horrible name
970
968
  source_reflection.actual_source_reflection
971
969
  end
972
970
 
973
971
  private
972
+ attr_reader :delegate_reflection
973
+
974
974
  def collect_join_reflections(seed)
975
975
  a = source_reflection.add_as_source seed
976
976
  if options[:source_type]
@@ -1001,9 +1001,9 @@ module ActiveRecord
1001
1001
  @previous_reflection = previous_reflection
1002
1002
  end
1003
1003
 
1004
- def join_scopes(table, predicate_builder) # :nodoc:
1004
+ def join_scopes(table, predicate_builder, klass = self.klass) # :nodoc:
1005
1005
  scopes = @previous_reflection.join_scopes(table, predicate_builder) + super
1006
- scopes << build_scope(table, predicate_builder).instance_exec(nil, &source_type_scope)
1006
+ scopes << build_scope(table, predicate_builder, klass).instance_exec(nil, &source_type_scope)
1007
1007
  end
1008
1008
 
1009
1009
  def constraints
@@ -251,25 +251,27 @@ 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
  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
262
+ relation = apply_start_limit(relation, start) if start
263
+ relation = apply_finish_limit(relation, finish) if finish
270
264
  relation
271
265
  end
272
266
 
267
+ def apply_start_limit(relation, start)
268
+ relation.where(bind_attribute(primary_key, start) { |attr, bind| attr.gteq(bind) })
269
+ end
270
+
271
+ def apply_finish_limit(relation, finish)
272
+ relation.where(bind_attribute(primary_key, finish) { |attr, bind| attr.lteq(bind) })
273
+ end
274
+
273
275
  def batch_order
274
276
  arel_attribute(primary_key).asc
275
277
  end