activerecord 4.2.11.1 → 5.2.4.5

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (274) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +594 -1620
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +10 -11
  5. data/examples/performance.rb +32 -31
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +263 -249
  8. data/lib/active_record/association_relation.rb +11 -6
  9. data/lib/active_record/associations/alias_tracker.rb +29 -35
  10. data/lib/active_record/associations/association.rb +77 -43
  11. data/lib/active_record/associations/association_scope.rb +106 -133
  12. data/lib/active_record/associations/belongs_to_association.rb +52 -41
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
  14. data/lib/active_record/associations/builder/association.rb +29 -38
  15. data/lib/active_record/associations/builder/belongs_to.rb +77 -30
  16. data/lib/active_record/associations/builder/collection_association.rb +9 -22
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +42 -35
  18. data/lib/active_record/associations/builder/has_many.rb +6 -4
  19. data/lib/active_record/associations/builder/has_one.rb +13 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +15 -11
  21. data/lib/active_record/associations/collection_association.rb +139 -280
  22. data/lib/active_record/associations/collection_proxy.rb +231 -133
  23. data/lib/active_record/associations/foreign_association.rb +3 -1
  24. data/lib/active_record/associations/has_many_association.rb +34 -89
  25. data/lib/active_record/associations/has_many_through_association.rb +49 -76
  26. data/lib/active_record/associations/has_one_association.rb +38 -24
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +40 -87
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +12 -12
  31. data/lib/active_record/associations/join_dependency.rb +133 -159
  32. data/lib/active_record/associations/preloader/association.rb +85 -120
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -74
  34. data/lib/active_record/associations/preloader.rb +81 -91
  35. data/lib/active_record/associations/singular_association.rb +27 -34
  36. data/lib/active_record/associations/through_association.rb +38 -18
  37. data/lib/active_record/associations.rb +1732 -1597
  38. data/lib/active_record/attribute_assignment.rb +58 -182
  39. data/lib/active_record/attribute_decorators.rb +39 -15
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +10 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +94 -135
  42. data/lib/active_record/attribute_methods/primary_key.rb +86 -71
  43. data/lib/active_record/attribute_methods/query.rb +4 -2
  44. data/lib/active_record/attribute_methods/read.rb +45 -63
  45. data/lib/active_record/attribute_methods/serialization.rb +40 -20
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
  47. data/lib/active_record/attribute_methods/write.rb +30 -45
  48. data/lib/active_record/attribute_methods.rb +166 -109
  49. data/lib/active_record/attributes.rb +201 -82
  50. data/lib/active_record/autosave_association.rb +94 -36
  51. data/lib/active_record/base.rb +57 -44
  52. data/lib/active_record/callbacks.rb +97 -57
  53. data/lib/active_record/coders/json.rb +3 -1
  54. data/lib/active_record/coders/yaml_column.rb +24 -12
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +712 -290
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +10 -5
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +237 -90
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +71 -21
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +118 -52
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +67 -46
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +318 -217
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +81 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +570 -228
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +138 -70
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +325 -202
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +542 -601
  69. data/lib/active_record/connection_adapters/column.rb +50 -41
  70. data/lib/active_record/connection_adapters/connection_specification.rb +147 -135
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +41 -180
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +35 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +45 -114
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -58
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +10 -6
  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 +4 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
  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 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +55 -53
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +5 -3
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +107 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +144 -90
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +462 -284
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +432 -323
  117. data/lib/active_record/connection_adapters/schema_cache.rb +48 -24
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +269 -308
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +40 -27
  128. data/lib/active_record/core.rb +178 -198
  129. data/lib/active_record/counter_cache.rb +79 -36
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +87 -105
  132. data/lib/active_record/enum.rb +135 -88
  133. data/lib/active_record/errors.rb +179 -52
  134. data/lib/active_record/explain.rb +23 -11
  135. data/lib/active_record/explain_registry.rb +4 -2
  136. data/lib/active_record/explain_subscriber.rb +10 -5
  137. data/lib/active_record/fixture_set/file.rb +35 -9
  138. data/lib/active_record/fixtures.rb +188 -132
  139. data/lib/active_record/gem_version.rb +5 -3
  140. data/lib/active_record/inheritance.rb +148 -112
  141. data/lib/active_record/integration.rb +70 -28
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +21 -3
  144. data/lib/active_record/locale/en.yml +3 -2
  145. data/lib/active_record/locking/optimistic.rb +88 -96
  146. data/lib/active_record/locking/pessimistic.rb +15 -3
  147. data/lib/active_record/log_subscriber.rb +95 -33
  148. data/lib/active_record/migration/command_recorder.rb +133 -90
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +8 -6
  151. data/lib/active_record/migration.rb +581 -282
  152. data/lib/active_record/model_schema.rb +290 -111
  153. data/lib/active_record/nested_attributes.rb +264 -222
  154. data/lib/active_record/no_touching.rb +7 -1
  155. data/lib/active_record/null_relation.rb +24 -37
  156. data/lib/active_record/persistence.rb +347 -119
  157. data/lib/active_record/query_cache.rb +13 -24
  158. data/lib/active_record/querying.rb +19 -17
  159. data/lib/active_record/railtie.rb +94 -32
  160. data/lib/active_record/railties/console_sandbox.rb +2 -0
  161. data/lib/active_record/railties/controller_runtime.rb +9 -3
  162. data/lib/active_record/railties/databases.rake +149 -156
  163. data/lib/active_record/readonly_attributes.rb +5 -4
  164. data/lib/active_record/reflection.rb +414 -267
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +204 -55
  167. data/lib/active_record/relation/calculations.rb +256 -248
  168. data/lib/active_record/relation/delegation.rb +67 -60
  169. data/lib/active_record/relation/finder_methods.rb +288 -239
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +86 -86
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +24 -24
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  179. data/lib/active_record/relation/predicate_builder.rb +116 -119
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +448 -393
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +11 -13
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +287 -340
  187. data/lib/active_record/result.rb +54 -36
  188. data/lib/active_record/runtime_registry.rb +6 -4
  189. data/lib/active_record/sanitization.rb +155 -124
  190. data/lib/active_record/schema.rb +30 -24
  191. data/lib/active_record/schema_dumper.rb +91 -87
  192. data/lib/active_record/schema_migration.rb +19 -16
  193. data/lib/active_record/scoping/default.rb +102 -85
  194. data/lib/active_record/scoping/named.rb +81 -32
  195. data/lib/active_record/scoping.rb +45 -26
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +5 -5
  198. data/lib/active_record/statement_cache.rb +45 -35
  199. data/lib/active_record/store.rb +42 -36
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +134 -96
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +56 -100
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +83 -41
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -16
  206. data/lib/active_record/timestamp.rb +70 -38
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +199 -124
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +4 -45
  212. data/lib/active_record/type/date_time.rb +4 -49
  213. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  214. data/lib/active_record/type/hash_lookup_type_map.rb +5 -3
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +24 -15
  218. data/lib/active_record/type/text.rb +2 -2
  219. data/lib/active_record/type/time.rb +11 -16
  220. data/lib/active_record/type/type_map.rb +15 -17
  221. data/lib/active_record/type/unsigned_integer.rb +9 -7
  222. data/lib/active_record/type.rb +79 -23
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +13 -4
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +14 -13
  230. data/lib/active_record/validations/uniqueness.rb +40 -41
  231. data/lib/active_record/validations.rb +38 -35
  232. data/lib/active_record/version.rb +3 -1
  233. data/lib/active_record.rb +34 -22
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -35
  237. data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +8 -3
  238. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +8 -1
  239. data/lib/rails/generators/active_record/migration.rb +18 -1
  240. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  241. data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +3 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  243. data/lib/rails/generators/active_record.rb +7 -5
  244. metadata +72 -49
  245. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  246. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  247. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  248. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  249. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  250. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  251. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  252. data/lib/active_record/attribute.rb +0 -163
  253. data/lib/active_record/attribute_set/builder.rb +0 -106
  254. data/lib/active_record/attribute_set.rb +0 -81
  255. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  256. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  257. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  258. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  259. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  260. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  261. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  262. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  263. data/lib/active_record/type/big_integer.rb +0 -13
  264. data/lib/active_record/type/binary.rb +0 -50
  265. data/lib/active_record/type/boolean.rb +0 -31
  266. data/lib/active_record/type/decimal.rb +0 -64
  267. data/lib/active_record/type/decorator.rb +0 -14
  268. data/lib/active_record/type/float.rb +0 -19
  269. data/lib/active_record/type/integer.rb +0 -59
  270. data/lib/active_record/type/mutable.rb +0 -16
  271. data/lib/active_record/type/numeric.rb +0 -36
  272. data/lib/active_record/type/string.rb +0 -40
  273. data/lib/active_record/type/time_value.rb +0 -38
  274. data/lib/active_record/type/value.rb +0 -110
@@ -1,7 +1,8 @@
1
- require 'thread'
2
- require 'active_support/core_ext/hash/indifferent_access'
3
- require 'active_support/core_ext/object/duplicable'
4
- require 'active_support/core_ext/string/filters'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/indifferent_access"
4
+ require "active_support/core_ext/string/filters"
5
+ require "concurrent/map"
5
6
 
6
7
  module ActiveRecord
7
8
  module Core
@@ -16,6 +17,13 @@ module ActiveRecord
16
17
  # retrieved on both a class and instance level by calling +logger+.
17
18
  mattr_accessor :logger, instance_writer: false
18
19
 
20
+ ##
21
+ # :singleton-method:
22
+ #
23
+ # Specifies if the methods calling database queries should be logged below
24
+ # their relevant queries. Defaults to false.
25
+ mattr_accessor :verbose_query_logs, instance_writer: false, default: false
26
+
19
27
  ##
20
28
  # Contains the database configuration - as is typically stored in config/database.yml -
21
29
  # as a Hash.
@@ -56,8 +64,7 @@ module ActiveRecord
56
64
  # :singleton-method:
57
65
  # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling
58
66
  # dates and times from the database. This is set to :utc by default.
59
- mattr_accessor :default_timezone, instance_writer: false
60
- self.default_timezone = :utc
67
+ mattr_accessor :default_timezone, instance_writer: false, default: :utc
61
68
 
62
69
  ##
63
70
  # :singleton-method:
@@ -67,14 +74,27 @@ module ActiveRecord
67
74
  # ActiveRecord::Schema file which can be loaded into any database that
68
75
  # supports migrations. Use :ruby if you want to have different database
69
76
  # adapters for, e.g., your development and test environments.
70
- mattr_accessor :schema_format, instance_writer: false
71
- self.schema_format = :ruby
77
+ mattr_accessor :schema_format, instance_writer: false, default: :ruby
78
+
79
+ ##
80
+ # :singleton-method:
81
+ # Specifies if an error should be raised if the query has an order being
82
+ # ignored when doing batch queries. Useful in applications where the
83
+ # scope being ignored is error-worthy, rather than a warning.
84
+ mattr_accessor :error_on_ignored_order, instance_writer: false, default: false
85
+
86
+ # :singleton-method:
87
+ # Specify the behavior for unsafe raw query methods. Values are as follows
88
+ # deprecated - Warnings are logged when unsafe raw SQL is passed to
89
+ # query methods.
90
+ # disabled - Unsafe raw SQL passed to query methods results in
91
+ # UnknownAttributeReference exception.
92
+ mattr_accessor :allow_unsafe_raw_sql, instance_writer: false, default: :deprecated
72
93
 
73
94
  ##
74
95
  # :singleton-method:
75
96
  # Specify whether or not to use timestamps for migration versions
76
- mattr_accessor :timestamped_migrations, instance_writer: false
77
- self.timestamped_migrations = true
97
+ mattr_accessor :timestamped_migrations, instance_writer: false, default: true
78
98
 
79
99
  ##
80
100
  # :singleton-method:
@@ -82,20 +102,30 @@ module ActiveRecord
82
102
  # db:migrate rake task. This is true by default, which is useful for the
83
103
  # development environment. This should ideally be false in the production
84
104
  # environment where dumping schema is rarely needed.
85
- mattr_accessor :dump_schema_after_migration, instance_writer: false
86
- self.dump_schema_after_migration = true
105
+ mattr_accessor :dump_schema_after_migration, instance_writer: false, default: true
106
+
107
+ ##
108
+ # :singleton-method:
109
+ # Specifies which database schemas to dump when calling db:structure:dump.
110
+ # If the value is :schema_search_path (the default), any schemas listed in
111
+ # schema_search_path are dumped. Use :all to dump all schemas regardless
112
+ # of schema_search_path, or a string of comma separated schemas for a
113
+ # custom list.
114
+ mattr_accessor :dump_schemas, instance_writer: false, default: :schema_search_path
115
+
116
+ ##
117
+ # :singleton-method:
118
+ # Specify a threshold for the size of query result sets. If the number of
119
+ # records in the set exceeds the threshold, a warning is logged. This can
120
+ # be used to identify queries which load thousands of records and
121
+ # potentially cause memory bloat.
122
+ mattr_accessor :warn_on_records_fetched_greater_than, instance_writer: false
87
123
 
88
124
  mattr_accessor :maintain_test_schema, instance_accessor: false
89
125
 
90
- def self.disable_implicit_join_references=(value)
91
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
92
- Implicit join references were removed with Rails 4.1.
93
- Make sure to remove this configuration because it does nothing.
94
- MSG
95
- end
126
+ mattr_accessor :belongs_to_required_by_default, instance_accessor: false
96
127
 
97
128
  class_attribute :default_connection_handler, instance_writer: false
98
- class_attribute :find_by_statement_cache
99
129
 
100
130
  def self.connection_handler
101
131
  ActiveRecord::RuntimeRegistry.connection_handler || default_connection_handler
@@ -108,17 +138,18 @@ module ActiveRecord
108
138
  self.default_connection_handler = ConnectionAdapters::ConnectionHandler.new
109
139
  end
110
140
 
111
- module ClassMethods
141
+ module ClassMethods # :nodoc:
112
142
  def allocate
113
143
  define_attribute_methods
114
144
  super
115
145
  end
116
146
 
117
147
  def initialize_find_by_cache # :nodoc:
118
- self.find_by_statement_cache = {}.extend(Mutex_m)
148
+ @find_by_statement_cache = { true => Concurrent::Map.new, false => Concurrent::Map.new }
119
149
  end
120
150
 
121
151
  def inherited(child_class) # :nodoc:
152
+ # initialize cache at class definition for thread safety
122
153
  child_class.initialize_find_by_cache
123
154
  super
124
155
  end
@@ -126,74 +157,64 @@ module ActiveRecord
126
157
  def find(*ids) # :nodoc:
127
158
  # We don't have cache keys for this stuff yet
128
159
  return super unless ids.length == 1
129
- # Allow symbols to super to maintain compatibility for deprecated finders until Rails 5
130
- return super if ids.first.kind_of?(Symbol)
131
160
  return super if block_given? ||
132
161
  primary_key.nil? ||
133
- default_scopes.any? ||
134
- current_scope ||
135
- columns_hash.include?(inheritance_column) ||
136
- ids.first.kind_of?(Array)
137
-
138
- id = ids.first
139
- if ActiveRecord::Base === id
140
- id = id.id
141
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
142
- You are passing an instance of ActiveRecord::Base to `find`.
143
- Please pass the id of the object by calling `.id`
144
- MSG
145
- end
162
+ scope_attributes? ||
163
+ columns_hash.include?(inheritance_column)
164
+
165
+ id = ids.first
166
+
167
+ return super if StatementCache.unsupported_value?(id)
168
+
146
169
  key = primary_key
147
170
 
148
- s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
149
- find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
150
- where(key => params.bind).limit(1)
151
- }
171
+ statement = cached_find_by_statement(key) { |params|
172
+ where(key => params.bind).limit(1)
152
173
  }
153
- record = s.execute([id], self, connection).first
174
+
175
+ record = statement.execute([id], connection).first
154
176
  unless record
155
- raise RecordNotFound, "Couldn't find #{name} with '#{primary_key}'=#{id}"
177
+ raise RecordNotFound.new("Couldn't find #{name} with '#{primary_key}'=#{id}",
178
+ name, primary_key, id)
156
179
  end
157
180
  record
158
- rescue RangeError
159
- raise RecordNotFound, "Couldn't find #{name} with an out of range value for '#{primary_key}'"
181
+ rescue ::RangeError
182
+ raise RecordNotFound.new("Couldn't find #{name} with an out of range value for '#{primary_key}'",
183
+ name, primary_key)
160
184
  end
161
185
 
162
186
  def find_by(*args) # :nodoc:
163
- return super if current_scope || !(Hash === args.first) || reflect_on_all_aggregations.any?
164
- return super if default_scopes.any?
187
+ return super if scope_attributes? || reflect_on_all_aggregations.any? ||
188
+ columns_hash.key?(inheritance_column) && base_class != self
165
189
 
166
190
  hash = args.first
167
191
 
168
- return super if hash.values.any? { |v|
169
- v.nil? || Array === v || Hash === v
192
+ return super if !(Hash === hash) || hash.values.any? { |v|
193
+ StatementCache.unsupported_value?(v)
170
194
  }
171
195
 
172
196
  # We can't cache Post.find_by(author: david) ...yet
173
197
  return super unless hash.keys.all? { |k| columns_hash.has_key?(k.to_s) }
174
198
 
175
- key = hash.keys
199
+ keys = hash.keys
176
200
 
177
- klass = self
178
- s = find_by_statement_cache[key] || find_by_statement_cache.synchronize {
179
- find_by_statement_cache[key] ||= StatementCache.create(connection) { |params|
180
- wheres = key.each_with_object({}) { |param,o|
181
- o[param] = params.bind
182
- }
183
- klass.where(wheres).limit(1)
201
+ statement = cached_find_by_statement(keys) { |params|
202
+ wheres = keys.each_with_object({}) { |param, o|
203
+ o[param] = params.bind
184
204
  }
205
+ where(wheres).limit(1)
185
206
  }
186
207
  begin
187
- s.execute(hash.values, self, connection).first
188
- rescue TypeError => e
189
- raise ActiveRecord::StatementInvalid.new(e.message, e)
190
- rescue RangeError
208
+ statement.execute(hash.values, connection).first
209
+ rescue TypeError
210
+ raise ActiveRecord::StatementInvalid
211
+ rescue ::RangeError
191
212
  nil
192
213
  end
193
214
  end
194
215
 
195
216
  def find_by!(*args) # :nodoc:
196
- find_by(*args) or raise RecordNotFound.new("Couldn't find #{name}")
217
+ find_by(*args) || raise(RecordNotFound.new("Couldn't find #{name}", name))
197
218
  end
198
219
 
199
220
  def initialize_generated_modules # :nodoc:
@@ -203,7 +224,9 @@ module ActiveRecord
203
224
  def generated_association_methods
204
225
  @generated_association_methods ||= begin
205
226
  mod = const_set(:GeneratedAssociationMethods, Module.new)
227
+ private_constant :GeneratedAssociationMethods
206
228
  include mod
229
+
207
230
  mod
208
231
  end
209
232
  end
@@ -217,14 +240,14 @@ module ActiveRecord
217
240
  elsif !connected?
218
241
  "#{super} (call '#{super}.connection' to establish a connection)"
219
242
  elsif table_exists?
220
- attr_list = columns.map { |c| "#{c.name}: #{c.type}" } * ', '
243
+ attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ", "
221
244
  "#{super}(#{attr_list})"
222
245
  else
223
246
  "#{super}(Table doesn't exist)"
224
247
  end
225
248
  end
226
249
 
227
- # Overwrite the default class equality method to provide support for association proxies.
250
+ # Overwrite the default class equality method to provide support for decorated models.
228
251
  def ===(object)
229
252
  object.is_a?(self)
230
253
  end
@@ -232,33 +255,46 @@ module ActiveRecord
232
255
  # Returns an instance of <tt>Arel::Table</tt> loaded with the current table name.
233
256
  #
234
257
  # class Post < ActiveRecord::Base
235
- # scope :published_and_commented, -> { published.and(self.arel_table[:comments_count].gt(0)) }
258
+ # scope :published_and_commented, -> { published.and(arel_table[:comments_count].gt(0)) }
236
259
  # end
237
260
  def arel_table # :nodoc:
238
- @arel_table ||= Arel::Table.new(table_name, arel_engine)
261
+ @arel_table ||= Arel::Table.new(table_name, type_caster: type_caster)
239
262
  end
240
263
 
241
- # Returns the Arel engine.
242
- def arel_engine # :nodoc:
243
- @arel_engine ||=
244
- if Base == self || connection_handler.retrieve_connection_pool(self)
245
- self
246
- else
247
- superclass.arel_engine
248
- end
264
+ def arel_attribute(name, table = arel_table) # :nodoc:
265
+ name = attribute_alias(name) if attribute_alias?(name)
266
+ table[name]
267
+ end
268
+
269
+ def predicate_builder # :nodoc:
270
+ @predicate_builder ||= PredicateBuilder.new(table_metadata)
271
+ end
272
+
273
+ def type_caster # :nodoc:
274
+ TypeCaster::Map.new(self)
249
275
  end
250
276
 
251
277
  private
252
278
 
253
- def relation #:nodoc:
254
- relation = Relation.create(self, arel_table)
279
+ def cached_find_by_statement(key, &block)
280
+ cache = @find_by_statement_cache[connection.prepared_statements]
281
+ cache.compute_if_absent(key) { StatementCache.create(connection, &block) }
282
+ end
283
+
284
+ def relation
285
+ relation = Relation.create(self)
255
286
 
256
- if finder_needs_type_condition?
257
- relation.where(type_condition).create_with(inheritance_column.to_sym => sti_name)
258
- else
259
- relation
287
+ if finder_needs_type_condition? && !ignore_default_scope?
288
+ relation.where!(type_condition)
289
+ relation.create_with!(inheritance_column.to_s => sti_name)
290
+ else
291
+ relation
292
+ end
293
+ end
294
+
295
+ def table_metadata
296
+ TableMetadata.new(self, arel_table)
260
297
  end
261
- end
262
298
  end
263
299
 
264
300
  # New objects can be instantiated as either empty (pass no construction parameter) or pre-set with
@@ -269,16 +305,14 @@ module ActiveRecord
269
305
  # ==== Example:
270
306
  # # Instantiates a single new object
271
307
  # User.new(first_name: 'Jamie')
272
- def initialize(attributes = nil, options = {})
273
- @attributes = self.class._default_attributes.dup
308
+ def initialize(attributes = nil)
274
309
  self.class.define_attribute_methods
310
+ @attributes = self.class._default_attributes.deep_dup
275
311
 
276
312
  init_internals
277
313
  initialize_internals_callback
278
314
 
279
- # +options+ argument is only needed to make protected_attributes gem easier to hook.
280
- # Remove it when we drop support to this gem.
281
- init_attributes(attributes, options) if attributes
315
+ assign_attributes(attributes) if attributes
282
316
 
283
317
  yield self if block_given?
284
318
  _run_initialize_callbacks
@@ -286,7 +320,7 @@ module ActiveRecord
286
320
 
287
321
  # Initialize an empty model object from +coder+. +coder+ should be
288
322
  # the result of previously encoding an Active Record model, using
289
- # `encode_with`
323
+ # #encode_with.
290
324
  #
291
325
  # class Post < ActiveRecord::Base
292
326
  # end
@@ -300,14 +334,16 @@ module ActiveRecord
300
334
  # post.title # => 'hello world'
301
335
  def init_with(coder)
302
336
  coder = LegacyYamlAdapter.convert(self.class, coder)
303
- @attributes = coder['attributes']
337
+ @attributes = self.class.yaml_encoder.decode(coder)
304
338
 
305
339
  init_internals
306
340
 
307
- @new_record = coder['new_record']
341
+ @new_record = coder["new_record"]
308
342
 
309
343
  self.class.define_attribute_methods
310
344
 
345
+ yield self if block_given?
346
+
311
347
  _run_find_callbacks
312
348
  _run_initialize_callbacks
313
349
 
@@ -342,23 +378,22 @@ module ActiveRecord
342
378
 
343
379
  ##
344
380
  def initialize_dup(other) # :nodoc:
345
- @attributes = @attributes.dup
381
+ @attributes = @attributes.deep_dup
346
382
  @attributes.reset(self.class.primary_key)
347
383
 
348
384
  _run_initialize_callbacks
349
385
 
350
- @aggregation_cache = {}
351
- @association_cache = {}
352
-
353
- @new_record = true
354
- @destroyed = false
386
+ @new_record = true
387
+ @destroyed = false
388
+ @_start_transaction_state = {}
389
+ @transaction_state = nil
355
390
 
356
391
  super
357
392
  end
358
393
 
359
394
  # Populate +coder+ with attributes about this record that should be
360
395
  # serialized. The structure of +coder+ defined in this method is
361
- # guaranteed to match the structure of +coder+ passed to the +init_with+
396
+ # guaranteed to match the structure of +coder+ passed to the #init_with
362
397
  # method.
363
398
  #
364
399
  # Example:
@@ -369,11 +404,9 @@ module ActiveRecord
369
404
  # Post.new.encode_with(coder)
370
405
  # coder # => {"attributes" => {"id" => nil, ... }}
371
406
  def encode_with(coder)
372
- # FIXME: Remove this when we better serialize attributes
373
- coder['raw_attributes'] = attributes_before_type_cast
374
- coder['attributes'] = @attributes
375
- coder['new_record'] = new_record?
376
- coder['active_record_yaml_version'] = 0
407
+ self.class.yaml_encoder.encode(@attributes, coder)
408
+ coder["new_record"] = new_record?
409
+ coder["active_record_yaml_version"] = 2
377
410
  end
378
411
 
379
412
  # Returns true if +comparison_object+ is the same exact object, or +comparison_object+
@@ -397,7 +430,7 @@ module ActiveRecord
397
430
  # [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
398
431
  def hash
399
432
  if id
400
- id.hash
433
+ self.class.hash ^ id.hash
401
434
  else
402
435
  super
403
436
  end
@@ -419,7 +452,7 @@ module ActiveRecord
419
452
  # Allows sort on objects
420
453
  def <=>(other_object)
421
454
  if other_object.is_a?(self.class)
422
- self.to_key <=> other_object.to_key
455
+ to_key <=> other_object.to_key
423
456
  else
424
457
  super
425
458
  end
@@ -445,135 +478,82 @@ module ActiveRecord
445
478
  # We check defined?(@attributes) not to issue warnings if the object is
446
479
  # allocated but not initialized.
447
480
  inspection = if defined?(@attributes) && @attributes
448
- self.class.column_names.collect { |name|
449
- if has_attribute?(name)
450
- "#{name}: #{attribute_for_inspect(name)}"
451
- end
452
- }.compact.join(", ")
453
- else
454
- "not initialized"
455
- end
481
+ self.class.attribute_names.collect do |name|
482
+ if has_attribute?(name)
483
+ "#{name}: #{attribute_for_inspect(name)}"
484
+ end
485
+ end.compact.join(", ")
486
+ else
487
+ "not initialized"
488
+ end
489
+
456
490
  "#<#{self.class} #{inspection}>"
457
491
  end
458
492
 
459
- # Takes a PP and prettily prints this record to it, allowing you to get a nice result from `pp record`
493
+ # Takes a PP and prettily prints this record to it, allowing you to get a nice result from <tt>pp record</tt>
460
494
  # when pp is required.
461
495
  def pretty_print(pp)
462
496
  return super if custom_inspect_method_defined?
463
497
  pp.object_address_group(self) do
464
498
  if defined?(@attributes) && @attributes
465
499
  column_names = self.class.column_names.select { |name| has_attribute?(name) || new_record? }
466
- pp.seplist(column_names, proc { pp.text ',' }) do |column_name|
500
+ pp.seplist(column_names, proc { pp.text "," }) do |column_name|
467
501
  column_value = read_attribute(column_name)
468
- pp.breakable ' '
502
+ pp.breakable " "
469
503
  pp.group(1) do
470
504
  pp.text column_name
471
- pp.text ':'
505
+ pp.text ":"
472
506
  pp.breakable
473
507
  pp.pp column_value
474
508
  end
475
509
  end
476
510
  else
477
- pp.breakable ' '
478
- pp.text 'not initialized'
511
+ pp.breakable " "
512
+ pp.text "not initialized"
479
513
  end
480
514
  end
481
515
  end
482
516
 
483
517
  # Returns a hash of the given methods with their names as keys and returned values as values.
484
518
  def slice(*methods)
485
- Hash[methods.map! { |method| [method, public_send(method)] }].with_indifferent_access
519
+ Hash[methods.flatten.map! { |method| [method, public_send(method)] }].with_indifferent_access
486
520
  end
487
521
 
488
522
  private
489
523
 
490
- def set_transaction_state(state) # :nodoc:
491
- @transaction_state = state
492
- end
493
-
494
- def has_transactional_callbacks? # :nodoc:
495
- !_rollback_callbacks.empty? || !_commit_callbacks.empty?
496
- end
497
-
498
- # Updates the attributes on this particular ActiveRecord object so that
499
- # if it is associated with a transaction, then the state of the AR object
500
- # will be updated to reflect the current state of the transaction
501
- #
502
- # The @transaction_state variable stores the states of the associated
503
- # transaction. This relies on the fact that a transaction can only be in
504
- # one rollback or commit (otherwise a list of states would be required)
505
- # Each AR object inside of a transaction carries that transaction's
506
- # TransactionState.
507
- #
508
- # This method checks to see if the ActiveRecord object's state reflects
509
- # the TransactionState, and rolls back or commits the ActiveRecord object
510
- # as appropriate.
511
- #
512
- # Since ActiveRecord objects can be inside multiple transactions, this
513
- # method recursively goes through the parent of the TransactionState and
514
- # checks if the ActiveRecord object reflects the state of the object.
515
- def sync_with_transaction_state
516
- update_attributes_from_transaction_state(@transaction_state, 0)
517
- end
524
+ # +Array#flatten+ will call +#to_ary+ (recursively) on each of the elements of
525
+ # the array, and then rescues from the possible +NoMethodError+. If those elements are
526
+ # +ActiveRecord::Base+'s, then this triggers the various +method_missing+'s that we have,
527
+ # which significantly impacts upon performance.
528
+ #
529
+ # So we can avoid the +method_missing+ hit by explicitly defining +#to_ary+ as +nil+ here.
530
+ #
531
+ # See also https://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
532
+ def to_ary
533
+ nil
534
+ end
518
535
 
519
- def update_attributes_from_transaction_state(transaction_state, depth)
520
- @reflects_state = [false] if depth == 0
536
+ def init_internals
537
+ @readonly = false
538
+ @destroyed = false
539
+ @marked_for_destruction = false
540
+ @destroyed_by_association = nil
541
+ @new_record = true
542
+ @_start_transaction_state = {}
543
+ @transaction_state = nil
544
+ end
521
545
 
522
- if transaction_state && transaction_state.finalized? && !has_transactional_callbacks?
523
- unless @reflects_state[depth]
524
- restore_transaction_record_state if transaction_state.rolledback?
525
- clear_transaction_record_state
526
- @reflects_state[depth] = true
527
- end
546
+ def initialize_internals_callback
547
+ end
528
548
 
529
- if transaction_state.parent && !@reflects_state[depth+1]
530
- update_attributes_from_transaction_state(transaction_state.parent, depth+1)
549
+ def thaw
550
+ if frozen?
551
+ @attributes = @attributes.dup
531
552
  end
532
553
  end
533
- end
534
-
535
- # Under Ruby 1.9, Array#flatten will call #to_ary (recursively) on each of the elements
536
- # of the array, and then rescues from the possible NoMethodError. If those elements are
537
- # ActiveRecord::Base's, then this triggers the various method_missing's that we have,
538
- # which significantly impacts upon performance.
539
- #
540
- # So we can avoid the method_missing hit by explicitly defining #to_ary as nil here.
541
- #
542
- # See also http://tenderlovemaking.com/2011/06/28/til-its-ok-to-return-nil-from-to_ary.html
543
- def to_ary # :nodoc:
544
- nil
545
- end
546
-
547
- def init_internals
548
- @aggregation_cache = {}
549
- @association_cache = {}
550
- @readonly = false
551
- @destroyed = false
552
- @marked_for_destruction = false
553
- @destroyed_by_association = nil
554
- @new_record = true
555
- @txn = nil
556
- @_start_transaction_state = {}
557
- @transaction_state = nil
558
- end
559
-
560
- def initialize_internals_callback
561
- end
562
554
 
563
- # This method is needed to make protected_attributes gem easier to hook.
564
- # Remove it when we drop support to this gem.
565
- def init_attributes(attributes, options)
566
- assign_attributes(attributes)
567
- end
568
-
569
- def thaw
570
- if frozen?
571
- @attributes = @attributes.dup
555
+ def custom_inspect_method_defined?
556
+ self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
572
557
  end
573
- end
574
-
575
- def custom_inspect_method_defined?
576
- self.class.instance_method(:inspect).owner != ActiveRecord::Base.instance_method(:inspect).owner
577
- end
578
558
  end
579
559
  end