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
@@ -21,7 +21,7 @@ module ActiveRecord
21
21
  # ]
22
22
  #
23
23
  # # Get an array of hashes representing the result (column => value):
24
- # result.to_hash
24
+ # result.to_a
25
25
  # # => [{"id" => 1, "title" => "title_1", "body" => "body_1"},
26
26
  # {"id" => 2, "title" => "title_2", "body" => "body_2"},
27
27
  # ...
@@ -43,6 +43,11 @@ module ActiveRecord
43
43
  @column_types = column_types
44
44
  end
45
45
 
46
+ # Returns true if this result set includes the column named +name+
47
+ def includes_column?(name)
48
+ @columns.include? name
49
+ end
50
+
46
51
  # Returns the number of elements in the rows array.
47
52
  def length
48
53
  @rows.length
@@ -60,9 +65,12 @@ module ActiveRecord
60
65
  end
61
66
  end
62
67
 
63
- # Returns an array of hashes representing each row record.
64
68
  def to_hash
65
- hash_rows
69
+ ActiveSupport::Deprecation.warn(<<-MSG.squish)
70
+ `ActiveRecord::Result#to_hash` has been renamed to `to_a`.
71
+ `to_hash` is deprecated and will be removed in Rails 6.1.
72
+ MSG
73
+ to_a
66
74
  end
67
75
 
68
76
  alias :map! :map
@@ -78,6 +86,8 @@ module ActiveRecord
78
86
  hash_rows
79
87
  end
80
88
 
89
+ alias :to_a :to_ary
90
+
81
91
  def [](idx)
82
92
  hash_rows[idx]
83
93
  end
@@ -97,12 +107,21 @@ module ActiveRecord
97
107
  end
98
108
 
99
109
  def cast_values(type_overrides = {}) # :nodoc:
100
- types = columns.map { |name| column_type(name, type_overrides) }
101
- result = rows.map do |values|
102
- types.zip(values).map { |type, value| type.deserialize(value) }
103
- end
110
+ if columns.one?
111
+ # Separated to avoid allocating an array per row
104
112
 
105
- columns.one? ? result.map!(&:first) : result
113
+ type = column_type(columns.first, type_overrides)
114
+
115
+ rows.map do |(value)|
116
+ type.deserialize(value)
117
+ end
118
+ else
119
+ types = columns.map { |name| column_type(name, type_overrides) }
120
+
121
+ rows.map do |values|
122
+ Array.new(values.size) { |i| types[i].deserialize(values[i]) }
123
+ end
124
+ end
106
125
  end
107
126
 
108
127
  def initialize_copy(other)
@@ -113,7 +132,6 @@ module ActiveRecord
113
132
  end
114
133
 
115
134
  private
116
-
117
135
  def column_type(name, type_overrides = {})
118
136
  type_overrides.fetch(name) do
119
137
  column_types.fetch(name, Type.default_value)
@@ -125,7 +143,9 @@ module ActiveRecord
125
143
  begin
126
144
  # We freeze the strings to prevent them getting duped when
127
145
  # used as keys in ActiveRecord::Base's @attributes hash
128
- columns = @columns.map { |c| c.dup.freeze }
146
+ columns = @columns.map(&:-@)
147
+ length = columns.length
148
+
129
149
  @rows.map { |row|
130
150
  # In the past we used Hash[columns.zip(row)]
131
151
  # though elegant, the verbose way is much more efficient
@@ -134,8 +154,6 @@ module ActiveRecord
134
154
  hash = {}
135
155
 
136
156
  index = 0
137
- length = columns.length
138
-
139
157
  while index < length
140
158
  hash[columns[index]] = row[index]
141
159
  index += 1
@@ -61,8 +61,9 @@ module ActiveRecord
61
61
  # # => "id ASC"
62
62
  def sanitize_sql_for_order(condition)
63
63
  if condition.is_a?(Array) && condition.first.to_s.include?("?")
64
- enforce_raw_sql_whitelist([condition.first],
65
- whitelist: AttributeMethods::ClassMethods::COLUMN_NAME_ORDER_WHITELIST
64
+ disallow_raw_sql!(
65
+ [condition.first],
66
+ permit: connection.column_name_with_order_matcher
66
67
  )
67
68
 
68
69
  # Ensure we aren't dealing with a subclass of String that might
@@ -133,44 +134,34 @@ module ActiveRecord
133
134
  end
134
135
  end
135
136
 
136
- private
137
- # Accepts a hash of SQL conditions and replaces those attributes
138
- # that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
139
- # relationship with their expanded aggregate attribute values.
140
- #
141
- # Given:
142
- #
143
- # class Person < ActiveRecord::Base
144
- # composed_of :address, class_name: "Address",
145
- # mapping: [%w(address_street street), %w(address_city city)]
146
- # end
147
- #
148
- # Then:
149
- #
150
- # { address: Address.new("813 abc st.", "chicago") }
151
- # # => { address_street: "813 abc st.", address_city: "chicago" }
152
- def expand_hash_conditions_for_aggregates(attrs) # :doc:
153
- expanded_attrs = {}
154
- attrs.each do |attr, value|
155
- if aggregation = reflect_on_aggregation(attr.to_sym)
156
- mapping = aggregation.mapping
157
- mapping.each do |field_attr, aggregate_attr|
158
- expanded_attrs[field_attr] = if value.is_a?(Array)
159
- value.map { |it| it.send(aggregate_attr) }
160
- elsif mapping.size == 1 && !value.respond_to?(aggregate_attr)
161
- value
162
- else
163
- value.send(aggregate_attr)
164
- end
165
- end
166
- else
167
- expanded_attrs[attr] = value
168
- end
169
- end
170
- expanded_attrs
137
+ def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
138
+ unexpected = nil
139
+ args.each do |arg|
140
+ next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
141
+ (unexpected ||= []) << arg
171
142
  end
172
- deprecate :expand_hash_conditions_for_aggregates
173
143
 
144
+ return unless unexpected
145
+
146
+ if allow_unsafe_raw_sql == :deprecated
147
+ ActiveSupport::Deprecation.warn(
148
+ "Dangerous query method (method whose arguments are used as raw " \
149
+ "SQL) called with non-attribute argument(s): " \
150
+ "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
151
+ "arguments will be disallowed in Rails 6.1. This method should " \
152
+ "not be called with user-provided values, such as request " \
153
+ "parameters or model attributes. Known-safe values can be passed " \
154
+ "by wrapping them in Arel.sql()."
155
+ )
156
+ else
157
+ raise(ActiveRecord::UnknownAttributeReference,
158
+ "Query method called with non-attribute argument(s): " +
159
+ unexpected.map(&:inspect).join(", ")
160
+ )
161
+ end
162
+ end
163
+
164
+ private
174
165
  def replace_bind_variables(statement, values)
175
166
  raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
176
167
  bound = values.dup
@@ -202,10 +193,11 @@ module ActiveRecord
202
193
 
203
194
  def quote_bound_value(value, c = connection)
204
195
  if value.respond_to?(:map) && !value.acts_like?(:string)
205
- if value.respond_to?(:empty?) && value.empty?
196
+ quoted = value.map { |v| c.quote(v) }
197
+ if quoted.empty?
206
198
  c.quote(nil)
207
199
  else
208
- value.map { |v| c.quote(v) }.join(",")
200
+ quoted.join(",")
209
201
  end
210
202
  else
211
203
  c.quote(value)
@@ -50,21 +50,12 @@ module ActiveRecord
50
50
  instance_eval(&block)
51
51
 
52
52
  if info[:version].present?
53
- ActiveRecord::SchemaMigration.create_table
54
- connection.assume_migrated_upto_version(info[:version], migrations_paths)
53
+ connection.schema_migration.create_table
54
+ connection.assume_migrated_upto_version(info[:version])
55
55
  end
56
56
 
57
57
  ActiveRecord::InternalMetadata.create_table
58
58
  ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
59
59
  end
60
-
61
- private
62
- # Returns the migrations paths.
63
- #
64
- # ActiveRecord::Schema.new.migrations_paths
65
- # # => ["db/migrate"] # Rails migration path by default.
66
- def migrations_paths
67
- ActiveRecord::Migrator.migrations_paths
68
- end
69
60
  end
70
61
  end
@@ -17,6 +17,12 @@ module ActiveRecord
17
17
  # Only strings are accepted if ActiveRecord::Base.schema_format == :sql.
18
18
  cattr_accessor :ignore_tables, default: []
19
19
 
20
+ ##
21
+ # :singleton-method:
22
+ # Specify a custom regular expression matching foreign keys which name
23
+ # should not be dumped to db/schema.rb.
24
+ cattr_accessor :fk_ignore_pattern, default: /^fk_rails_[0-9a-f]{10}$/
25
+
20
26
  class << self
21
27
  def dump(connection = ActiveRecord::Base.connection, stream = STDOUT, config = ActiveRecord::Base)
22
28
  connection.create_schema_dumper(generate_options(config)).dump(stream)
@@ -41,6 +47,7 @@ module ActiveRecord
41
47
  end
42
48
 
43
49
  private
50
+ attr_accessor :table_name
44
51
 
45
52
  def initialize(connection, options = {})
46
53
  @connection = connection
@@ -65,11 +72,11 @@ module ActiveRecord
65
72
  # of editing this file, please use the migrations feature of Active Record to
66
73
  # incrementally modify your database, and then regenerate this schema definition.
67
74
  #
68
- # Note that this schema.rb definition is the authoritative source for your
69
- # database schema. If you need to create the application database on another
70
- # system, you should be using db:schema:load, not running all the migrations
71
- # from scratch. The latter is a flawed and unsustainable approach (the more migrations
72
- # you'll amass, the slower it'll run and the greater likelihood for issues).
75
+ # This file is the source Rails uses to define your schema when running `rails
76
+ # db:schema:load`. When creating a new database, `rails db:schema:load` tends to
77
+ # be faster and is potentially less error prone than running all of your
78
+ # migrations from scratch. Old migrations may fail to apply correctly if those
79
+ # migrations use external dependencies or application code.
73
80
  #
74
81
  # It's strongly recommended that you check this file into your version control system.
75
82
 
@@ -104,6 +111,8 @@ HEADER
104
111
  def table(table, stream)
105
112
  columns = @connection.columns(table)
106
113
  begin
114
+ self.table_name = table
115
+
107
116
  tbl = StringIO.new
108
117
 
109
118
  # first dump primary key column
@@ -137,7 +146,11 @@ HEADER
137
146
  raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
138
147
  next if column.name == pk
139
148
  type, colspec = column_spec(column)
140
- tbl.print " t.#{type} #{column.name.inspect}"
149
+ if type.is_a?(Symbol)
150
+ tbl.print " t.#{type} #{column.name.inspect}"
151
+ else
152
+ tbl.print " t.column #{column.name.inspect}, #{type.inspect}"
153
+ end
141
154
  tbl.print ", #{format_colspec(colspec)}" if colspec.present?
142
155
  tbl.puts
143
156
  end
@@ -153,6 +166,8 @@ HEADER
153
166
  stream.puts "# Could not dump table #{table.inspect} because of following #{e.class}"
154
167
  stream.puts "# #{e.message}"
155
168
  stream.puts
169
+ ensure
170
+ self.table_name = nil
156
171
  end
157
172
  end
158
173
 
@@ -210,7 +225,7 @@ HEADER
210
225
  parts << "primary_key: #{foreign_key.primary_key.inspect}"
211
226
  end
212
227
 
213
- if foreign_key.name !~ /^fk_rails_[0-9a-f]{10}$/
228
+ if foreign_key.export_name_on_schema_dump?
214
229
  parts << "name: #{foreign_key.name.inspect}"
215
230
  end
216
231
 
@@ -10,12 +10,16 @@ module ActiveRecord
10
10
  # to be executed the next time.
11
11
  class SchemaMigration < ActiveRecord::Base # :nodoc:
12
12
  class << self
13
+ def _internal?
14
+ true
15
+ end
16
+
13
17
  def primary_key
14
18
  "version"
15
19
  end
16
20
 
17
21
  def table_name
18
- "#{table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{table_name_suffix}"
22
+ "#{table_name_prefix}#{schema_migrations_table_name}#{table_name_suffix}"
19
23
  end
20
24
 
21
25
  def table_exists?
@@ -27,7 +31,7 @@ module ActiveRecord
27
31
  version_options = connection.internal_string_options_for_primary_key
28
32
 
29
33
  connection.create_table(table_name, id: false) do |t|
30
- t.string :version, version_options
34
+ t.string :version, **version_options
31
35
  end
32
36
  end
33
37
  end
@@ -44,7 +44,6 @@ module ActiveRecord
44
44
  end
45
45
 
46
46
  private
47
-
48
47
  # Use this macro in your model to set a default scope for all operations on
49
48
  # the model.
50
49
  #
@@ -100,7 +99,7 @@ module ActiveRecord
100
99
  self.default_scopes += [scope]
101
100
  end
102
101
 
103
- def build_default_scope(base_rel = nil)
102
+ def build_default_scope(relation = relation())
104
103
  return if abstract_class?
105
104
 
106
105
  if default_scope_override.nil?
@@ -111,15 +110,14 @@ module ActiveRecord
111
110
  # The user has defined their own default scope method, so call that
112
111
  evaluate_default_scope do
113
112
  if scope = default_scope
114
- (base_rel ||= relation).merge!(scope)
113
+ relation.merge!(scope)
115
114
  end
116
115
  end
117
116
  elsif default_scopes.any?
118
- base_rel ||= relation
119
117
  evaluate_default_scope do
120
- default_scopes.inject(base_rel) do |default_scope, scope|
118
+ default_scopes.inject(relation) do |default_scope, scope|
121
119
  scope = scope.respond_to?(:to_proc) ? scope : scope.method(:call)
122
- default_scope.merge!(base_rel.instance_exec(&scope))
120
+ default_scope.instance_exec(&scope) || default_scope
123
121
  end
124
122
  end
125
123
  end
@@ -24,13 +24,21 @@ module ActiveRecord
24
24
  # You can define a scope that applies to all finders using
25
25
  # {default_scope}[rdoc-ref:Scoping::Default::ClassMethods#default_scope].
26
26
  def all
27
- current_scope = self.current_scope
27
+ scope = current_scope
28
+
29
+ if scope
30
+ if scope._deprecated_scope_source
31
+ ActiveSupport::Deprecation.warn(<<~MSG.squish)
32
+ Class level methods will no longer inherit scoping from `#{scope._deprecated_scope_source}`
33
+ in Rails 6.1. To continue using the scoped relation, pass it into the block directly.
34
+ To instead access the full set of models, as Rails 6.1 will, use `#{name}.default_scoped`.
35
+ MSG
36
+ end
28
37
 
29
- if current_scope
30
- if self == current_scope.klass
31
- current_scope.clone
38
+ if self == scope.klass
39
+ scope.clone
32
40
  else
33
- relation.merge!(current_scope)
41
+ relation.merge!(scope)
34
42
  end
35
43
  else
36
44
  default_scoped
@@ -38,21 +46,20 @@ module ActiveRecord
38
46
  end
39
47
 
40
48
  def scope_for_association(scope = relation) # :nodoc:
41
- current_scope = self.current_scope
42
-
43
- if current_scope && current_scope.empty_scope?
49
+ if current_scope&.empty_scope?
44
50
  scope
45
51
  else
46
52
  default_scoped(scope)
47
53
  end
48
54
  end
49
55
 
50
- def default_scoped(scope = relation) # :nodoc:
56
+ # Returns a scope for the model with default scopes.
57
+ def default_scoped(scope = relation)
51
58
  build_default_scope(scope) || scope
52
59
  end
53
60
 
54
61
  def default_extensions # :nodoc:
55
- if scope = current_scope || build_default_scope
62
+ if scope = scope_for_association || build_default_scope
56
63
  scope.extensions
57
64
  else
58
65
  []
@@ -181,25 +188,27 @@ module ActiveRecord
181
188
  extension = Module.new(&block) if block
182
189
 
183
190
  if body.respond_to?(:to_proc)
184
- singleton_class.send(:define_method, name) do |*args|
185
- scope = all
186
- scope = scope._exec_scope(*args, &body)
191
+ singleton_class.define_method(name) do |*args|
192
+ scope = all._exec_scope(name, *args, &body)
187
193
  scope = scope.extending(extension) if extension
188
194
  scope
189
195
  end
190
196
  else
191
- singleton_class.send(:define_method, name) do |*args|
192
- scope = all
193
- scope = scope.scoping { body.call(*args) || scope }
197
+ singleton_class.define_method(name) do |*args|
198
+ scope = body.call(*args) || all
194
199
  scope = scope.extending(extension) if extension
195
200
  scope
196
201
  end
197
202
  end
203
+ singleton_class.send(:ruby2_keywords, name) if respond_to?(:ruby2_keywords, true)
198
204
 
199
205
  generate_relation_method(name)
200
206
  end
201
207
 
202
208
  private
209
+ def singleton_method_added(name)
210
+ generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
211
+ end
203
212
 
204
213
  def valid_scope_name?(name)
205
214
  if respond_to?(name, true) && logger
@@ -12,14 +12,6 @@ module ActiveRecord
12
12
  end
13
13
 
14
14
  module ClassMethods # :nodoc:
15
- def current_scope(skip_inherited_scope = false)
16
- ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
17
- end
18
-
19
- def current_scope=(scope)
20
- ScopeRegistry.set_value_for(:current_scope, self, scope)
21
- end
22
-
23
15
  # Collects attributes from scopes that should be applied when creating
24
16
  # an AR instance for the particular class this is called on.
25
17
  def scope_attributes
@@ -30,6 +22,14 @@ module ActiveRecord
30
22
  def scope_attributes?
31
23
  current_scope
32
24
  end
25
+
26
+ def current_scope(skip_inherited_scope = false)
27
+ ScopeRegistry.value_for(:current_scope, self, skip_inherited_scope)
28
+ end
29
+
30
+ def current_scope=(scope)
31
+ ScopeRegistry.set_value_for(:current_scope, self, scope)
32
+ end
33
33
  end
34
34
 
35
35
  def populate_with_current_scope_attributes # :nodoc:
@@ -95,7 +95,6 @@ module ActiveRecord
95
95
  end
96
96
 
97
97
  private
98
-
99
98
  def raise_invalid_scope_type!(scope_type)
100
99
  if !VALID_SCOPE_TYPES.include?(scope_type)
101
100
  raise ArgumentError, "Invalid scope type '#{scope_type}' sent to the registry. Scope types must be included in VALID_SCOPE_TYPES"
@@ -44,7 +44,7 @@ module ActiveRecord
44
44
  def initialize(values)
45
45
  @values = values
46
46
  @indexes = values.each_with_index.find_all { |thing, i|
47
- Arel::Nodes::BindParam === thing
47
+ Substitute === thing
48
48
  }.map(&:last)
49
49
  end
50
50
 
@@ -56,6 +56,28 @@ module ActiveRecord
56
56
  end
57
57
  end
58
58
 
59
+ class PartialQueryCollector
60
+ def initialize
61
+ @parts = []
62
+ @binds = []
63
+ end
64
+
65
+ def <<(str)
66
+ @parts << str
67
+ self
68
+ end
69
+
70
+ def add_bind(obj)
71
+ @binds << obj
72
+ @parts << Substitute.new
73
+ self
74
+ end
75
+
76
+ def value
77
+ [@parts, @binds]
78
+ end
79
+ end
80
+
59
81
  def self.query(sql)
60
82
  Query.new(sql)
61
83
  end
@@ -64,6 +86,10 @@ module ActiveRecord
64
86
  PartialQuery.new(values)
65
87
  end
66
88
 
89
+ def self.partial_query_collector
90
+ PartialQueryCollector.new
91
+ end
92
+
67
93
  class Params # :nodoc:
68
94
  def bind; Substitute.new; end
69
95
  end
@@ -106,6 +132,8 @@ module ActiveRecord
106
132
  sql = query_builder.sql_for bind_values, connection
107
133
 
108
134
  klass.find_by_sql(sql, bind_values, preparable: true, &block)
135
+ rescue ::RangeError
136
+ nil
109
137
  end
110
138
 
111
139
  def self.unsupported_value?(value)
@@ -114,8 +142,7 @@ module ActiveRecord
114
142
  end
115
143
  end
116
144
 
117
- protected
118
-
145
+ private
119
146
  attr_reader :query_builder, :bind_map, :klass
120
147
  end
121
148
  end