activerecord 5.1.5 → 5.2.8.1

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 (261) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +655 -608
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +5 -5
  5. data/examples/performance.rb +2 -0
  6. data/examples/simple.rb +2 -0
  7. data/lib/active_record/aggregations.rb +6 -5
  8. data/lib/active_record/association_relation.rb +7 -5
  9. data/lib/active_record/associations/alias_tracker.rb +19 -27
  10. data/lib/active_record/associations/association.rb +41 -37
  11. data/lib/active_record/associations/association_scope.rb +38 -50
  12. data/lib/active_record/associations/belongs_to_association.rb +28 -9
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +14 -5
  16. data/lib/active_record/associations/builder/collection_association.rb +3 -3
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
  18. data/lib/active_record/associations/builder/has_many.rb +2 -0
  19. data/lib/active_record/associations/builder/has_one.rb +2 -0
  20. data/lib/active_record/associations/builder/singular_association.rb +2 -0
  21. data/lib/active_record/associations/collection_association.rb +59 -47
  22. data/lib/active_record/associations/collection_proxy.rb +20 -49
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +12 -1
  25. data/lib/active_record/associations/has_many_through_association.rb +36 -30
  26. data/lib/active_record/associations/has_one_association.rb +12 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +13 -8
  28. data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
  31. data/lib/active_record/associations/join_dependency.rb +48 -93
  32. data/lib/active_record/associations/preloader/association.rb +45 -61
  33. data/lib/active_record/associations/preloader/through_association.rb +71 -79
  34. data/lib/active_record/associations/preloader.rb +18 -38
  35. data/lib/active_record/associations/singular_association.rb +14 -16
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +40 -63
  38. data/lib/active_record/attribute_assignment.rb +2 -5
  39. data/lib/active_record/attribute_decorators.rb +3 -2
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
  41. data/lib/active_record/attribute_methods/dirty.rb +32 -216
  42. data/lib/active_record/attribute_methods/primary_key.rb +7 -6
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +9 -3
  45. data/lib/active_record/attribute_methods/serialization.rb +23 -0
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
  47. data/lib/active_record/attribute_methods/write.rb +21 -9
  48. data/lib/active_record/attribute_methods.rb +65 -24
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +35 -19
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +12 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +15 -1
  55. data/lib/active_record/collection_cache_key.rb +12 -8
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +142 -42
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +110 -173
  69. data/lib/active_record/connection_adapters/column.rb +3 -1
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -3
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -112
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +66 -74
  117. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +82 -95
  126. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  127. data/lib/active_record/connection_handling.rb +4 -2
  128. data/lib/active_record/core.rb +51 -61
  129. data/lib/active_record/counter_cache.rb +20 -15
  130. data/lib/active_record/define_callbacks.rb +5 -3
  131. data/lib/active_record/dynamic_matchers.rb +9 -9
  132. data/lib/active_record/enum.rb +18 -13
  133. data/lib/active_record/errors.rb +60 -15
  134. data/lib/active_record/explain.rb +3 -1
  135. data/lib/active_record/explain_registry.rb +2 -0
  136. data/lib/active_record/explain_subscriber.rb +2 -0
  137. data/lib/active_record/fixture_set/file.rb +2 -0
  138. data/lib/active_record/fixtures.rb +67 -60
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +49 -19
  141. data/lib/active_record/integration.rb +58 -19
  142. data/lib/active_record/internal_metadata.rb +2 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  144. data/lib/active_record/locking/optimistic.rb +30 -42
  145. data/lib/active_record/locking/pessimistic.rb +9 -6
  146. data/lib/active_record/log_subscriber.rb +43 -0
  147. data/lib/active_record/migration/command_recorder.rb +11 -9
  148. data/lib/active_record/migration/compatibility.rb +47 -9
  149. data/lib/active_record/migration/join_table.rb +2 -0
  150. data/lib/active_record/migration.rb +189 -139
  151. data/lib/active_record/model_schema.rb +19 -24
  152. data/lib/active_record/nested_attributes.rb +18 -6
  153. data/lib/active_record/no_touching.rb +3 -1
  154. data/lib/active_record/null_relation.rb +2 -0
  155. data/lib/active_record/persistence.rb +198 -49
  156. data/lib/active_record/query_cache.rb +12 -14
  157. data/lib/active_record/querying.rb +4 -2
  158. data/lib/active_record/railtie.rb +80 -6
  159. data/lib/active_record/railties/console_sandbox.rb +2 -0
  160. data/lib/active_record/railties/controller_runtime.rb +2 -0
  161. data/lib/active_record/railties/databases.rake +46 -36
  162. data/lib/active_record/readonly_attributes.rb +3 -2
  163. data/lib/active_record/reflection.rb +108 -194
  164. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  165. data/lib/active_record/relation/batches.rb +20 -5
  166. data/lib/active_record/relation/calculations.rb +46 -20
  167. data/lib/active_record/relation/delegation.rb +45 -27
  168. data/lib/active_record/relation/finder_methods.rb +77 -78
  169. data/lib/active_record/relation/from_clause.rb +2 -8
  170. data/lib/active_record/relation/merger.rb +53 -23
  171. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  172. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  173. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  174. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  175. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  176. data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
  177. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  178. data/lib/active_record/relation/predicate_builder.rb +60 -79
  179. data/lib/active_record/relation/query_attribute.rb +28 -2
  180. data/lib/active_record/relation/query_methods.rb +129 -100
  181. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  182. data/lib/active_record/relation/spawn_methods.rb +4 -2
  183. data/lib/active_record/relation/where_clause.rb +65 -68
  184. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  185. data/lib/active_record/relation.rb +120 -214
  186. data/lib/active_record/result.rb +2 -0
  187. data/lib/active_record/runtime_registry.rb +2 -0
  188. data/lib/active_record/sanitization.rb +129 -121
  189. data/lib/active_record/schema.rb +4 -2
  190. data/lib/active_record/schema_dumper.rb +36 -26
  191. data/lib/active_record/schema_migration.rb +2 -0
  192. data/lib/active_record/scoping/default.rb +8 -9
  193. data/lib/active_record/scoping/named.rb +23 -7
  194. data/lib/active_record/scoping.rb +9 -8
  195. data/lib/active_record/secure_token.rb +2 -0
  196. data/lib/active_record/serialization.rb +2 -0
  197. data/lib/active_record/statement_cache.rb +23 -13
  198. data/lib/active_record/store.rb +3 -1
  199. data/lib/active_record/suppressor.rb +2 -0
  200. data/lib/active_record/table_metadata.rb +12 -3
  201. data/lib/active_record/tasks/database_tasks.rb +26 -15
  202. data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
  203. data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
  204. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  205. data/lib/active_record/timestamp.rb +13 -6
  206. data/lib/active_record/touch_later.rb +2 -0
  207. data/lib/active_record/transactions.rb +33 -28
  208. data/lib/active_record/translation.rb +2 -0
  209. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  210. data/lib/active_record/type/date.rb +2 -0
  211. data/lib/active_record/type/date_time.rb +2 -0
  212. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  213. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  214. data/lib/active_record/type/internal/timezone.rb +2 -0
  215. data/lib/active_record/type/json.rb +30 -0
  216. data/lib/active_record/type/serialized.rb +6 -0
  217. data/lib/active_record/type/text.rb +2 -0
  218. data/lib/active_record/type/time.rb +2 -0
  219. data/lib/active_record/type/type_map.rb +2 -0
  220. data/lib/active_record/type/unsigned_integer.rb +2 -0
  221. data/lib/active_record/type.rb +4 -1
  222. data/lib/active_record/type_caster/connection.rb +2 -0
  223. data/lib/active_record/type_caster/map.rb +3 -1
  224. data/lib/active_record/type_caster.rb +2 -0
  225. data/lib/active_record/validations/absence.rb +2 -0
  226. data/lib/active_record/validations/associated.rb +2 -0
  227. data/lib/active_record/validations/length.rb +2 -0
  228. data/lib/active_record/validations/presence.rb +2 -0
  229. data/lib/active_record/validations/uniqueness.rb +36 -6
  230. data/lib/active_record/validations.rb +2 -0
  231. data/lib/active_record/version.rb +2 -0
  232. data/lib/active_record.rb +11 -4
  233. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  234. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  235. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  236. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  238. data/lib/rails/generators/active_record/migration.rb +2 -0
  239. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  240. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  242. data/lib/rails/generators/active_record.rb +3 -1
  243. metadata +26 -40
  244. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  245. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  246. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  247. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  248. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  249. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  250. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  251. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  252. data/lib/active_record/attribute.rb +0 -240
  253. data/lib/active_record/attribute_mutation_tracker.rb +0 -114
  254. data/lib/active_record/attribute_set/builder.rb +0 -124
  255. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  256. data/lib/active_record/attribute_set.rb +0 -113
  257. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  258. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  259. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  260. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  261. data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "set"
2
4
 
3
5
  module ActiveRecord
@@ -8,23 +10,22 @@ module ActiveRecord
8
10
  # Returns this record's primary key value wrapped in an array if one is
9
11
  # available.
10
12
  def to_key
11
- sync_with_transaction_state
12
13
  key = id
13
14
  [key] if key
14
15
  end
15
16
 
16
17
  # Returns the primary key value.
17
18
  def id
18
- if pk = self.class.primary_key
19
- sync_with_transaction_state
20
- _read_attribute(pk)
21
- end
19
+ sync_with_transaction_state
20
+ primary_key = self.class.primary_key
21
+ _read_attribute(primary_key) if primary_key
22
22
  end
23
23
 
24
24
  # Sets the primary key value.
25
25
  def id=(value)
26
26
  sync_with_transaction_state
27
- write_attribute(self.class.primary_key, value) if self.class.primary_key
27
+ primary_key = self.class.primary_key
28
+ _write_attribute(primary_key, value) if primary_key
28
29
  end
29
30
 
30
31
  # Queries the primary key value.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  module Query
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  module Read
4
6
  extend ActiveSupport::Concern
5
7
 
6
- module ClassMethods
8
+ module ClassMethods # :nodoc:
7
9
  private
8
10
 
9
11
  # We want to generate the methods via module_eval rather than
@@ -29,9 +31,11 @@ module ActiveRecord
29
31
  temp_method = "__temp__#{safe_name}"
30
32
 
31
33
  ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
34
+ sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
32
35
 
33
36
  generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
34
37
  def #{temp_method}
38
+ #{sync_with_transaction_state}
35
39
  name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
36
40
  _read_attribute(name) { |n| missing_attribute(n, caller) }
37
41
  end
@@ -54,7 +58,9 @@ module ActiveRecord
54
58
  attr_name.to_s
55
59
  end
56
60
 
57
- name = self.class.primary_key if name == "id".freeze && self.class.primary_key
61
+ primary_key = self.class.primary_key
62
+ name = primary_key if name == "id".freeze && primary_key
63
+ sync_with_transaction_state if name == primary_key
58
64
  _read_attribute(name, &block)
59
65
  end
60
66
 
@@ -63,7 +69,7 @@ module ActiveRecord
63
69
  if defined?(JRUBY_VERSION)
64
70
  # This form is significantly faster on JRuby, and this is one of our biggest hotspots.
65
71
  # https://github.com/jruby/jruby/pull/2562
66
- def _read_attribute(attr_name, &block) # :nodoc
72
+ def _read_attribute(attr_name, &block) # :nodoc:
67
73
  @attributes.fetch_value(attr_name.to_s, &block)
68
74
  end
69
75
  else
@@ -1,8 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  module Serialization
4
6
  extend ActiveSupport::Concern
5
7
 
8
+ class ColumnNotSerializableError < StandardError
9
+ def initialize(name, type)
10
+ super <<-EOS.strip_heredoc
11
+ Column `#{name}` of type #{type.class} does not support `serialize` feature.
12
+ Usually it means that you are trying to use `serialize`
13
+ on a column that already implements serialization natively.
14
+ EOS
15
+ end
16
+ end
17
+
6
18
  module ClassMethods
7
19
  # If you have an attribute that needs to be saved to the database as an
8
20
  # object, and retrieved as the same object, then specify the name of that
@@ -58,9 +70,20 @@ module ActiveRecord
58
70
  end
59
71
 
60
72
  decorate_attribute_type(attr_name, :serialize) do |type|
73
+ if type_incompatible_with_serialize?(type, class_name_or_coder)
74
+ raise ColumnNotSerializableError.new(attr_name, type)
75
+ end
76
+
61
77
  Type::Serialized.new(type, coder)
62
78
  end
63
79
  end
80
+
81
+ private
82
+
83
+ def type_incompatible_with_serialize?(type, class_name)
84
+ type.is_a?(ActiveRecord::Type::Json) && class_name == ::JSON ||
85
+ type.respond_to?(:type_cast_array, true) && class_name == ::Array
86
+ end
64
87
  end
65
88
  end
66
89
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  module TimeZoneConversion
@@ -54,17 +56,13 @@ module ActiveRecord
54
56
  extend ActiveSupport::Concern
55
57
 
56
58
  included do
57
- mattr_accessor :time_zone_aware_attributes, instance_writer: false
58
- self.time_zone_aware_attributes = false
59
-
60
- class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false
61
- self.skip_time_zone_conversion_for_attributes = []
59
+ mattr_accessor :time_zone_aware_attributes, instance_writer: false, default: false
62
60
 
63
- class_attribute :time_zone_aware_types, instance_writer: false
64
- self.time_zone_aware_types = [:datetime, :time]
61
+ class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false, default: []
62
+ class_attribute :time_zone_aware_types, instance_writer: false, default: [ :datetime, :time ]
65
63
  end
66
64
 
67
- module ClassMethods
65
+ module ClassMethods # :nodoc:
68
66
  private
69
67
 
70
68
  def inherited(subclass)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module AttributeMethods
3
5
  module Write
@@ -7,17 +9,19 @@ module ActiveRecord
7
9
  attribute_method_suffix "="
8
10
  end
9
11
 
10
- module ClassMethods
12
+ module ClassMethods # :nodoc:
11
13
  private
12
14
 
13
15
  def define_method_attribute=(name)
14
16
  safe_name = name.unpack("h*".freeze).first
15
17
  ActiveRecord::AttributeMethods::AttrNames.set_name_cache safe_name, name
18
+ sync_with_transaction_state = "sync_with_transaction_state" if name == primary_key
16
19
 
17
20
  generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1
18
21
  def __temp__#{safe_name}=(value)
19
22
  name = ::ActiveRecord::AttributeMethods::AttrNames::ATTR_#{safe_name}
20
- write_attribute(name, value)
23
+ #{sync_with_transaction_state}
24
+ _write_attribute(name, value)
21
25
  end
22
26
  alias_method #{(name + '=').inspect}, :__temp__#{safe_name}=
23
27
  undef_method :__temp__#{safe_name}=
@@ -35,21 +39,29 @@ module ActiveRecord
35
39
  attr_name.to_s
36
40
  end
37
41
 
38
- name = self.class.primary_key if name == "id".freeze && self.class.primary_key
39
- @attributes.write_from_user(name, value)
40
- value
42
+ primary_key = self.class.primary_key
43
+ name = primary_key if name == "id".freeze && primary_key
44
+ sync_with_transaction_state if name == primary_key
45
+ _write_attribute(name, value)
41
46
  end
42
47
 
43
- def raw_write_attribute(attr_name, value) # :nodoc:
44
- name = attr_name.to_s
45
- @attributes.write_cast_value(name, value)
48
+ # This method exists to avoid the expensive primary_key check internally, without
49
+ # breaking compatibility with the write_attribute API
50
+ def _write_attribute(attr_name, value) # :nodoc:
51
+ @attributes.write_from_user(attr_name.to_s, value)
46
52
  value
47
53
  end
48
54
 
49
55
  private
56
+ def write_attribute_without_type_cast(attr_name, value)
57
+ name = attr_name.to_s
58
+ @attributes.write_cast_value(name, value)
59
+ value
60
+ end
61
+
50
62
  # Handle *= for method_missing.
51
63
  def attribute=(attribute_name, value)
52
- write_attribute(attribute_name, value)
64
+ _write_attribute(attribute_name, value)
53
65
  end
54
66
  end
55
67
  end
@@ -1,7 +1,6 @@
1
- require "active_support/core_ext/enumerable"
2
- require "active_support/core_ext/string/filters"
1
+ # frozen_string_literal: true
2
+
3
3
  require "mutex_m"
4
- require "concurrent/map"
5
4
 
6
5
  module ActiveRecord
7
6
  # = Active Record Attribute Methods
@@ -34,7 +33,9 @@ module ActiveRecord
34
33
 
35
34
  BLACKLISTED_CLASS_METHODS = %w(private public protected allocate new name parent superclass)
36
35
 
37
- class GeneratedAttributeMethods < Module; end # :nodoc:
36
+ class GeneratedAttributeMethods < Module #:nodoc:
37
+ include Mutex_m
38
+ end
38
39
 
39
40
  module ClassMethods
40
41
  def inherited(child_class) #:nodoc:
@@ -43,7 +44,7 @@ module ActiveRecord
43
44
  end
44
45
 
45
46
  def initialize_generated_modules # :nodoc:
46
- @generated_attribute_methods = GeneratedAttributeMethods.new { extend Mutex_m }
47
+ @generated_attribute_methods = GeneratedAttributeMethods.new
47
48
  @attribute_methods_generated = false
48
49
  include @generated_attribute_methods
49
50
 
@@ -62,7 +63,6 @@ module ActiveRecord
62
63
  super(attribute_names)
63
64
  @attribute_methods_generated = true
64
65
  end
65
- true
66
66
  end
67
67
 
68
68
  def undefine_attribute_methods # :nodoc:
@@ -167,6 +167,57 @@ module ActiveRecord
167
167
  end
168
168
  end
169
169
 
170
+ # Regexp whitelist. Matches the following:
171
+ # "#{table_name}.#{column_name}"
172
+ # "#{column_name}"
173
+ COLUMN_NAME_WHITELIST = /\A(?:\w+\.)?\w+\z/i
174
+
175
+ # Regexp whitelist. Matches the following:
176
+ # "#{table_name}.#{column_name}"
177
+ # "#{table_name}.#{column_name} #{direction}"
178
+ # "#{table_name}.#{column_name} #{direction} NULLS FIRST"
179
+ # "#{table_name}.#{column_name} NULLS LAST"
180
+ # "#{column_name}"
181
+ # "#{column_name} #{direction}"
182
+ # "#{column_name} #{direction} NULLS FIRST"
183
+ # "#{column_name} NULLS LAST"
184
+ COLUMN_NAME_ORDER_WHITELIST = /
185
+ \A
186
+ (?:\w+\.)?
187
+ \w+
188
+ (?:\s+asc|\s+desc)?
189
+ (?:\s+nulls\s+(?:first|last))?
190
+ \z
191
+ /ix
192
+
193
+ def enforce_raw_sql_whitelist(args, whitelist: COLUMN_NAME_WHITELIST) # :nodoc:
194
+ unexpected = args.reject do |arg|
195
+ arg.kind_of?(Arel::Node) ||
196
+ arg.is_a?(Arel::Nodes::SqlLiteral) ||
197
+ arg.is_a?(Arel::Attributes::Attribute) ||
198
+ arg.to_s.split(/\s*,\s*/).all? { |part| whitelist.match?(part) }
199
+ end
200
+
201
+ return if unexpected.none?
202
+
203
+ if allow_unsafe_raw_sql == :deprecated
204
+ ActiveSupport::Deprecation.warn(
205
+ "Dangerous query method (method whose arguments are used as raw " \
206
+ "SQL) called with non-attribute argument(s): " \
207
+ "#{unexpected.map(&:inspect).join(", ")}. Non-attribute " \
208
+ "arguments will be disallowed in Rails 6.0. This method should " \
209
+ "not be called with user-provided values, such as request " \
210
+ "parameters or model attributes. Known-safe values can be passed " \
211
+ "by wrapping them in Arel.sql()."
212
+ )
213
+ else
214
+ raise(ActiveRecord::UnknownAttributeReference,
215
+ "Query method called with non-attribute argument(s): " +
216
+ unexpected.map(&:inspect).join(", ")
217
+ )
218
+ end
219
+ end
220
+
170
221
  # Returns true if the given attribute exists, otherwise false.
171
222
  #
172
223
  # class Person < ActiveRecord::Base
@@ -236,7 +287,7 @@ module ActiveRecord
236
287
  return has_attribute?(name)
237
288
  end
238
289
 
239
- return true
290
+ true
240
291
  end
241
292
 
242
293
  # Returns +true+ if the given attribute is in the attributes hash, otherwise +false+.
@@ -401,24 +452,18 @@ module ActiveRecord
401
452
 
402
453
  private
403
454
 
404
- def arel_attributes_with_values_for_create(attribute_names)
405
- arel_attributes_with_values(attributes_for_create(attribute_names))
455
+ def attributes_with_values_for_create(attribute_names)
456
+ attributes_with_values(attributes_for_create(attribute_names))
406
457
  end
407
458
 
408
- def arel_attributes_with_values_for_update(attribute_names)
409
- arel_attributes_with_values(attributes_for_update(attribute_names))
459
+ def attributes_with_values_for_update(attribute_names)
460
+ attributes_with_values(attributes_for_update(attribute_names))
410
461
  end
411
462
 
412
- # Returns a Hash of the Arel::Attributes and attribute values that have been
413
- # typecasted for use in an Arel insert/update method.
414
- def arel_attributes_with_values(attribute_names)
415
- attrs = {}
416
- arel_table = self.class.arel_table
417
-
418
- attribute_names.each do |name|
419
- attrs[arel_table[name]] = typecasted_attribute_value(name)
463
+ def attributes_with_values(attribute_names)
464
+ attribute_names.each_with_object({}) do |name, attrs|
465
+ attrs[name] = _read_attribute(name)
420
466
  end
421
- attrs
422
467
  end
423
468
 
424
469
  # Filters the primary keys and readonly attributes from the attribute names.
@@ -443,9 +488,5 @@ module ActiveRecord
443
488
  def pk_attribute?(name)
444
489
  name == self.class.primary_key
445
490
  end
446
-
447
- def typecasted_attribute_value(name)
448
- _read_attribute(name)
449
- end
450
491
  end
451
492
  end
@@ -1,4 +1,6 @@
1
- require "active_record/attribute/user_provided_default"
1
+ # frozen_string_literal: true
2
+
3
+ require "active_model/attribute/user_provided_default"
2
4
 
3
5
  module ActiveRecord
4
6
  # See ActiveRecord::Attributes::ClassMethods for documentation
@@ -6,8 +8,7 @@ module ActiveRecord
6
8
  extend ActiveSupport::Concern
7
9
 
8
10
  included do
9
- class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false # :internal:
10
- self.attributes_to_define_after_schema_loads = {}
11
+ class_attribute :attributes_to_define_after_schema_loads, instance_accessor: false, default: {} # :internal:
11
12
  end
12
13
 
13
14
  module ClassMethods
@@ -56,7 +57,7 @@ module ActiveRecord
56
57
  # store_listing = StoreListing.new(price_in_cents: '10.1')
57
58
  #
58
59
  # # before
59
- # store_listing.price_in_cents # => BigDecimal.new(10.1)
60
+ # store_listing.price_in_cents # => BigDecimal(10.1)
60
61
  #
61
62
  # class StoreListing < ActiveRecord::Base
62
63
  # attribute :price_in_cents, :integer
@@ -249,14 +250,14 @@ module ActiveRecord
249
250
  if value == NO_DEFAULT_PROVIDED
250
251
  default_attribute = _default_attributes[name].with_type(type)
251
252
  elsif from_user
252
- default_attribute = Attribute::UserProvidedDefault.new(
253
+ default_attribute = ActiveModel::Attribute::UserProvidedDefault.new(
253
254
  name,
254
255
  value,
255
256
  type,
256
257
  _default_attributes.fetch(name.to_s) { nil },
257
258
  )
258
259
  else
259
- default_attribute = Attribute.from_database(name, value, type)
260
+ default_attribute = ActiveModel::Attribute.from_database(name, value, type)
260
261
  end
261
262
  _default_attributes[name] = default_attribute
262
263
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Autosave Association
3
5
  #
@@ -140,8 +142,7 @@ module ActiveRecord
140
142
 
141
143
  included do
142
144
  Associations::Builder::Association.extensions << AssociationBuilderExtension
143
- mattr_accessor :index_nested_attribute_errors, instance_writer: false
144
- self.index_nested_attribute_errors = false
145
+ mattr_accessor :index_nested_attribute_errors, instance_writer: false, default: false
145
146
  end
146
147
 
147
148
  module ClassMethods # :nodoc:
@@ -216,13 +217,7 @@ module ActiveRecord
216
217
  method = :validate_single_association
217
218
  end
218
219
 
219
- define_non_cyclic_method(validation_method) do
220
- send(method, reflection)
221
- # TODO: remove the following line as soon as the return value of
222
- # callbacks is ignored, that is, returning `false` does not
223
- # display a deprecation warning or halts the callback chain.
224
- true
225
- end
220
+ define_non_cyclic_method(validation_method) { send(method, reflection) }
226
221
  validate validation_method
227
222
  after_validation :_ensure_no_duplicate_errors
228
223
  end
@@ -277,7 +272,7 @@ module ActiveRecord
277
272
  # or saved. If +autosave+ is +false+ only new records will be returned,
278
273
  # unless the parent is/was a new record itself.
279
274
  def associated_records_to_validate_or_save(association, new_record, autosave)
280
- if new_record
275
+ if new_record || custom_validation_context?
281
276
  association && association.target
282
277
  elsif autosave
283
278
  association.target.find_all(&:changed_for_autosave?)
@@ -309,7 +304,7 @@ module ActiveRecord
309
304
  def validate_single_association(reflection)
310
305
  association = association_instance_get(reflection.name)
311
306
  record = association && association.reader
312
- association_valid?(reflection, record) if record
307
+ association_valid?(reflection, record) if record && (record.changed_for_autosave? || custom_validation_context?)
313
308
  end
314
309
 
315
310
  # Validate the associated records if <tt>:validate</tt> or
@@ -329,7 +324,7 @@ module ActiveRecord
329
324
  def association_valid?(reflection, record, index = nil)
330
325
  return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
331
326
 
332
- context = validation_context unless [:create, :update].include?(validation_context)
327
+ context = validation_context if custom_validation_context?
333
328
 
334
329
  unless valid = record.valid?(context)
335
330
  if reflection.options[:autosave]
@@ -369,7 +364,6 @@ module ActiveRecord
369
364
  # association whether or not the parent was a new record before saving.
370
365
  def before_save_collection_association
371
366
  @new_record_before_save = new_record?
372
- true
373
367
  end
374
368
 
375
369
  def after_save_collection_association
@@ -388,10 +382,14 @@ module ActiveRecord
388
382
  if association = association_instance_get(reflection.name)
389
383
  autosave = reflection.options[:autosave]
390
384
 
385
+ # By saving the instance variable in a local variable,
386
+ # we make the whole callback re-entrant.
387
+ new_record_before_save = @new_record_before_save
388
+
391
389
  # reconstruct the scope now that we know the owner's id
392
- association.reset_scope if association.respond_to?(:reset_scope)
390
+ association.reset_scope
393
391
 
394
- if records = associated_records_to_validate_or_save(association, @new_record_before_save, autosave)
392
+ if records = associated_records_to_validate_or_save(association, new_record_before_save, autosave)
395
393
  if autosave
396
394
  records_to_destroy = records.select(&:marked_for_destruction?)
397
395
  records_to_destroy.each { |record| association.destroy(record) }
@@ -403,11 +401,16 @@ module ActiveRecord
403
401
 
404
402
  saved = true
405
403
 
406
- if autosave != false && (@new_record_before_save || record.new_record?)
404
+ if autosave != false && (new_record_before_save || record.new_record?)
407
405
  if autosave
408
406
  saved = association.insert_record(record, false)
409
- else
410
- association.insert_record(record) unless reflection.nested?
407
+ elsif !reflection.nested?
408
+ association_saved = association.insert_record(record)
409
+
410
+ if reflection.validate?
411
+ errors.add(reflection.name) unless association_saved
412
+ saved = association_saved
413
+ end
411
414
  end
412
415
  elsif autosave
413
416
  saved = record.save(validate: false)
@@ -442,6 +445,9 @@ module ActiveRecord
442
445
  if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key)
443
446
  unless reflection.through_reflection
444
447
  record[reflection.foreign_key] = key
448
+ if inverse_reflection = reflection.inverse_of
449
+ record.association(inverse_reflection.name).loaded!
450
+ end
445
451
  end
446
452
 
447
453
  saved = record.save(validate: !autosave)
@@ -455,10 +461,16 @@ module ActiveRecord
455
461
  # If the record is new or it has changed, returns true.
456
462
  def record_changed?(reflection, record, key)
457
463
  record.new_record? ||
458
- (record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key) ||
464
+ association_foreign_key_changed?(reflection, record, key) ||
459
465
  record.will_save_change_to_attribute?(reflection.foreign_key)
460
466
  end
461
467
 
468
+ def association_foreign_key_changed?(reflection, record, key)
469
+ return false if reflection.through_reflection?
470
+
471
+ record.has_attribute?(reflection.foreign_key) && record[reflection.foreign_key] != key
472
+ end
473
+
462
474
  # Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
463
475
  #
464
476
  # In addition, it will destroy the association if it was marked for destruction.
@@ -487,6 +499,10 @@ module ActiveRecord
487
499
  end
488
500
  end
489
501
 
502
+ def custom_validation_context?
503
+ validation_context && [:create, :update].exclude?(validation_context)
504
+ end
505
+
490
506
  def _ensure_no_duplicate_errors
491
507
  errors.messages.each_key do |attribute|
492
508
  errors[attribute].uniq!
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
  require "active_support/benchmarkable"
3
5
  require "active_support/dependencies"
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Callbacks
3
5
  #
@@ -96,9 +98,9 @@ module ActiveRecord
96
98
  # == Types of callbacks
97
99
  #
98
100
  # There are four types of callbacks accepted by the callback macros: Method references (symbol), callback objects,
99
- # inline methods (using a proc), and inline eval methods (using a string). Method references and callback objects
101
+ # inline methods (using a proc). Method references and callback objects
100
102
  # are the recommended approaches, inline methods using a proc are sometimes appropriate (such as for
101
- # creating mix-ins), and inline eval methods are deprecated.
103
+ # creating mix-ins).
102
104
  #
103
105
  # The method reference callbacks work by specifying a protected or private method available in the object, like this:
104
106
  #
@@ -230,7 +232,7 @@ module ActiveRecord
230
232
  #
231
233
  # For example:
232
234
  #
233
- # class Topic
235
+ # class Topic < ActiveRecord::Base
234
236
  # has_many :children
235
237
  #
236
238
  # after_save :log_children
@@ -238,7 +240,7 @@ module ActiveRecord
238
240
  #
239
241
  # private
240
242
  #
241
- # def log_chidren
243
+ # def log_children
242
244
  # # Child processing
243
245
  # end
244
246
  #
@@ -255,7 +257,7 @@ module ActiveRecord
255
257
  #
256
258
  # For example:
257
259
  #
258
- # class Topic
260
+ # class Topic < ActiveRecord::Base
259
261
  # has_many :children
260
262
  #
261
263
  # after_commit :log_children
@@ -263,7 +265,7 @@ module ActiveRecord
263
265
  #
264
266
  # private
265
267
  #
266
- # def log_chidren
268
+ # def log_children
267
269
  # # Child processing
268
270
  # end
269
271
  #
@@ -330,6 +332,10 @@ module ActiveRecord
330
332
  _run_touch_callbacks { super }
331
333
  end
332
334
 
335
+ def increment!(attribute, by = 1, touch: nil) # :nodoc:
336
+ touch ? _run_touch_callbacks { super } : super
337
+ end
338
+
333
339
  private
334
340
 
335
341
  def create_or_update(*)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Coders # :nodoc:
3
5
  class JSON # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "yaml"
2
4
 
3
5
  module ActiveRecord
@@ -21,7 +23,7 @@ module ActiveRecord
21
23
  def load(yaml)
22
24
  return object_class.new if object_class != Object && yaml.nil?
23
25
  return yaml unless yaml.is_a?(String) && /^---/.match?(yaml)
24
- obj = YAML.load(yaml)
26
+ obj = yaml_load(yaml)
25
27
 
26
28
  assert_valid_value(obj, action: "load")
27
29
  obj ||= object_class.new if object_class != Object
@@ -43,6 +45,18 @@ module ActiveRecord
43
45
  rescue ArgumentError
44
46
  raise ArgumentError, "Cannot serialize #{object_class}. Classes passed to `serialize` must have a 0 argument constructor."
45
47
  end
48
+
49
+ def yaml_load(payload)
50
+ if !ActiveRecord::Base.use_yaml_unsafe_load
51
+ YAML.safe_load(payload, permitted_classes: ActiveRecord::Base.yaml_column_permitted_classes, aliases: true)
52
+ else
53
+ if YAML.respond_to?(:unsafe_load)
54
+ YAML.unsafe_load(payload)
55
+ else
56
+ YAML.load(payload)
57
+ end
58
+ end
59
+ end
46
60
  end
47
61
  end
48
62
  end