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,4 +1,6 @@
1
- require 'active_support/core_ext/hash/indifferent_access'
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/hash/indifferent_access"
2
4
 
3
5
  module ActiveRecord
4
6
  # Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
@@ -9,39 +11,66 @@ module ActiveRecord
9
11
  # of the model. This is very helpful for easily exposing store keys to a form or elsewhere that's
10
12
  # already built around just accessing attributes on the model.
11
13
  #
14
+ # Every accessor comes with dirty tracking methods (+key_changed?+, +key_was+ and +key_change+) and
15
+ # methods to access the changes made during the last save (+saved_change_to_key?+, +saved_change_to_key+ and
16
+ # +key_before_last_save+).
17
+ #
18
+ # NOTE: There is no +key_will_change!+ method for accessors, use +store_will_change!+ instead.
19
+ #
12
20
  # Make sure that you declare the database column used for the serialized store as a text, so there's
13
21
  # plenty of room.
14
22
  #
15
23
  # You can set custom coder to encode/decode your serialized attributes to/from different formats.
16
24
  # JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
17
25
  #
18
- # NOTE - If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
19
- # the serialization provided by +store+. Simply use +store_accessor+ instead to generate
26
+ # NOTE: If you are using structured database data types (eg. PostgreSQL +hstore+/+json+, or MySQL 5.7+
27
+ # +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
28
+ # Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
20
29
  # the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
21
30
  # using a symbol.
22
31
  #
32
+ # NOTE: The default validations with the exception of +uniqueness+ will work.
33
+ # For example, if you want to check for +uniqueness+ with +hstore+ you will
34
+ # need to use a custom validation to handle it.
35
+ #
23
36
  # Examples:
24
37
  #
25
38
  # class User < ActiveRecord::Base
26
39
  # store :settings, accessors: [ :color, :homepage ], coder: JSON
40
+ # store :parent, accessors: [ :name ], coder: JSON, prefix: true
41
+ # store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
42
+ # store :settings, accessors: [ :two_factor_auth ], suffix: true
43
+ # store :settings, accessors: [ :login_retry ], suffix: :config
27
44
  # end
28
45
  #
29
- # u = User.new(color: 'black', homepage: '37signals.com')
46
+ # u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
30
47
  # u.color # Accessor stored attribute
48
+ # u.parent_name # Accessor stored attribute with prefix
49
+ # u.partner_name # Accessor stored attribute with custom prefix
50
+ # u.two_factor_auth_settings # Accessor stored attribute with suffix
51
+ # u.login_retry_config # Accessor stored attribute with custom suffix
31
52
  # u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
32
53
  #
33
54
  # # There is no difference between strings and symbols for accessing custom attributes
34
55
  # u.settings[:country] # => 'Denmark'
35
56
  # u.settings['country'] # => 'Denmark'
36
57
  #
58
+ # # Dirty tracking
59
+ # u.color = 'green'
60
+ # u.color_changed? # => true
61
+ # u.color_was # => 'black'
62
+ # u.color_change # => ['black', 'red']
63
+ #
37
64
  # # Add additional accessors to an existing store through store_accessor
38
65
  # class SuperUser < User
39
66
  # store_accessor :settings, :privileges, :servants
67
+ # store_accessor :parent, :birthday, prefix: true
68
+ # store_accessor :settings, :secret_question, suffix: :config
40
69
  # end
41
70
  #
42
- # The stored attribute names can be retrieved using +stored_attributes+.
71
+ # The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
43
72
  #
44
- # User.stored_attributes[:settings] # [:color, :homepage]
73
+ # User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
45
74
  #
46
75
  # == Overwriting default accessors
47
76
  #
@@ -73,22 +102,79 @@ module ActiveRecord
73
102
 
74
103
  module ClassMethods
75
104
  def store(store_attribute, options = {})
76
- serialize store_attribute, IndifferentCoder.new(options[:coder])
77
- store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
105
+ serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
106
+ store_accessor(store_attribute, options[:accessors], **options.slice(:prefix, :suffix)) if options.has_key? :accessors
78
107
  end
79
108
 
80
- def store_accessor(store_attribute, *keys)
109
+ def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
81
110
  keys = keys.flatten
82
111
 
112
+ accessor_prefix =
113
+ case prefix
114
+ when String, Symbol
115
+ "#{prefix}_"
116
+ when TrueClass
117
+ "#{store_attribute}_"
118
+ else
119
+ ""
120
+ end
121
+ accessor_suffix =
122
+ case suffix
123
+ when String, Symbol
124
+ "_#{suffix}"
125
+ when TrueClass
126
+ "_#{store_attribute}"
127
+ else
128
+ ""
129
+ end
130
+
83
131
  _store_accessors_module.module_eval do
84
132
  keys.each do |key|
85
- define_method("#{key}=") do |value|
133
+ accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
134
+
135
+ define_method("#{accessor_key}=") do |value|
86
136
  write_store_attribute(store_attribute, key, value)
87
137
  end
88
138
 
89
- define_method(key) do
139
+ define_method(accessor_key) do
90
140
  read_store_attribute(store_attribute, key)
91
141
  end
142
+
143
+ define_method("#{accessor_key}_changed?") do
144
+ return false unless attribute_changed?(store_attribute)
145
+ prev_store, new_store = changes[store_attribute]
146
+ prev_store&.dig(key) != new_store&.dig(key)
147
+ end
148
+
149
+ define_method("#{accessor_key}_change") do
150
+ return unless attribute_changed?(store_attribute)
151
+ prev_store, new_store = changes[store_attribute]
152
+ [prev_store&.dig(key), new_store&.dig(key)]
153
+ end
154
+
155
+ define_method("#{accessor_key}_was") do
156
+ return unless attribute_changed?(store_attribute)
157
+ prev_store, _new_store = changes[store_attribute]
158
+ prev_store&.dig(key)
159
+ end
160
+
161
+ define_method("saved_change_to_#{accessor_key}?") do
162
+ return false unless saved_change_to_attribute?(store_attribute)
163
+ prev_store, new_store = saved_change_to_attribute(store_attribute)
164
+ prev_store&.dig(key) != new_store&.dig(key)
165
+ end
166
+
167
+ define_method("saved_change_to_#{accessor_key}") do
168
+ return unless saved_change_to_attribute?(store_attribute)
169
+ prev_store, new_store = saved_change_to_attribute(store_attribute)
170
+ [prev_store&.dig(key), new_store&.dig(key)]
171
+ end
172
+
173
+ define_method("#{accessor_key}_before_last_save") do
174
+ return unless saved_change_to_attribute?(store_attribute)
175
+ prev_store, _new_store = saved_change_to_attribute(store_attribute)
176
+ prev_store&.dig(key)
177
+ end
92
178
  end
93
179
  end
94
180
 
@@ -109,27 +195,26 @@ module ActiveRecord
109
195
 
110
196
  def stored_attributes
111
197
  parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
112
- if self.local_stored_attributes
113
- parent.merge!(self.local_stored_attributes) { |k, a, b| a | b }
198
+ if local_stored_attributes
199
+ parent.merge!(local_stored_attributes) { |k, a, b| a | b }
114
200
  end
115
201
  parent
116
202
  end
117
203
  end
118
204
 
119
- protected
120
- def read_store_attribute(store_attribute, key)
205
+ private
206
+ def read_store_attribute(store_attribute, key) # :doc:
121
207
  accessor = store_accessor_for(store_attribute)
122
208
  accessor.read(self, store_attribute, key)
123
209
  end
124
210
 
125
- def write_store_attribute(store_attribute, key, value)
211
+ def write_store_attribute(store_attribute, key, value) # :doc:
126
212
  accessor = store_accessor_for(store_attribute)
127
213
  accessor.write(self, store_attribute, key, value)
128
214
  end
129
215
 
130
- private
131
216
  def store_accessor_for(store_attribute)
132
- type_for_attribute(store_attribute.to_s).accessor
217
+ type_for_attribute(store_attribute).accessor
133
218
  end
134
219
 
135
220
  class HashAccessor # :nodoc:
@@ -172,34 +257,34 @@ module ActiveRecord
172
257
  end
173
258
  end
174
259
 
175
- class IndifferentCoder # :nodoc:
176
- def initialize(coder_or_class_name)
177
- @coder =
178
- if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
179
- coder_or_class_name
180
- else
181
- ActiveRecord::Coders::YAMLColumn.new(coder_or_class_name || Object)
182
- end
183
- end
260
+ class IndifferentCoder # :nodoc:
261
+ def initialize(attr_name, coder_or_class_name)
262
+ @coder =
263
+ if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
264
+ coder_or_class_name
265
+ else
266
+ ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
267
+ end
268
+ end
184
269
 
185
- def dump(obj)
186
- @coder.dump self.class.as_indifferent_hash(obj)
187
- end
270
+ def dump(obj)
271
+ @coder.dump self.class.as_indifferent_hash(obj)
272
+ end
188
273
 
189
- def load(yaml)
190
- self.class.as_indifferent_hash(@coder.load(yaml || ''))
191
- end
274
+ def load(yaml)
275
+ self.class.as_indifferent_hash(@coder.load(yaml || ""))
276
+ end
192
277
 
193
- def self.as_indifferent_hash(obj)
194
- case obj
195
- when ActiveSupport::HashWithIndifferentAccess
196
- obj
197
- when Hash
198
- obj.with_indifferent_access
199
- else
200
- ActiveSupport::HashWithIndifferentAccess.new
278
+ def self.as_indifferent_hash(obj)
279
+ case obj
280
+ when ActiveSupport::HashWithIndifferentAccess
281
+ obj
282
+ when Hash
283
+ obj.with_indifferent_access
284
+ else
285
+ ActiveSupport::HashWithIndifferentAccess.new
286
+ end
201
287
  end
202
288
  end
203
- end
204
289
  end
205
290
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ # ActiveRecord::Suppressor prevents the receiver from being saved during
5
+ # a given block.
6
+ #
7
+ # For example, here's a pattern of creating notifications when new comments
8
+ # are posted. (The notification may in turn trigger an email, a push
9
+ # notification, or just appear in the UI somewhere):
10
+ #
11
+ # class Comment < ActiveRecord::Base
12
+ # belongs_to :commentable, polymorphic: true
13
+ # after_create -> { Notification.create! comment: self,
14
+ # recipients: commentable.recipients }
15
+ # end
16
+ #
17
+ # That's what you want the bulk of the time. New comment creates a new
18
+ # Notification. But there may well be off cases, like copying a commentable
19
+ # and its comments, where you don't want that. So you'd have a concern
20
+ # something like this:
21
+ #
22
+ # module Copyable
23
+ # def copy_to(destination)
24
+ # Notification.suppress do
25
+ # # Copy logic that creates new comments that we do not want
26
+ # # triggering notifications.
27
+ # end
28
+ # end
29
+ # end
30
+ module Suppressor
31
+ extend ActiveSupport::Concern
32
+
33
+ module ClassMethods
34
+ def suppress(&block)
35
+ previous_state = SuppressorRegistry.suppressed[name]
36
+ SuppressorRegistry.suppressed[name] = true
37
+ yield
38
+ ensure
39
+ SuppressorRegistry.suppressed[name] = previous_state
40
+ end
41
+ end
42
+
43
+ def save(*, **) # :nodoc:
44
+ SuppressorRegistry.suppressed[self.class.name] ? true : super
45
+ end
46
+
47
+ def save!(*, **) # :nodoc:
48
+ SuppressorRegistry.suppressed[self.class.name] ? true : super
49
+ end
50
+ end
51
+
52
+ class SuppressorRegistry # :nodoc:
53
+ extend ActiveSupport::PerThreadRegistry
54
+
55
+ attr_reader :suppressed
56
+
57
+ def initialize
58
+ @suppressed = {}
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,90 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class TableMetadata # :nodoc:
5
+ delegate :foreign_type, :foreign_key, :join_primary_key, :join_foreign_key, to: :association, prefix: true
6
+
7
+ def initialize(klass, arel_table, association = nil, types = klass)
8
+ @klass = klass
9
+ @types = types
10
+ @arel_table = arel_table
11
+ @association = association
12
+ end
13
+
14
+ def resolve_column_aliases(hash)
15
+ new_hash = hash.dup
16
+ hash.each_key do |key|
17
+ if key.is_a?(Symbol) && new_key = klass.attribute_aliases[key.to_s]
18
+ new_hash[new_key] = new_hash.delete(key)
19
+ end
20
+ end
21
+ new_hash
22
+ end
23
+
24
+ def arel_attribute(column_name)
25
+ if klass
26
+ klass.arel_attribute(column_name, arel_table)
27
+ else
28
+ arel_table[column_name]
29
+ end
30
+ end
31
+
32
+ def type(column_name)
33
+ types.type_for_attribute(column_name)
34
+ end
35
+
36
+ def has_column?(column_name)
37
+ klass && klass.columns_hash.key?(column_name.to_s)
38
+ end
39
+
40
+ def associated_with?(association_name)
41
+ klass && klass._reflect_on_association(association_name)
42
+ end
43
+
44
+ def associated_table(table_name)
45
+ association = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.to_s.singularize)
46
+
47
+ if !association && table_name == arel_table.name
48
+ self
49
+ elsif association && !association.polymorphic?
50
+ association_klass = association.klass
51
+ arel_table = association_klass.arel_table.alias(table_name)
52
+ TableMetadata.new(association_klass, arel_table, association)
53
+ else
54
+ type_caster = TypeCaster::Connection.new(klass, table_name)
55
+ arel_table = Arel::Table.new(table_name, type_caster: type_caster)
56
+ TableMetadata.new(nil, arel_table, association, type_caster)
57
+ end
58
+ end
59
+
60
+ def associated_predicate_builder(table_name)
61
+ associated_table(table_name).predicate_builder
62
+ end
63
+
64
+ def polymorphic_association?
65
+ association && association.polymorphic?
66
+ end
67
+
68
+ def aggregated_with?(aggregation_name)
69
+ klass && reflect_on_aggregation(aggregation_name)
70
+ end
71
+
72
+ def reflect_on_aggregation(aggregation_name)
73
+ klass.reflect_on_aggregation(aggregation_name)
74
+ end
75
+
76
+ protected
77
+ def predicate_builder
78
+ if klass
79
+ predicate_builder = klass.predicate_builder.dup
80
+ predicate_builder.instance_variable_set(:@table, self)
81
+ predicate_builder
82
+ else
83
+ PredicateBuilder.new(self)
84
+ end
85
+ end
86
+
87
+ private
88
+ attr_reader :klass, :types, :arel_table, :association
89
+ end
90
+ end