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