activerecord 5.0.7 → 5.1.7

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 (219) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -2080
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/examples/performance.rb +28 -28
  6. data/examples/simple.rb +3 -3
  7. data/lib/active_record/aggregations.rb +244 -244
  8. data/lib/active_record/association_relation.rb +5 -5
  9. data/lib/active_record/associations/alias_tracker.rb +10 -11
  10. data/lib/active_record/associations/association.rb +23 -5
  11. data/lib/active_record/associations/association_scope.rb +95 -81
  12. data/lib/active_record/associations/belongs_to_association.rb +7 -4
  13. data/lib/active_record/associations/builder/belongs_to.rb +30 -16
  14. data/lib/active_record/associations/builder/collection_association.rb +1 -2
  15. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +27 -27
  16. data/lib/active_record/associations/collection_association.rb +36 -205
  17. data/lib/active_record/associations/collection_proxy.rb +132 -63
  18. data/lib/active_record/associations/has_many_association.rb +10 -19
  19. data/lib/active_record/associations/has_many_through_association.rb +12 -4
  20. data/lib/active_record/associations/has_one_association.rb +24 -28
  21. data/lib/active_record/associations/has_one_through_association.rb +5 -1
  22. data/lib/active_record/associations/join_dependency/join_association.rb +4 -28
  23. data/lib/active_record/associations/join_dependency/join_base.rb +1 -1
  24. data/lib/active_record/associations/join_dependency/join_part.rb +1 -1
  25. data/lib/active_record/associations/join_dependency.rb +121 -118
  26. data/lib/active_record/associations/preloader/association.rb +64 -64
  27. data/lib/active_record/associations/preloader/belongs_to.rb +0 -2
  28. data/lib/active_record/associations/preloader/collection_association.rb +6 -6
  29. data/lib/active_record/associations/preloader/has_many.rb +0 -2
  30. data/lib/active_record/associations/preloader/singular_association.rb +6 -8
  31. data/lib/active_record/associations/preloader/through_association.rb +41 -41
  32. data/lib/active_record/associations/preloader.rb +94 -94
  33. data/lib/active_record/associations/singular_association.rb +8 -25
  34. data/lib/active_record/associations/through_association.rb +2 -5
  35. data/lib/active_record/associations.rb +1591 -1562
  36. data/lib/active_record/attribute/user_provided_default.rb +4 -2
  37. data/lib/active_record/attribute.rb +98 -71
  38. data/lib/active_record/attribute_assignment.rb +61 -61
  39. data/lib/active_record/attribute_decorators.rb +35 -13
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +7 -7
  41. data/lib/active_record/attribute_methods/dirty.rb +229 -46
  42. data/lib/active_record/attribute_methods/primary_key.rb +74 -73
  43. data/lib/active_record/attribute_methods/read.rb +39 -35
  44. data/lib/active_record/attribute_methods/serialization.rb +7 -7
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +35 -58
  46. data/lib/active_record/attribute_methods/write.rb +30 -33
  47. data/lib/active_record/attribute_methods.rb +56 -65
  48. data/lib/active_record/attribute_mutation_tracker.rb +63 -11
  49. data/lib/active_record/attribute_set/builder.rb +27 -33
  50. data/lib/active_record/attribute_set/yaml_encoder.rb +41 -0
  51. data/lib/active_record/attribute_set.rb +9 -6
  52. data/lib/active_record/attributes.rb +22 -22
  53. data/lib/active_record/autosave_association.rb +18 -13
  54. data/lib/active_record/base.rb +24 -22
  55. data/lib/active_record/callbacks.rb +56 -14
  56. data/lib/active_record/coders/yaml_column.rb +9 -11
  57. data/lib/active_record/collection_cache_key.rb +3 -4
  58. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +330 -284
  59. data/lib/active_record/connection_adapters/abstract/database_limits.rb +1 -3
  60. data/lib/active_record/connection_adapters/abstract/database_statements.rb +39 -37
  61. data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -27
  62. data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -51
  63. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +10 -20
  64. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +74 -79
  65. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +53 -41
  66. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +120 -100
  67. data/lib/active_record/connection_adapters/abstract/transaction.rb +49 -43
  68. data/lib/active_record/connection_adapters/abstract_adapter.rb +165 -135
  69. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +404 -424
  70. data/lib/active_record/connection_adapters/column.rb +26 -4
  71. data/lib/active_record/connection_adapters/connection_specification.rb +128 -118
  72. data/lib/active_record/connection_adapters/mysql/column.rb +6 -31
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -49
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +22 -22
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +6 -12
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +49 -45
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +16 -19
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -28
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +43 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +7 -6
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +23 -27
  82. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +32 -53
  83. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +3 -3
  84. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +19 -9
  85. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +5 -3
  86. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
  87. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -2
  88. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +1 -1
  89. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -3
  90. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +16 -16
  91. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +0 -10
  92. data/lib/active_record/connection_adapters/postgresql/oid/{rails_5_1_point.rb → legacy_point.rb} +9 -16
  93. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -2
  94. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +13 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +28 -8
  96. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +32 -30
  97. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +51 -51
  99. data/lib/active_record/connection_adapters/postgresql/oid.rb +22 -21
  100. data/lib/active_record/connection_adapters/postgresql/quoting.rb +40 -35
  101. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +15 -0
  102. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +37 -24
  103. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +19 -23
  104. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +182 -222
  105. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +6 -4
  106. data/lib/active_record/connection_adapters/postgresql/utils.rb +7 -5
  107. data/lib/active_record/connection_adapters/postgresql_adapter.rb +198 -167
  108. data/lib/active_record/connection_adapters/schema_cache.rb +16 -7
  109. data/lib/active_record/connection_adapters/sql_type_metadata.rb +3 -3
  110. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +1 -1
  111. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +16 -19
  112. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +1 -8
  113. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +28 -0
  114. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +17 -0
  115. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +32 -0
  116. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +184 -167
  117. data/lib/active_record/connection_adapters/statement_pool.rb +7 -7
  118. data/lib/active_record/connection_handling.rb +14 -26
  119. data/lib/active_record/core.rb +109 -93
  120. data/lib/active_record/counter_cache.rb +60 -13
  121. data/lib/active_record/define_callbacks.rb +20 -0
  122. data/lib/active_record/dynamic_matchers.rb +80 -79
  123. data/lib/active_record/enum.rb +8 -6
  124. data/lib/active_record/errors.rb +64 -15
  125. data/lib/active_record/explain.rb +1 -2
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +7 -4
  128. data/lib/active_record/fixture_set/file.rb +11 -8
  129. data/lib/active_record/fixtures.rb +66 -53
  130. data/lib/active_record/gem_version.rb +1 -1
  131. data/lib/active_record/inheritance.rb +93 -79
  132. data/lib/active_record/integration.rb +7 -7
  133. data/lib/active_record/internal_metadata.rb +3 -16
  134. data/lib/active_record/legacy_yaml_adapter.rb +1 -1
  135. data/lib/active_record/locking/optimistic.rb +69 -74
  136. data/lib/active_record/locking/pessimistic.rb +10 -1
  137. data/lib/active_record/log_subscriber.rb +23 -28
  138. data/lib/active_record/migration/command_recorder.rb +94 -94
  139. data/lib/active_record/migration/compatibility.rb +100 -47
  140. data/lib/active_record/migration/join_table.rb +6 -6
  141. data/lib/active_record/migration.rb +153 -155
  142. data/lib/active_record/model_schema.rb +94 -107
  143. data/lib/active_record/nested_attributes.rb +200 -199
  144. data/lib/active_record/null_relation.rb +11 -34
  145. data/lib/active_record/persistence.rb +65 -50
  146. data/lib/active_record/query_cache.rb +2 -6
  147. data/lib/active_record/querying.rb +3 -4
  148. data/lib/active_record/railtie.rb +16 -17
  149. data/lib/active_record/railties/controller_runtime.rb +6 -2
  150. data/lib/active_record/railties/databases.rake +105 -133
  151. data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
  152. data/lib/active_record/readonly_attributes.rb +2 -2
  153. data/lib/active_record/reflection.rb +154 -108
  154. data/lib/active_record/relation/batches/batch_enumerator.rb +1 -1
  155. data/lib/active_record/relation/batches.rb +80 -51
  156. data/lib/active_record/relation/calculations.rb +169 -162
  157. data/lib/active_record/relation/delegation.rb +32 -31
  158. data/lib/active_record/relation/finder_methods.rb +197 -231
  159. data/lib/active_record/relation/merger.rb +58 -62
  160. data/lib/active_record/relation/predicate_builder/array_handler.rb +7 -5
  161. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +23 -23
  162. data/lib/active_record/relation/predicate_builder/base_handler.rb +3 -1
  163. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +0 -8
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +12 -10
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +0 -8
  166. data/lib/active_record/relation/predicate_builder.rb +92 -89
  167. data/lib/active_record/relation/query_attribute.rb +1 -1
  168. data/lib/active_record/relation/query_methods.rb +255 -293
  169. data/lib/active_record/relation/record_fetch_warning.rb +3 -3
  170. data/lib/active_record/relation/spawn_methods.rb +4 -5
  171. data/lib/active_record/relation/where_clause.rb +80 -65
  172. data/lib/active_record/relation/where_clause_factory.rb +47 -8
  173. data/lib/active_record/relation.rb +93 -119
  174. data/lib/active_record/result.rb +41 -32
  175. data/lib/active_record/runtime_registry.rb +3 -3
  176. data/lib/active_record/sanitization.rb +176 -192
  177. data/lib/active_record/schema.rb +3 -3
  178. data/lib/active_record/schema_dumper.rb +15 -38
  179. data/lib/active_record/schema_migration.rb +8 -4
  180. data/lib/active_record/scoping/default.rb +90 -90
  181. data/lib/active_record/scoping/named.rb +11 -11
  182. data/lib/active_record/scoping.rb +6 -6
  183. data/lib/active_record/secure_token.rb +2 -2
  184. data/lib/active_record/statement_cache.rb +13 -15
  185. data/lib/active_record/store.rb +31 -32
  186. data/lib/active_record/suppressor.rb +2 -1
  187. data/lib/active_record/table_metadata.rb +9 -5
  188. data/lib/active_record/tasks/database_tasks.rb +65 -55
  189. data/lib/active_record/tasks/mysql_database_tasks.rb +76 -73
  190. data/lib/active_record/tasks/postgresql_database_tasks.rb +72 -47
  191. data/lib/active_record/tasks/sqlite_database_tasks.rb +18 -16
  192. data/lib/active_record/timestamp.rb +46 -25
  193. data/lib/active_record/touch_later.rb +1 -2
  194. data/lib/active_record/transactions.rb +97 -109
  195. data/lib/active_record/type/adapter_specific_registry.rb +46 -42
  196. data/lib/active_record/type/decimal_without_scale.rb +13 -0
  197. data/lib/active_record/type/hash_lookup_type_map.rb +3 -3
  198. data/lib/active_record/type/internal/abstract_json.rb +4 -0
  199. data/lib/active_record/type/serialized.rb +14 -8
  200. data/lib/active_record/type/text.rb +9 -0
  201. data/lib/active_record/type/time.rb +0 -1
  202. data/lib/active_record/type/type_map.rb +11 -15
  203. data/lib/active_record/type/unsigned_integer.rb +15 -0
  204. data/lib/active_record/type.rb +17 -13
  205. data/lib/active_record/type_caster/connection.rb +8 -6
  206. data/lib/active_record/type_caster/map.rb +3 -1
  207. data/lib/active_record/type_caster.rb +2 -2
  208. data/lib/active_record/validations/associated.rb +1 -1
  209. data/lib/active_record/validations/presence.rb +2 -2
  210. data/lib/active_record/validations/uniqueness.rb +8 -39
  211. data/lib/active_record/validations.rb +4 -4
  212. data/lib/active_record/version.rb +1 -1
  213. data/lib/active_record.rb +20 -20
  214. data/lib/rails/generators/active_record/migration/migration_generator.rb +37 -34
  215. data/lib/rails/generators/active_record/migration.rb +1 -1
  216. data/lib/rails/generators/active_record/model/model_generator.rb +9 -9
  217. data/lib/rails/generators/active_record.rb +4 -4
  218. metadata +24 -13
  219. data/lib/active_record/relation/predicate_builder/class_handler.rb +0 -27
@@ -32,8 +32,6 @@ module ActiveRecord
32
32
  class Result
33
33
  include Enumerable
34
34
 
35
- IDENTITY_TYPE = Type::Value.new # :nodoc:
36
-
37
35
  attr_reader :columns, :rows, :column_types
38
36
 
39
37
  def initialize(columns, rows, column_types = {})
@@ -43,10 +41,15 @@ module ActiveRecord
43
41
  @column_types = column_types
44
42
  end
45
43
 
44
+ # Returns the number of elements in the rows array.
46
45
  def length
47
46
  @rows.length
48
47
  end
49
48
 
49
+ # Calls the given block once for each element in row collection, passing
50
+ # row as parameter.
51
+ #
52
+ # Returns an +Enumerator+ if no block is given.
50
53
  def each
51
54
  if block_given?
52
55
  hash_rows.each { |row| yield row }
@@ -55,6 +58,7 @@ module ActiveRecord
55
58
  end
56
59
  end
57
60
 
61
+ # Returns an array of hashes representing each row record.
58
62
  def to_hash
59
63
  hash_rows
60
64
  end
@@ -62,11 +66,12 @@ module ActiveRecord
62
66
  alias :map! :map
63
67
  alias :collect! :map
64
68
 
65
- # Returns true if there are no records.
69
+ # Returns true if there are no records, otherwise false.
66
70
  def empty?
67
71
  rows.empty?
68
72
  end
69
73
 
74
+ # Returns an array of hashes representing each row record.
70
75
  def to_ary
71
76
  hash_rows
72
77
  end
@@ -75,11 +80,15 @@ module ActiveRecord
75
80
  hash_rows[idx]
76
81
  end
77
82
 
83
+ # Returns the first record from the rows collection.
84
+ # If the rows collection is empty, returns +nil+.
78
85
  def first
79
86
  return nil if @rows.empty?
80
87
  Hash[@columns.zip(@rows.first)]
81
88
  end
82
89
 
90
+ # Returns the last record from the rows collection.
91
+ # If the rows collection is empty, returns +nil+.
83
92
  def last
84
93
  return nil if @rows.empty?
85
94
  Hash[@columns.zip(@rows.last)]
@@ -103,36 +112,36 @@ module ActiveRecord
103
112
 
104
113
  private
105
114
 
106
- def column_type(name, type_overrides = {})
107
- type_overrides.fetch(name) do
108
- column_types.fetch(name, IDENTITY_TYPE)
115
+ def column_type(name, type_overrides = {})
116
+ type_overrides.fetch(name) do
117
+ column_types.fetch(name, Type.default_value)
118
+ end
109
119
  end
110
- end
111
120
 
112
- def hash_rows
113
- @hash_rows ||=
114
- begin
115
- # We freeze the strings to prevent them getting duped when
116
- # used as keys in ActiveRecord::Base's @attributes hash
117
- columns = @columns.map { |c| c.dup.freeze }
118
- @rows.map { |row|
119
- # In the past we used Hash[columns.zip(row)]
120
- # though elegant, the verbose way is much more efficient
121
- # both time and memory wise cause it avoids a big array allocation
122
- # this method is called a lot and needs to be micro optimised
123
- hash = {}
124
-
125
- index = 0
126
- length = columns.length
127
-
128
- while index < length
129
- hash[columns[index]] = row[index]
130
- index += 1
131
- end
132
-
133
- hash
134
- }
135
- end
136
- end
121
+ def hash_rows
122
+ @hash_rows ||=
123
+ begin
124
+ # We freeze the strings to prevent them getting duped when
125
+ # used as keys in ActiveRecord::Base's @attributes hash
126
+ columns = @columns.map { |c| c.dup.freeze }
127
+ @rows.map { |row|
128
+ # In the past we used Hash[columns.zip(row)]
129
+ # though elegant, the verbose way is much more efficient
130
+ # both time and memory wise cause it avoids a big array allocation
131
+ # this method is called a lot and needs to be micro optimised
132
+ hash = {}
133
+
134
+ index = 0
135
+ length = columns.length
136
+
137
+ while index < length
138
+ hash[columns[index]] = row[index]
139
+ index += 1
140
+ end
141
+
142
+ hash
143
+ }
144
+ end
145
+ end
137
146
  end
138
147
  end
@@ -1,4 +1,4 @@
1
- require 'active_support/per_thread_registry'
1
+ require "active_support/per_thread_registry"
2
2
 
3
3
  module ActiveRecord
4
4
  # This is a thread locals registry for Active Record. For example:
@@ -12,9 +12,9 @@ module ActiveRecord
12
12
  class RuntimeRegistry # :nodoc:
13
13
  extend ActiveSupport::PerThreadRegistry
14
14
 
15
- attr_accessor :connection_handler, :sql_runtime, :connection_id
15
+ attr_accessor :connection_handler, :sql_runtime
16
16
 
17
- [:connection_handler, :sql_runtime, :connection_id].each do |val|
17
+ [:connection_handler, :sql_runtime].each do |val|
18
18
  class_eval %{ def self.#{val}; instance.#{val}; end }, __FILE__, __LINE__
19
19
  class_eval %{ def self.#{val}=(x); instance.#{val}=x; end }, __FILE__, __LINE__
20
20
  end
@@ -3,228 +3,212 @@ module ActiveRecord
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  module ClassMethods
6
- # Used to sanitize objects before they're used in an SQL SELECT statement.
7
- # Delegates to {connection.quote}[rdoc-ref:ConnectionAdapters::Quoting#quote].
8
- def sanitize(object) # :nodoc:
9
- connection.quote(object)
10
- end
11
- alias_method :quote_value, :sanitize
12
-
13
- protected
14
-
15
- # Accepts an array or string of SQL conditions and sanitizes
16
- # them into a valid SQL fragment for a WHERE clause.
17
- #
18
- # sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
19
- # # => "name='foo''bar' and group_id=4"
20
- #
21
- # sanitize_sql_for_conditions(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
22
- # # => "name='foo''bar' and group_id='4'"
23
- #
24
- # sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
25
- # # => "name='foo''bar' and group_id='4'"
26
- #
27
- # sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
28
- # # => "name='foo''bar' and group_id='4'"
29
- def sanitize_sql_for_conditions(condition)
30
- return nil if condition.blank?
31
-
32
- case condition
33
- when Array; sanitize_sql_array(condition)
34
- else condition
6
+ private
7
+
8
+ # Accepts an array or string of SQL conditions and sanitizes
9
+ # them into a valid SQL fragment for a WHERE clause.
10
+ #
11
+ # sanitize_sql_for_conditions(["name=? and group_id=?", "foo'bar", 4])
12
+ # # => "name='foo''bar' and group_id=4"
13
+ #
14
+ # sanitize_sql_for_conditions(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
15
+ # # => "name='foo''bar' and group_id='4'"
16
+ #
17
+ # sanitize_sql_for_conditions(["name='%s' and group_id='%s'", "foo'bar", 4])
18
+ # # => "name='foo''bar' and group_id='4'"
19
+ #
20
+ # sanitize_sql_for_conditions("name='foo''bar' and group_id='4'")
21
+ # # => "name='foo''bar' and group_id='4'"
22
+ def sanitize_sql_for_conditions(condition) # :doc:
23
+ return nil if condition.blank?
24
+
25
+ case condition
26
+ when Array; sanitize_sql_array(condition)
27
+ else condition
28
+ end
35
29
  end
36
- end
37
- alias_method :sanitize_sql, :sanitize_sql_for_conditions
38
- alias_method :sanitize_conditions, :sanitize_sql
39
-
40
- # Accepts an array, hash, or string of SQL conditions and sanitizes
41
- # them into a valid SQL fragment for a SET clause.
42
- #
43
- # sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
44
- # # => "name=NULL and group_id=4"
45
- #
46
- # sanitize_sql_for_assignment(["name=:name and group_id=:group_id", name: nil, group_id: 4])
47
- # # => "name=NULL and group_id=4"
48
- #
49
- # Post.send(:sanitize_sql_for_assignment, { name: nil, group_id: 4 })
50
- # # => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
51
- #
52
- # sanitize_sql_for_assignment("name=NULL and group_id='4'")
53
- # # => "name=NULL and group_id='4'"
54
- def sanitize_sql_for_assignment(assignments, default_table_name = self.table_name)
55
- case assignments
56
- when Array; sanitize_sql_array(assignments)
57
- when Hash; sanitize_sql_hash_for_assignment(assignments, default_table_name)
58
- else assignments
30
+ alias :sanitize_sql :sanitize_sql_for_conditions
31
+ alias :sanitize_conditions :sanitize_sql
32
+ deprecate sanitize_conditions: :sanitize_sql
33
+
34
+ # Accepts an array, hash, or string of SQL conditions and sanitizes
35
+ # them into a valid SQL fragment for a SET clause.
36
+ #
37
+ # sanitize_sql_for_assignment(["name=? and group_id=?", nil, 4])
38
+ # # => "name=NULL and group_id=4"
39
+ #
40
+ # sanitize_sql_for_assignment(["name=:name and group_id=:group_id", name: nil, group_id: 4])
41
+ # # => "name=NULL and group_id=4"
42
+ #
43
+ # Post.send(:sanitize_sql_for_assignment, { name: nil, group_id: 4 })
44
+ # # => "`posts`.`name` = NULL, `posts`.`group_id` = 4"
45
+ #
46
+ # sanitize_sql_for_assignment("name=NULL and group_id='4'")
47
+ # # => "name=NULL and group_id='4'"
48
+ def sanitize_sql_for_assignment(assignments, default_table_name = table_name) # :doc:
49
+ case assignments
50
+ when Array; sanitize_sql_array(assignments)
51
+ when Hash; sanitize_sql_hash_for_assignment(assignments, default_table_name)
52
+ else assignments
53
+ end
59
54
  end
60
- end
61
55
 
62
- # Accepts an array, or string of SQL conditions and sanitizes
63
- # them into a valid SQL fragment for an ORDER clause.
64
- #
65
- # sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
66
- # # => "field(id, 1,3,2)"
67
- #
68
- # sanitize_sql_for_order("id ASC")
69
- # # => "id ASC"
70
- def sanitize_sql_for_order(condition)
71
- if condition.is_a?(Array) && condition.first.to_s.include?('?')
72
- sanitize_sql_array(condition)
73
- else
74
- condition
56
+ # Accepts an array, or string of SQL conditions and sanitizes
57
+ # them into a valid SQL fragment for an ORDER clause.
58
+ #
59
+ # sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
60
+ # # => "field(id, 1,3,2)"
61
+ #
62
+ # sanitize_sql_for_order("id ASC")
63
+ # # => "id ASC"
64
+ def sanitize_sql_for_order(condition) # :doc:
65
+ if condition.is_a?(Array) && condition.first.to_s.include?("?")
66
+ sanitize_sql_array(condition)
67
+ else
68
+ condition
69
+ end
75
70
  end
76
- end
77
71
 
78
- # Accepts a hash of SQL conditions and replaces those attributes
79
- # that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
80
- # relationship with their expanded aggregate attribute values.
81
- #
82
- # Given:
83
- #
84
- # class Person < ActiveRecord::Base
85
- # composed_of :address, class_name: "Address",
86
- # mapping: [%w(address_street street), %w(address_city city)]
87
- # end
88
- #
89
- # Then:
90
- #
91
- # { address: Address.new("813 abc st.", "chicago") }
92
- # # => { address_street: "813 abc st.", address_city: "chicago" }
93
- def expand_hash_conditions_for_aggregates(attrs)
94
- expanded_attrs = {}
95
- attrs.each do |attr, value|
96
- if aggregation = reflect_on_aggregation(attr.to_sym)
97
- mapping = aggregation.mapping
98
- mapping.each do |field_attr, aggregate_attr|
99
- if mapping.size == 1 && !value.respond_to?(aggregate_attr)
100
- expanded_attrs[field_attr] = value
101
- else
102
- expanded_attrs[field_attr] = value.send(aggregate_attr)
72
+ # Accepts a hash of SQL conditions and replaces those attributes
73
+ # that correspond to a {#composed_of}[rdoc-ref:Aggregations::ClassMethods#composed_of]
74
+ # relationship with their expanded aggregate attribute values.
75
+ #
76
+ # Given:
77
+ #
78
+ # class Person < ActiveRecord::Base
79
+ # composed_of :address, class_name: "Address",
80
+ # mapping: [%w(address_street street), %w(address_city city)]
81
+ # end
82
+ #
83
+ # Then:
84
+ #
85
+ # { address: Address.new("813 abc st.", "chicago") }
86
+ # # => { address_street: "813 abc st.", address_city: "chicago" }
87
+ def expand_hash_conditions_for_aggregates(attrs) # :doc:
88
+ expanded_attrs = {}
89
+ attrs.each do |attr, value|
90
+ if aggregation = reflect_on_aggregation(attr.to_sym)
91
+ mapping = aggregation.mapping
92
+ mapping.each do |field_attr, aggregate_attr|
93
+ if mapping.size == 1 && !value.respond_to?(aggregate_attr)
94
+ expanded_attrs[field_attr] = value
95
+ else
96
+ expanded_attrs[field_attr] = value.send(aggregate_attr)
97
+ end
103
98
  end
99
+ else
100
+ expanded_attrs[attr] = value
104
101
  end
105
- else
106
- expanded_attrs[attr] = value
107
102
  end
103
+ expanded_attrs
108
104
  end
109
- expanded_attrs
110
- end
111
105
 
112
- # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
113
- #
114
- # sanitize_sql_hash_for_assignment({ status: nil, group_id: 1 }, "posts")
115
- # # => "`posts`.`status` = NULL, `posts`.`group_id` = 1"
116
- def sanitize_sql_hash_for_assignment(attrs, table)
117
- c = connection
118
- attrs.map do |attr, value|
119
- if value.is_a?(Base)
120
- require "active_support/core_ext/string/filters"
121
- ActiveSupport::Deprecation.warn(<<-WARNING.squish)
122
- Passing `ActiveRecord::Base` objects to
123
- `sanitize_sql_hash_for_assignment` (or methods which call it,
124
- such as `update_all`) is deprecated. Please pass the id directly,
125
- instead.
126
- WARNING
127
- else
106
+ # Sanitizes a hash of attribute/value pairs into SQL conditions for a SET clause.
107
+ #
108
+ # sanitize_sql_hash_for_assignment({ status: nil, group_id: 1 }, "posts")
109
+ # # => "`posts`.`status` = NULL, `posts`.`group_id` = 1"
110
+ def sanitize_sql_hash_for_assignment(attrs, table) # :doc:
111
+ c = connection
112
+ attrs.map do |attr, value|
128
113
  value = type_for_attribute(attr.to_s).serialize(value)
129
- end
130
- "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
131
- end.join(', ')
132
- end
133
-
134
- # Sanitizes a +string+ so that it is safe to use within an SQL
135
- # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%".
136
- #
137
- # sanitize_sql_like("100%")
138
- # # => "100\\%"
139
- #
140
- # sanitize_sql_like("snake_cased_string")
141
- # # => "snake\\_cased\\_string"
142
- #
143
- # sanitize_sql_like("100%", "!")
144
- # # => "100!%"
145
- #
146
- # sanitize_sql_like("snake_cased_string", "!")
147
- # # => "snake!_cased!_string"
148
- def sanitize_sql_like(string, escape_character = "\\")
149
- pattern = Regexp.union(escape_character, "%", "_")
150
- string.gsub(pattern) { |x| [escape_character, x].join }
151
- end
114
+ "#{c.quote_table_name_for_assignment(table, attr)} = #{c.quote(value)}"
115
+ end.join(", ")
116
+ end
152
117
 
153
- # Accepts an array of conditions. The array has each value
154
- # sanitized and interpolated into the SQL statement.
155
- #
156
- # sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
157
- # # => "name='foo''bar' and group_id=4"
158
- #
159
- # sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
160
- # # => "name='foo''bar' and group_id=4"
161
- #
162
- # sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
163
- # # => "name='foo''bar' and group_id='4'"
164
- def sanitize_sql_array(ary)
165
- statement, *values = ary
166
- if values.first.is_a?(Hash) && statement =~ /:\w+/
167
- replace_named_bind_variables(statement, values.first)
168
- elsif statement.include?('?')
169
- replace_bind_variables(statement, values)
170
- elsif statement.blank?
171
- statement
172
- else
173
- statement % values.collect { |value| connection.quote_string(value.to_s) }
118
+ # Sanitizes a +string+ so that it is safe to use within an SQL
119
+ # LIKE statement. This method uses +escape_character+ to escape all occurrences of "\", "_" and "%".
120
+ #
121
+ # sanitize_sql_like("100%")
122
+ # # => "100\\%"
123
+ #
124
+ # sanitize_sql_like("snake_cased_string")
125
+ # # => "snake\\_cased\\_string"
126
+ #
127
+ # sanitize_sql_like("100%", "!")
128
+ # # => "100!%"
129
+ #
130
+ # sanitize_sql_like("snake_cased_string", "!")
131
+ # # => "snake!_cased!_string"
132
+ def sanitize_sql_like(string, escape_character = "\\") # :doc:
133
+ pattern = Regexp.union(escape_character, "%", "_")
134
+ string.gsub(pattern) { |x| [escape_character, x].join }
174
135
  end
175
- end
176
136
 
177
- def replace_bind_variables(statement, values) # :nodoc:
178
- raise_if_bind_arity_mismatch(statement, statement.count('?'), values.size)
179
- bound = values.dup
180
- c = connection
181
- statement.gsub(/\?/) do
182
- replace_bind_variable(bound.shift, c)
137
+ # Accepts an array of conditions. The array has each value
138
+ # sanitized and interpolated into the SQL statement.
139
+ #
140
+ # sanitize_sql_array(["name=? and group_id=?", "foo'bar", 4])
141
+ # # => "name='foo''bar' and group_id=4"
142
+ #
143
+ # sanitize_sql_array(["name=:name and group_id=:group_id", name: "foo'bar", group_id: 4])
144
+ # # => "name='foo''bar' and group_id=4"
145
+ #
146
+ # sanitize_sql_array(["name='%s' and group_id='%s'", "foo'bar", 4])
147
+ # # => "name='foo''bar' and group_id='4'"
148
+ def sanitize_sql_array(ary) # :doc:
149
+ statement, *values = ary
150
+ if values.first.is_a?(Hash) && /:\w+/.match?(statement)
151
+ replace_named_bind_variables(statement, values.first)
152
+ elsif statement.include?("?")
153
+ replace_bind_variables(statement, values)
154
+ elsif statement.blank?
155
+ statement
156
+ else
157
+ statement % values.collect { |value| connection.quote_string(value.to_s) }
158
+ end
183
159
  end
184
- end
185
160
 
186
- def replace_bind_variable(value, c = connection) # :nodoc:
187
- if ActiveRecord::Relation === value
188
- value.to_sql
189
- else
190
- quote_bound_value(value, c)
161
+ def replace_bind_variables(statement, values)
162
+ raise_if_bind_arity_mismatch(statement, statement.count("?"), values.size)
163
+ bound = values.dup
164
+ c = connection
165
+ statement.gsub(/\?/) do
166
+ replace_bind_variable(bound.shift, c)
167
+ end
191
168
  end
192
- end
193
169
 
194
- def replace_named_bind_variables(statement, bind_vars) # :nodoc:
195
- statement.gsub(/(:?):([a-zA-Z]\w*)/) do |match|
196
- if $1 == ':' # skip postgresql casts
197
- match # return the whole match
198
- elsif bind_vars.include?(match = $2.to_sym)
199
- replace_bind_variable(bind_vars[match])
170
+ def replace_bind_variable(value, c = connection)
171
+ if ActiveRecord::Relation === value
172
+ value.to_sql
200
173
  else
201
- raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
174
+ quote_bound_value(value, c)
202
175
  end
203
176
  end
204
- end
205
177
 
206
- def quote_bound_value(value, c = connection) # :nodoc:
207
- if value.respond_to?(:map) && !value.acts_like?(:string)
208
- if value.respond_to?(:empty?) && value.empty?
209
- c.quote(nil)
178
+ def replace_named_bind_variables(statement, bind_vars)
179
+ statement.gsub(/(:?):([a-zA-Z]\w*)/) do |match|
180
+ if $1 == ":" # skip postgresql casts
181
+ match # return the whole match
182
+ elsif bind_vars.include?(match = $2.to_sym)
183
+ replace_bind_variable(bind_vars[match])
184
+ else
185
+ raise PreparedStatementInvalid, "missing value for :#{match} in #{statement}"
186
+ end
187
+ end
188
+ end
189
+
190
+ def quote_bound_value(value, c = connection)
191
+ if value.respond_to?(:map) && !value.acts_like?(:string)
192
+ if value.respond_to?(:empty?) && value.empty?
193
+ c.quote(nil)
194
+ else
195
+ value.map { |v| c.quote(v) }.join(",")
196
+ end
210
197
  else
211
- value.map { |v| c.quote(v) }.join(',')
198
+ c.quote(value)
212
199
  end
213
- else
214
- c.quote(value)
215
200
  end
216
- end
217
201
 
218
- def raise_if_bind_arity_mismatch(statement, expected, provided) # :nodoc:
219
- unless expected == provided
220
- raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}"
202
+ def raise_if_bind_arity_mismatch(statement, expected, provided)
203
+ unless expected == provided
204
+ raise PreparedStatementInvalid, "wrong number of bind variables (#{provided} for #{expected}) in: #{statement}"
205
+ end
221
206
  end
222
- end
223
207
  end
224
208
 
225
- # TODO: Deprecate this
226
209
  def quoted_id # :nodoc:
227
- self.class.quote_value(@attributes[self.class.primary_key].value_for_database)
210
+ self.class.connection.quote(@attributes[self.class.primary_key].value_for_database)
228
211
  end
212
+ deprecate :quoted_id
229
213
  end
230
214
  end
@@ -40,7 +40,7 @@ module ActiveRecord
40
40
  # ActiveRecord::Schema.define(version: 20380119000001) do
41
41
  # ...
42
42
  # end
43
- def self.define(info={}, &block)
43
+ def self.define(info = {}, &block)
44
44
  new.define(info, &block)
45
45
  end
46
46
 
@@ -48,7 +48,7 @@ module ActiveRecord
48
48
  instance_eval(&block)
49
49
 
50
50
  if info[:version].present?
51
- initialize_schema_migrations_table
51
+ ActiveRecord::SchemaMigration.create_table
52
52
  connection.assume_migrated_upto_version(info[:version], migrations_paths)
53
53
  end
54
54
 
@@ -61,7 +61,7 @@ module ActiveRecord
61
61
  #
62
62
  # ActiveRecord::Schema.new.migrations_paths
63
63
  # # => ["db/migrate"] # Rails migration path by default.
64
- def migrations_paths # :nodoc:
64
+ def migrations_paths
65
65
  ActiveRecord::Migrator.migrations_paths
66
66
  end
67
67
  end