activerecord 5.1.0 → 5.2.0.rc1

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 (260) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +410 -530
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +4 -4
  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 +4 -2
  9. data/lib/active_record/associations/alias_tracker.rb +23 -32
  10. data/lib/active_record/associations/association.rb +20 -21
  11. data/lib/active_record/associations/association_scope.rb +49 -49
  12. data/lib/active_record/associations/belongs_to_association.rb +12 -10
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +4 -7
  14. data/lib/active_record/associations/builder/association.rb +4 -7
  15. data/lib/active_record/associations/builder/belongs_to.rb +10 -6
  16. data/lib/active_record/associations/builder/collection_association.rb +1 -1
  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 +50 -41
  22. data/lib/active_record/associations/collection_proxy.rb +22 -39
  23. data/lib/active_record/associations/foreign_association.rb +2 -0
  24. data/lib/active_record/associations/has_many_association.rb +4 -2
  25. data/lib/active_record/associations/has_many_through_association.rb +12 -18
  26. data/lib/active_record/associations/has_one_association.rb +5 -1
  27. data/lib/active_record/associations/has_one_through_association.rb +8 -7
  28. data/lib/active_record/associations/join_dependency/join_association.rb +17 -64
  29. data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
  30. data/lib/active_record/associations/join_dependency/join_part.rb +2 -9
  31. data/lib/active_record/associations/join_dependency.rb +27 -44
  32. data/lib/active_record/associations/preloader/association.rb +53 -92
  33. data/lib/active_record/associations/preloader/through_association.rb +72 -73
  34. data/lib/active_record/associations/preloader.rb +17 -37
  35. data/lib/active_record/associations/singular_association.rb +14 -10
  36. data/lib/active_record/associations/through_association.rb +26 -11
  37. data/lib/active_record/associations.rb +68 -76
  38. data/lib/active_record/attribute_assignment.rb +2 -0
  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 +24 -214
  42. data/lib/active_record/attribute_methods/primary_key.rb +10 -13
  43. data/lib/active_record/attribute_methods/query.rb +2 -0
  44. data/lib/active_record/attribute_methods/read.rb +8 -2
  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 +22 -19
  48. data/lib/active_record/attribute_methods.rb +48 -12
  49. data/lib/active_record/attributes.rb +7 -6
  50. data/lib/active_record/autosave_association.rb +8 -11
  51. data/lib/active_record/base.rb +2 -0
  52. data/lib/active_record/callbacks.rb +8 -6
  53. data/lib/active_record/coders/json.rb +2 -0
  54. data/lib/active_record/coders/yaml_column.rb +2 -0
  55. data/lib/active_record/collection_cache_key.rb +14 -10
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +110 -35
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +2 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +175 -33
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +8 -2
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +13 -24
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +15 -6
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +58 -3
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +165 -85
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +45 -9
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -97
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +118 -180
  69. data/lib/active_record/connection_adapters/column.rb +4 -2
  70. data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +2 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +11 -17
  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 -23
  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 +30 -1
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -32
  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 +2 -0
  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_time.rb +2 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  96. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +3 -1
  98. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +4 -2
  101. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -1
  107. data/lib/active_record/connection_adapters/postgresql/quoting.rb +22 -1
  108. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
  109. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +14 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
  111. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
  112. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +269 -126
  113. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
  114. data/lib/active_record/connection_adapters/postgresql/utils.rb +2 -0
  115. data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -85
  116. data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
  117. data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
  118. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
  119. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +18 -0
  120. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
  122. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
  123. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +71 -1
  124. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +92 -95
  125. data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
  126. data/lib/active_record/connection_handling.rb +4 -2
  127. data/lib/active_record/core.rb +39 -60
  128. data/lib/active_record/counter_cache.rb +3 -2
  129. data/lib/active_record/define_callbacks.rb +5 -3
  130. data/lib/active_record/dynamic_matchers.rb +9 -9
  131. data/lib/active_record/enum.rb +17 -13
  132. data/lib/active_record/errors.rb +42 -3
  133. data/lib/active_record/explain.rb +3 -1
  134. data/lib/active_record/explain_registry.rb +2 -0
  135. data/lib/active_record/explain_subscriber.rb +2 -0
  136. data/lib/active_record/fixture_set/file.rb +2 -0
  137. data/lib/active_record/fixtures.rb +67 -60
  138. data/lib/active_record/gem_version.rb +4 -2
  139. data/lib/active_record/inheritance.rb +9 -9
  140. data/lib/active_record/integration.rb +58 -19
  141. data/lib/active_record/internal_metadata.rb +2 -0
  142. data/lib/active_record/legacy_yaml_adapter.rb +3 -1
  143. data/lib/active_record/locking/optimistic.rb +8 -6
  144. data/lib/active_record/locking/pessimistic.rb +9 -6
  145. data/lib/active_record/log_subscriber.rb +46 -4
  146. data/lib/active_record/migration/command_recorder.rb +11 -9
  147. data/lib/active_record/migration/compatibility.rb +74 -22
  148. data/lib/active_record/migration/join_table.rb +2 -0
  149. data/lib/active_record/migration.rb +181 -137
  150. data/lib/active_record/model_schema.rb +73 -58
  151. data/lib/active_record/nested_attributes.rb +18 -6
  152. data/lib/active_record/no_touching.rb +3 -1
  153. data/lib/active_record/null_relation.rb +2 -0
  154. data/lib/active_record/persistence.rb +153 -18
  155. data/lib/active_record/query_cache.rb +17 -12
  156. data/lib/active_record/querying.rb +4 -2
  157. data/lib/active_record/railtie.rb +61 -3
  158. data/lib/active_record/railties/console_sandbox.rb +2 -0
  159. data/lib/active_record/railties/controller_runtime.rb +2 -0
  160. data/lib/active_record/railties/databases.rake +47 -37
  161. data/lib/active_record/readonly_attributes.rb +3 -2
  162. data/lib/active_record/reflection.rb +131 -204
  163. data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
  164. data/lib/active_record/relation/batches.rb +32 -17
  165. data/lib/active_record/relation/calculations.rb +58 -20
  166. data/lib/active_record/relation/delegation.rb +10 -29
  167. data/lib/active_record/relation/finder_methods.rb +74 -85
  168. data/lib/active_record/relation/from_clause.rb +2 -8
  169. data/lib/active_record/relation/merger.rb +51 -20
  170. data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
  171. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  172. data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
  173. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
  174. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +54 -0
  175. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -6
  176. data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
  177. data/lib/active_record/relation/predicate_builder.rb +53 -78
  178. data/lib/active_record/relation/query_attribute.rb +9 -2
  179. data/lib/active_record/relation/query_methods.rb +101 -95
  180. data/lib/active_record/relation/record_fetch_warning.rb +2 -0
  181. data/lib/active_record/relation/spawn_methods.rb +3 -1
  182. data/lib/active_record/relation/where_clause.rb +65 -67
  183. data/lib/active_record/relation/where_clause_factory.rb +5 -48
  184. data/lib/active_record/relation.rb +99 -202
  185. data/lib/active_record/result.rb +2 -0
  186. data/lib/active_record/runtime_registry.rb +2 -0
  187. data/lib/active_record/sanitization.rb +129 -121
  188. data/lib/active_record/schema.rb +4 -2
  189. data/lib/active_record/schema_dumper.rb +36 -26
  190. data/lib/active_record/schema_migration.rb +2 -0
  191. data/lib/active_record/scoping/default.rb +10 -7
  192. data/lib/active_record/scoping/named.rb +38 -12
  193. data/lib/active_record/scoping.rb +12 -10
  194. data/lib/active_record/secure_token.rb +2 -0
  195. data/lib/active_record/serialization.rb +2 -0
  196. data/lib/active_record/statement_cache.rb +22 -12
  197. data/lib/active_record/store.rb +3 -1
  198. data/lib/active_record/suppressor.rb +2 -0
  199. data/lib/active_record/table_metadata.rb +12 -3
  200. data/lib/active_record/tasks/database_tasks.rb +37 -25
  201. data/lib/active_record/tasks/mysql_database_tasks.rb +11 -50
  202. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -3
  203. data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
  204. data/lib/active_record/timestamp.rb +5 -5
  205. data/lib/active_record/touch_later.rb +2 -0
  206. data/lib/active_record/transactions.rb +9 -7
  207. data/lib/active_record/translation.rb +2 -0
  208. data/lib/active_record/type/adapter_specific_registry.rb +2 -0
  209. data/lib/active_record/type/date.rb +2 -0
  210. data/lib/active_record/type/date_time.rb +2 -0
  211. data/lib/active_record/type/decimal_without_scale.rb +2 -0
  212. data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
  213. data/lib/active_record/type/internal/timezone.rb +2 -0
  214. data/lib/active_record/type/json.rb +30 -0
  215. data/lib/active_record/type/serialized.rb +2 -0
  216. data/lib/active_record/type/text.rb +2 -0
  217. data/lib/active_record/type/time.rb +2 -0
  218. data/lib/active_record/type/type_map.rb +2 -0
  219. data/lib/active_record/type/unsigned_integer.rb +2 -0
  220. data/lib/active_record/type.rb +4 -1
  221. data/lib/active_record/type_caster/connection.rb +2 -0
  222. data/lib/active_record/type_caster/map.rb +3 -1
  223. data/lib/active_record/type_caster.rb +2 -0
  224. data/lib/active_record/validations/absence.rb +2 -0
  225. data/lib/active_record/validations/associated.rb +2 -0
  226. data/lib/active_record/validations/length.rb +2 -0
  227. data/lib/active_record/validations/presence.rb +2 -0
  228. data/lib/active_record/validations/uniqueness.rb +35 -5
  229. data/lib/active_record/validations.rb +2 -0
  230. data/lib/active_record/version.rb +2 -0
  231. data/lib/active_record.rb +11 -4
  232. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  233. data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
  234. data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
  235. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
  236. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
  237. data/lib/rails/generators/active_record/migration.rb +2 -0
  238. data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
  239. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
  240. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  241. data/lib/rails/generators/active_record.rb +3 -1
  242. metadata +25 -37
  243. data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
  244. data/lib/active_record/associations/preloader/collection_association.rb +0 -17
  245. data/lib/active_record/associations/preloader/has_many.rb +0 -15
  246. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  247. data/lib/active_record/associations/preloader/has_one.rb +0 -15
  248. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  249. data/lib/active_record/associations/preloader/singular_association.rb +0 -18
  250. data/lib/active_record/attribute/user_provided_default.rb +0 -30
  251. data/lib/active_record/attribute.rb +0 -240
  252. data/lib/active_record/attribute_mutation_tracker.rb +0 -113
  253. data/lib/active_record/attribute_set/builder.rb +0 -124
  254. data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
  255. data/lib/active_record/attribute_set.rb +0 -113
  256. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
  257. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  258. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
  259. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
  260. data/lib/active_record/type/internal/abstract_json.rb +0 -33
@@ -1,3 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+
1
5
  module ActiveRecord
2
6
  module ModelSchema
3
7
  extend ActiveSupport::Concern
@@ -82,19 +86,6 @@ module ActiveRecord
82
86
  #
83
87
  # Sets the name of the internal metadata table.
84
88
 
85
- ##
86
- # :singleton-method: protected_environments
87
- # :call-seq: protected_environments
88
- #
89
- # The array of names of environments where destructive actions should be prohibited. By default,
90
- # the value is <tt>["production"]</tt>.
91
-
92
- ##
93
- # :singleton-method: protected_environments=
94
- # :call-seq: protected_environments=(environments)
95
- #
96
- # Sets an array of names of environments where destructive actions should be prohibited.
97
-
98
89
  ##
99
90
  # :singleton-method: pluralize_table_names
100
91
  # :call-seq: pluralize_table_names
@@ -111,47 +102,22 @@ module ActiveRecord
111
102
  # If true, the default table name for a Product class will be "products". If false, it would just be "product".
112
103
  # See table_name for the full rules on table/class naming. This is true, by default.
113
104
 
114
- ##
115
- # :singleton-method: ignored_columns
116
- # :call-seq: ignored_columns
117
- #
118
- # The list of columns names the model should ignore. Ignored columns won't have attribute
119
- # accessors defined, and won't be referenced in SQL queries.
120
-
121
- ##
122
- # :singleton-method: ignored_columns=
123
- # :call-seq: ignored_columns=(columns)
124
- #
125
- # Sets the columns names the model should ignore. Ignored columns won't have attribute
126
- # accessors defined, and won't be referenced in SQL queries.
127
-
128
105
  included do
129
106
  mattr_accessor :primary_key_prefix_type, instance_writer: false
130
107
 
131
- class_attribute :table_name_prefix, instance_writer: false
132
- self.table_name_prefix = ""
133
-
134
- class_attribute :table_name_suffix, instance_writer: false
135
- self.table_name_suffix = ""
136
-
137
- class_attribute :schema_migrations_table_name, instance_accessor: false
138
- self.schema_migrations_table_name = "schema_migrations"
139
-
140
- class_attribute :internal_metadata_table_name, instance_accessor: false
141
- self.internal_metadata_table_name = "ar_internal_metadata"
108
+ class_attribute :table_name_prefix, instance_writer: false, default: ""
109
+ class_attribute :table_name_suffix, instance_writer: false, default: ""
110
+ class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
111
+ class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
112
+ class_attribute :pluralize_table_names, instance_writer: false, default: true
142
113
 
143
- class_attribute :protected_environments, instance_accessor: false
144
114
  self.protected_environments = ["production"]
145
-
146
- class_attribute :pluralize_table_names, instance_writer: false
147
- self.pluralize_table_names = true
148
-
149
- class_attribute :ignored_columns, instance_accessor: false
150
- self.ignored_columns = [].freeze
151
-
152
115
  self.inheritance_column = "type"
116
+ self.ignored_columns = [].freeze
153
117
 
154
118
  delegate :type_for_attribute, to: :class
119
+
120
+ initialize_load_schema_monitor
155
121
  end
156
122
 
157
123
  # Derives the join table name for +first_table+ and +second_table+. The
@@ -259,6 +225,21 @@ module ActiveRecord
259
225
  (parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
260
226
  end
261
227
 
228
+ # The array of names of environments where destructive actions should be prohibited. By default,
229
+ # the value is <tt>["production"]</tt>.
230
+ def protected_environments
231
+ if defined?(@protected_environments)
232
+ @protected_environments
233
+ else
234
+ superclass.protected_environments
235
+ end
236
+ end
237
+
238
+ # Sets an array of names of environments where destructive actions should be prohibited.
239
+ def protected_environments=(environments)
240
+ @protected_environments = environments.map(&:to_s)
241
+ end
242
+
262
243
  # Defines the name of the table column which will store the class name on single-table
263
244
  # inheritance situations.
264
245
  #
@@ -278,6 +259,22 @@ module ActiveRecord
278
259
  @explicit_inheritance_column = true
279
260
  end
280
261
 
262
+ # The list of columns names the model should ignore. Ignored columns won't have attribute
263
+ # accessors defined, and won't be referenced in SQL queries.
264
+ def ignored_columns
265
+ if defined?(@ignored_columns)
266
+ @ignored_columns
267
+ else
268
+ superclass.ignored_columns
269
+ end
270
+ end
271
+
272
+ # Sets the columns names the model should ignore. Ignored columns won't have attribute
273
+ # accessors defined, and won't be referenced in SQL queries.
274
+ def ignored_columns=(columns)
275
+ @ignored_columns = columns.map(&:to_s)
276
+ end
277
+
281
278
  def sequence_name
282
279
  if base_class == self
283
280
  @sequence_name ||= reset_sequence_name
@@ -328,11 +325,11 @@ module ActiveRecord
328
325
  end
329
326
 
330
327
  def attributes_builder # :nodoc:
331
- @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key) do |name|
332
- unless columns_hash.key?(name)
333
- _default_attributes[name].dup
334
- end
328
+ unless defined?(@attributes_builder) && @attributes_builder
329
+ defaults = _default_attributes.except(*(column_names - [primary_key]))
330
+ @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
335
331
  end
332
+ @attributes_builder
336
333
  end
337
334
 
338
335
  def columns_hash # :nodoc:
@@ -351,7 +348,7 @@ module ActiveRecord
351
348
  end
352
349
 
353
350
  def yaml_encoder # :nodoc:
354
- @yaml_encoder ||= AttributeSet::YAMLEncoder.new(attribute_types)
351
+ @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
355
352
  end
356
353
 
357
354
  # Returns the type of the attribute with the given name, after applying
@@ -364,8 +361,9 @@ module ActiveRecord
364
361
  # it).
365
362
  #
366
363
  # +attr_name+ The name of the attribute to retrieve the type for. Must be
367
- # a string
364
+ # a string or a symbol.
368
365
  def type_for_attribute(attr_name, &block)
366
+ attr_name = attr_name.to_s
369
367
  if block
370
368
  attribute_types.fetch(attr_name, &block)
371
369
  else
@@ -377,11 +375,11 @@ module ActiveRecord
377
375
  # default values when instantiating the Active Record object for this table.
378
376
  def column_defaults
379
377
  load_schema
380
- _default_attributes.to_hash
378
+ @column_defaults ||= _default_attributes.to_hash
381
379
  end
382
380
 
383
381
  def _default_attributes # :nodoc:
384
- @default_attributes ||= AttributeSet.new({})
382
+ @default_attributes ||= ActiveModel::AttributeSet.new({})
385
383
  end
386
384
 
387
385
  # Returns an array of column names as strings.
@@ -428,22 +426,38 @@ module ActiveRecord
428
426
  # end
429
427
  def reset_column_information
430
428
  connection.clear_cache!
431
- undefine_attribute_methods
429
+ ([self] + descendants).each(&:undefine_attribute_methods)
432
430
  connection.schema_cache.clear_data_source_cache!(table_name)
433
431
 
434
432
  reload_schema_from_cache
435
433
  initialize_find_by_cache
436
434
  end
437
435
 
436
+ protected
437
+
438
+ def initialize_load_schema_monitor
439
+ @load_schema_monitor = Monitor.new
440
+ end
441
+
438
442
  private
439
443
 
444
+ def inherited(child_class)
445
+ super
446
+ child_class.initialize_load_schema_monitor
447
+ end
448
+
440
449
  def schema_loaded?
441
- defined?(@columns_hash) && @columns_hash
450
+ defined?(@schema_loaded) && @schema_loaded
442
451
  end
443
452
 
444
453
  def load_schema
445
- unless schema_loaded?
454
+ return if schema_loaded?
455
+ @load_schema_monitor.synchronize do
456
+ return if defined?(@columns_hash) && @columns_hash
457
+
446
458
  load_schema!
459
+
460
+ @schema_loaded = true
447
461
  end
448
462
  end
449
463
 
@@ -460,16 +474,17 @@ module ActiveRecord
460
474
  end
461
475
 
462
476
  def reload_schema_from_cache
463
- @arel_engine = nil
464
477
  @arel_table = nil
465
478
  @column_names = nil
466
479
  @attribute_types = nil
467
480
  @content_columns = nil
468
481
  @default_attributes = nil
482
+ @column_defaults = nil
469
483
  @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
470
484
  @attributes_builder = nil
471
485
  @columns = nil
472
486
  @columns_hash = nil
487
+ @schema_loaded = false
473
488
  @attribute_names = nil
474
489
  @yaml_encoder = nil
475
490
  direct_descendants.each do |descendant|
@@ -1,4 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "active_support/core_ext/hash/except"
4
+ require "active_support/core_ext/module/redefine_method"
2
5
  require "active_support/core_ext/object/try"
3
6
  require "active_support/core_ext/hash/indifferent_access"
4
7
 
@@ -10,8 +13,7 @@ module ActiveRecord
10
13
  extend ActiveSupport::Concern
11
14
 
12
15
  included do
13
- class_attribute :nested_attributes_options, instance_writer: false
14
- self.nested_attributes_options = {}
16
+ class_attribute :nested_attributes_options, instance_writer: false, default: {}
15
17
  end
16
18
 
17
19
  # = Active Record Nested Attributes
@@ -61,6 +63,18 @@ module ActiveRecord
61
63
  # member.update params[:member]
62
64
  # member.avatar.icon # => 'sad'
63
65
  #
66
+ # If you want to update the current avatar without providing the id, you must add <tt>:update_only</tt> option.
67
+ #
68
+ # class Member < ActiveRecord::Base
69
+ # has_one :avatar
70
+ # accepts_nested_attributes_for :avatar, update_only: true
71
+ # end
72
+ #
73
+ # params = { member: { avatar_attributes: { icon: 'sad' } } }
74
+ # member.update params[:member]
75
+ # member.avatar.id # => 2
76
+ # member.avatar.icon # => 'sad'
77
+ #
64
78
  # By default you will only be able to set and update attributes on the
65
79
  # associated model. If you want to destroy the associated model through the
66
80
  # attributes hash, you have to enable it first using the
@@ -354,9 +368,7 @@ module ActiveRecord
354
368
  # associations are just regular associations.
355
369
  def generate_association_writer(association_name, type)
356
370
  generated_association_methods.module_eval <<-eoruby, __FILE__, __LINE__ + 1
357
- if method_defined?(:#{association_name}_attributes=)
358
- remove_method(:#{association_name}_attributes=)
359
- end
371
+ silence_redefinition_of_method :#{association_name}_attributes=
360
372
  def #{association_name}_attributes=(attributes)
361
373
  assign_nested_attributes_for_#{type}_association(:#{association_name}, attributes)
362
374
  end
@@ -458,7 +470,7 @@ module ActiveRecord
458
470
  end
459
471
 
460
472
  unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
461
- raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
473
+ raise ArgumentError, "Hash or Array expected for attribute `#{association_name}`, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
462
474
  end
463
475
 
464
476
  check_record_limit!(options[:limit], attributes_collection)
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record No Touching
3
5
  module NoTouching
4
6
  extend ActiveSupport::Concern
5
7
 
6
8
  module ClassMethods
7
- # Lets you selectively disable calls to `touch` for the
9
+ # Lets you selectively disable calls to +touch+ for the
8
10
  # duration of a block.
9
11
  #
10
12
  # ==== Examples
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module NullRelation # :nodoc:
3
5
  def pluck(*column_names)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record \Persistence
3
5
  module Persistence
@@ -69,6 +71,132 @@ module ActiveRecord
69
71
  klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
70
72
  end
71
73
 
74
+ # Updates an object (or multiple objects) and saves it to the database, if validations pass.
75
+ # The resulting object is returned whether the object was saved successfully to the database or not.
76
+ #
77
+ # ==== Parameters
78
+ #
79
+ # * +id+ - This should be the id or an array of ids to be updated.
80
+ # * +attributes+ - This should be a hash of attributes or an array of hashes.
81
+ #
82
+ # ==== Examples
83
+ #
84
+ # # Updates one record
85
+ # Person.update(15, user_name: "Samuel", group: "expert")
86
+ #
87
+ # # Updates multiple records
88
+ # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
89
+ # Person.update(people.keys, people.values)
90
+ #
91
+ # # Updates multiple records from the result of a relation
92
+ # people = Person.where(group: "expert")
93
+ # people.update(group: "masters")
94
+ #
95
+ # Note: Updating a large number of records will run an UPDATE
96
+ # query for each record, which may cause a performance issue.
97
+ # When running callbacks is not needed for each record update,
98
+ # it is preferred to use {update_all}[rdoc-ref:Relation#update_all]
99
+ # for updating all records in a single query.
100
+ def update(id = :all, attributes)
101
+ if id.is_a?(Array)
102
+ id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
103
+ object.update(attributes[idx])
104
+ }
105
+ elsif id == :all
106
+ all.each { |record| record.update(attributes) }
107
+ else
108
+ if ActiveRecord::Base === id
109
+ raise ArgumentError,
110
+ "You are passing an instance of ActiveRecord::Base to `update`. " \
111
+ "Please pass the id of the object by calling `.id`."
112
+ end
113
+ object = find(id)
114
+ object.update(attributes)
115
+ object
116
+ end
117
+ end
118
+
119
+ # Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
120
+ # therefore all callbacks and filters are fired off before the object is deleted. This method is
121
+ # less efficient than #delete but allows cleanup methods and other actions to be run.
122
+ #
123
+ # This essentially finds the object (or multiple objects) with the given id, creates a new object
124
+ # from the attributes, and then calls destroy on it.
125
+ #
126
+ # ==== Parameters
127
+ #
128
+ # * +id+ - This should be the id or an array of ids to be destroyed.
129
+ #
130
+ # ==== Examples
131
+ #
132
+ # # Destroy a single object
133
+ # Todo.destroy(1)
134
+ #
135
+ # # Destroy multiple objects
136
+ # todos = [1,2,3]
137
+ # Todo.destroy(todos)
138
+ def destroy(id)
139
+ if id.is_a?(Array)
140
+ find(id).each(&:destroy)
141
+ else
142
+ find(id).destroy
143
+ end
144
+ end
145
+
146
+ # Deletes the row with a primary key matching the +id+ argument, using a
147
+ # SQL +DELETE+ statement, and returns the number of rows deleted. Active
148
+ # Record objects are not instantiated, so the object's callbacks are not
149
+ # executed, including any <tt>:dependent</tt> association options.
150
+ #
151
+ # You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
152
+ #
153
+ # Note: Although it is often much faster than the alternative, #destroy,
154
+ # skipping callbacks might bypass business logic in your application
155
+ # that ensures referential integrity or performs other essential jobs.
156
+ #
157
+ # ==== Examples
158
+ #
159
+ # # Delete a single row
160
+ # Todo.delete(1)
161
+ #
162
+ # # Delete multiple rows
163
+ # Todo.delete([2,3,4])
164
+ def delete(id_or_array)
165
+ where(primary_key => id_or_array).delete_all
166
+ end
167
+
168
+ def _insert_record(values) # :nodoc:
169
+ primary_key_value = nil
170
+
171
+ if primary_key && Hash === values
172
+ arel_primary_key = arel_attribute(primary_key)
173
+ primary_key_value = values[arel_primary_key]
174
+
175
+ if !primary_key_value && prefetch_primary_key?
176
+ primary_key_value = next_sequence_value
177
+ values[arel_primary_key] = primary_key_value
178
+ end
179
+ end
180
+
181
+ if values.empty?
182
+ im = arel_table.compile_insert(connection.empty_insert_statement_value)
183
+ im.into arel_table
184
+ else
185
+ im = arel_table.compile_insert(_substitute_values(values))
186
+ end
187
+
188
+ connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
189
+ end
190
+
191
+ def _update_record(values, id, id_was) # :nodoc:
192
+ bind = predicate_builder.build_bind_attribute(primary_key, id_was || id)
193
+ um = arel_table.where(
194
+ arel_attribute(primary_key).eq(bind)
195
+ ).compile_update(_substitute_values(values), primary_key)
196
+
197
+ connection.update(um, "#{self} Update")
198
+ end
199
+
72
200
  private
73
201
  # Called by +instantiate+ to decide which class to use for a new
74
202
  # record instance.
@@ -78,6 +206,13 @@ module ActiveRecord
78
206
  def discriminate_class_for_record(record)
79
207
  self
80
208
  end
209
+
210
+ def _substitute_values(values)
211
+ values.map do |attr, value|
212
+ bind = predicate_builder.build_bind_attribute(attr.name, value)
213
+ [attr, bind]
214
+ end
215
+ end
81
216
  end
82
217
 
83
218
  # Returns true if this object hasn't been saved yet -- that is, a record
@@ -175,7 +310,7 @@ module ActiveRecord
175
310
  # callbacks or any <tt>:dependent</tt> association
176
311
  # options, use <tt>#destroy</tt>.
177
312
  def delete
178
- self.class.delete(id) if persisted?
313
+ _relation_for_itself.delete_all if persisted?
179
314
  @destroyed = true
180
315
  freeze
181
316
  end
@@ -224,10 +359,10 @@ module ActiveRecord
224
359
  # Any change to the attributes on either instance will affect both instances.
225
360
  # If you want to change the sti column as well, use #becomes! instead.
226
361
  def becomes(klass)
227
- became = klass.new
362
+ became = klass.allocate
363
+ became.send(:initialize)
228
364
  became.instance_variable_set("@attributes", @attributes)
229
- became.instance_variable_set("@mutation_tracker", @mutation_tracker) if defined?(@mutation_tracker)
230
- became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
365
+ became.instance_variable_set("@mutations_from_database", @mutations_from_database) if defined?(@mutations_from_database)
231
366
  became.instance_variable_set("@new_record", new_record?)
232
367
  became.instance_variable_set("@destroyed", destroyed?)
233
368
  became.errors.copy!(errors)
@@ -267,11 +402,7 @@ module ActiveRecord
267
402
  verify_readonly_attribute(name)
268
403
  public_send("#{name}=", value)
269
404
 
270
- if has_changes_to_save?
271
- save(validate: false)
272
- else
273
- true
274
- end
405
+ save(validate: false)
275
406
  end
276
407
 
277
408
  # Updates the attributes of the model from the passed-in hash and saves the
@@ -330,10 +461,10 @@ module ActiveRecord
330
461
  verify_readonly_attribute(key.to_s)
331
462
  end
332
463
 
333
- updated_count = self.class.unscoped.where(self.class.primary_key => id).update_all(attributes)
464
+ updated_count = _relation_for_itself.update_all(attributes)
334
465
 
335
466
  attributes.each do |k, v|
336
- raw_write_attribute(k, v)
467
+ write_attribute_without_type_cast(k, v)
337
468
  end
338
469
 
339
470
  updated_count == 1
@@ -351,7 +482,7 @@ module ActiveRecord
351
482
  # Wrapper around #increment that writes the update to the database.
352
483
  # Only +attribute+ is updated; the record itself is not saved.
353
484
  # This means that any other modified attributes will still be dirty.
354
- # Validations and callbacks are skipped. Supports the `touch` option from
485
+ # Validations and callbacks are skipped. Supports the +touch+ option from
355
486
  # +update_counters+, see that for more.
356
487
  # Returns +self+.
357
488
  def increment!(attribute, by = 1, touch: nil)
@@ -372,7 +503,7 @@ module ActiveRecord
372
503
  # Wrapper around #decrement that writes the update to the database.
373
504
  # Only +attribute+ is updated; the record itself is not saved.
374
505
  # This means that any other modified attributes will still be dirty.
375
- # Validations and callbacks are skipped. Supports the `touch` option from
506
+ # Validations and callbacks are skipped. Supports the +touch+ option from
376
507
  # +update_counters+, see that for more.
377
508
  # Returns +self+.
378
509
  def decrement!(attribute, by = 1, touch: nil)
@@ -521,12 +652,11 @@ module ActiveRecord
521
652
  changes[column] = write_attribute(column, time)
522
653
  end
523
654
 
524
- primary_key = self.class.primary_key
525
- scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
655
+ scope = _relation_for_itself
526
656
 
527
657
  if locking_enabled?
528
658
  locking_column = self.class.locking_column
529
- scope = scope.where(locking_column => _read_attribute(locking_column))
659
+ scope = scope.where(locking_column => read_attribute_before_type_cast(locking_column))
530
660
  changes[locking_column] = increment_lock
531
661
  end
532
662
 
@@ -555,11 +685,16 @@ module ActiveRecord
555
685
  end
556
686
 
557
687
  def relation_for_destroy
688
+ _relation_for_itself
689
+ end
690
+
691
+ def _relation_for_itself
558
692
  self.class.unscoped.where(self.class.primary_key => id)
559
693
  end
560
694
 
561
695
  def create_or_update(*args, &block)
562
696
  _raise_readonly_record_error if readonly?
697
+ return false if destroyed?
563
698
  result = new_record? ? _create_record(&block) : _update_record(*args, &block)
564
699
  result != false
565
700
  end
@@ -572,7 +707,7 @@ module ActiveRecord
572
707
  rows_affected = 0
573
708
  @_trigger_update_callback = true
574
709
  else
575
- rows_affected = self.class.unscoped._update_record attributes_values, id, id_in_database
710
+ rows_affected = self.class._update_record(attributes_values, id, id_in_database)
576
711
  @_trigger_update_callback = rows_affected > 0
577
712
  end
578
713
 
@@ -586,7 +721,7 @@ module ActiveRecord
586
721
  def _create_record(attribute_names = self.attribute_names)
587
722
  attributes_values = arel_attributes_with_values_for_create(attribute_names)
588
723
 
589
- new_id = self.class.unscoped.insert attributes_values
724
+ new_id = self.class._insert_record(attributes_values)
590
725
  self.id ||= new_id if self.class.primary_key
591
726
 
592
727
  @new_record = false
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  # = Active Record Query Cache
3
5
  class QueryCache
@@ -5,35 +7,38 @@ module ActiveRecord
5
7
  # Enable the query cache within the block if Active Record is configured.
6
8
  # If it's not, it will execute the given block.
7
9
  def cache(&block)
8
- if connected?
9
- connection.cache(&block)
10
- else
10
+ if configurations.empty?
11
11
  yield
12
+ else
13
+ connection.cache(&block)
12
14
  end
13
15
  end
14
16
 
15
17
  # Disable the query cache within the block if Active Record is configured.
16
18
  # If it's not, it will execute the given block.
17
19
  def uncached(&block)
18
- if connected?
19
- connection.uncached(&block)
20
- else
20
+ if configurations.empty?
21
21
  yield
22
+ else
23
+ connection.uncached(&block)
22
24
  end
23
25
  end
24
26
  end
25
27
 
26
28
  def self.run
27
- caching_pool = ActiveRecord::Base.connection_pool
28
- caching_was_enabled = caching_pool.query_cache_enabled
29
+ ActiveRecord::Base.connection_handler.connection_pool_list.map do |pool|
30
+ caching_was_enabled = pool.query_cache_enabled
29
31
 
30
- caching_pool.enable_query_cache!
32
+ pool.enable_query_cache!
31
33
 
32
- [caching_pool, caching_was_enabled]
34
+ [pool, caching_was_enabled]
35
+ end
33
36
  end
34
37
 
35
- def self.complete((caching_pool, caching_was_enabled))
36
- caching_pool.disable_query_cache! unless caching_was_enabled
38
+ def self.complete(caching_pools)
39
+ caching_pools.each do |pool, caching_was_enabled|
40
+ pool.disable_query_cache! unless caching_was_enabled
41
+ end
37
42
 
38
43
  ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
39
44
  pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ActiveRecord
2
4
  module Querying
3
5
  delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
@@ -5,10 +7,10 @@ module ActiveRecord
5
7
  delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
6
8
  delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
7
9
  delegate :find_by, :find_by!, to: :all
8
- delegate :destroy, :destroy_all, :delete, :delete_all, :update, :update_all, to: :all
10
+ delegate :destroy_all, :delete_all, :update_all, to: :all
9
11
  delegate :find_each, :find_in_batches, :in_batches, to: :all
10
12
  delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
11
- :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly,
13
+ :where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
12
14
  :having, :create_with, :distinct, :references, :none, :unscope, :merge, to: :all
13
15
  delegate :count, :average, :minimum, :maximum, :sum, :calculate, to: :all
14
16
  delegate :pluck, :ids, to: :all