activerecord 4.2.9 → 6.1.4.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 (374) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +964 -1382
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +15 -14
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/aggregations.rb +266 -251
  8. data/lib/active_record/association_relation.rb +40 -15
  9. data/lib/active_record/associations/alias_tracker.rb +40 -43
  10. data/lib/active_record/associations/association.rb +162 -69
  11. data/lib/active_record/associations/association_scope.rb +105 -130
  12. data/lib/active_record/associations/belongs_to_association.rb +83 -65
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
  14. data/lib/active_record/associations/builder/association.rb +57 -43
  15. data/lib/active_record/associations/builder/belongs_to.rb +74 -57
  16. data/lib/active_record/associations/builder/collection_association.rb +15 -37
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
  18. data/lib/active_record/associations/builder/has_many.rb +13 -5
  19. data/lib/active_record/associations/builder/has_one.rb +44 -6
  20. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  21. data/lib/active_record/associations/collection_association.rb +148 -287
  22. data/lib/active_record/associations/collection_proxy.rb +252 -150
  23. data/lib/active_record/associations/foreign_association.rb +23 -1
  24. data/lib/active_record/associations/has_many_association.rb +56 -98
  25. data/lib/active_record/associations/has_many_through_association.rb +68 -89
  26. data/lib/active_record/associations/has_one_association.rb +73 -47
  27. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  28. data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
  29. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  30. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  31. data/lib/active_record/associations/join_dependency.rb +174 -169
  32. data/lib/active_record/associations/preloader/association.rb +108 -115
  33. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  34. data/lib/active_record/associations/preloader.rb +97 -94
  35. data/lib/active_record/associations/singular_association.rb +18 -39
  36. data/lib/active_record/associations/through_association.rb +39 -19
  37. data/lib/active_record/associations.rb +1845 -1598
  38. data/lib/active_record/attribute_assignment.rb +59 -185
  39. data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
  40. data/lib/active_record/attribute_methods/dirty.rb +168 -148
  41. data/lib/active_record/attribute_methods/primary_key.rb +93 -83
  42. data/lib/active_record/attribute_methods/query.rb +8 -10
  43. data/lib/active_record/attribute_methods/read.rb +19 -79
  44. data/lib/active_record/attribute_methods/serialization.rb +49 -24
  45. data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
  46. data/lib/active_record/attribute_methods/write.rb +24 -55
  47. data/lib/active_record/attribute_methods.rb +149 -154
  48. data/lib/active_record/attributes.rb +234 -78
  49. data/lib/active_record/autosave_association.rb +133 -60
  50. data/lib/active_record/base.rb +46 -46
  51. data/lib/active_record/callbacks.rb +234 -79
  52. data/lib/active_record/coders/json.rb +3 -1
  53. data/lib/active_record/coders/yaml_column.rb +34 -13
  54. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
  55. data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
  56. data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
  57. data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
  58. data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
  59. data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
  60. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
  61. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
  62. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  63. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
  64. data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
  65. data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
  66. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
  67. data/lib/active_record/connection_adapters/column.rb +67 -40
  68. data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
  69. data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
  70. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  71. data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
  72. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  73. data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
  74. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
  75. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  78. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
  79. data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
  80. data/lib/active_record/connection_adapters/pool_config.rb +73 -0
  81. data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
  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 -58
  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 +4 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
  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 +14 -19
  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 -4
  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/interval.rb +49 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  101. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  102. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  103. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  104. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
  106. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
  107. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  108. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  109. data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
  110. data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
  111. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  112. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  114. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  115. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
  116. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
  117. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  118. data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
  119. data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
  120. data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
  121. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
  122. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  123. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  126. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  127. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
  128. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
  129. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  130. data/lib/active_record/connection_adapters.rb +52 -0
  131. data/lib/active_record/connection_handling.rb +314 -41
  132. data/lib/active_record/core.rb +458 -241
  133. data/lib/active_record/counter_cache.rb +70 -49
  134. data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
  135. data/lib/active_record/database_configurations/database_config.rb +80 -0
  136. data/lib/active_record/database_configurations/hash_config.rb +96 -0
  137. data/lib/active_record/database_configurations/url_config.rb +53 -0
  138. data/lib/active_record/database_configurations.rb +272 -0
  139. data/lib/active_record/delegated_type.rb +209 -0
  140. data/lib/active_record/destroy_association_async_job.rb +36 -0
  141. data/lib/active_record/dynamic_matchers.rb +87 -106
  142. data/lib/active_record/enum.rb +211 -92
  143. data/lib/active_record/errors.rb +224 -54
  144. data/lib/active_record/explain.rb +27 -11
  145. data/lib/active_record/explain_registry.rb +4 -2
  146. data/lib/active_record/explain_subscriber.rb +10 -5
  147. data/lib/active_record/fixture_set/file.rb +33 -14
  148. data/lib/active_record/fixture_set/model_metadata.rb +32 -0
  149. data/lib/active_record/fixture_set/render_context.rb +17 -0
  150. data/lib/active_record/fixture_set/table_row.rb +152 -0
  151. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  152. data/lib/active_record/fixtures.rb +275 -500
  153. data/lib/active_record/gem_version.rb +6 -4
  154. data/lib/active_record/inheritance.rb +175 -110
  155. data/lib/active_record/insert_all.rb +212 -0
  156. data/lib/active_record/integration.rb +121 -29
  157. data/lib/active_record/internal_metadata.rb +62 -0
  158. data/lib/active_record/legacy_yaml_adapter.rb +27 -5
  159. data/lib/active_record/locale/en.yml +3 -2
  160. data/lib/active_record/locking/optimistic.rb +98 -92
  161. data/lib/active_record/locking/pessimistic.rb +22 -6
  162. data/lib/active_record/log_subscriber.rb +93 -31
  163. data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
  164. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  165. data/lib/active_record/middleware/database_selector.rb +77 -0
  166. data/lib/active_record/migration/command_recorder.rb +185 -90
  167. data/lib/active_record/migration/compatibility.rb +295 -0
  168. data/lib/active_record/migration/join_table.rb +8 -7
  169. data/lib/active_record/migration.rb +673 -325
  170. data/lib/active_record/model_schema.rb +418 -113
  171. data/lib/active_record/nested_attributes.rb +263 -224
  172. data/lib/active_record/no_touching.rb +15 -2
  173. data/lib/active_record/null_relation.rb +24 -38
  174. data/lib/active_record/persistence.rb +572 -136
  175. data/lib/active_record/query_cache.rb +29 -23
  176. data/lib/active_record/querying.rb +50 -31
  177. data/lib/active_record/railtie.rb +170 -51
  178. data/lib/active_record/railties/console_sandbox.rb +3 -3
  179. data/lib/active_record/railties/controller_runtime.rb +34 -33
  180. data/lib/active_record/railties/databases.rake +523 -199
  181. data/lib/active_record/readonly_attributes.rb +9 -4
  182. data/lib/active_record/reflection.rb +454 -291
  183. data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
  184. data/lib/active_record/relation/batches.rb +217 -59
  185. data/lib/active_record/relation/calculations.rb +324 -249
  186. data/lib/active_record/relation/delegation.rb +76 -84
  187. data/lib/active_record/relation/finder_methods.rb +316 -242
  188. data/lib/active_record/relation/from_clause.rb +30 -0
  189. data/lib/active_record/relation/merger.rb +95 -103
  190. data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
  191. data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
  192. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  193. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
  194. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  195. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  196. data/lib/active_record/relation/predicate_builder.rb +136 -122
  197. data/lib/active_record/relation/query_attribute.rb +50 -0
  198. data/lib/active_record/relation/query_methods.rb +757 -413
  199. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  200. data/lib/active_record/relation/spawn_methods.rb +18 -20
  201. data/lib/active_record/relation/where_clause.rb +239 -0
  202. data/lib/active_record/relation.rb +554 -343
  203. data/lib/active_record/result.rb +91 -47
  204. data/lib/active_record/runtime_registry.rb +6 -4
  205. data/lib/active_record/sanitization.rb +134 -122
  206. data/lib/active_record/schema.rb +21 -24
  207. data/lib/active_record/schema_dumper.rb +141 -92
  208. data/lib/active_record/schema_migration.rb +24 -23
  209. data/lib/active_record/scoping/default.rb +96 -83
  210. data/lib/active_record/scoping/named.rb +78 -36
  211. data/lib/active_record/scoping.rb +45 -27
  212. data/lib/active_record/secure_token.rb +48 -0
  213. data/lib/active_record/serialization.rb +8 -6
  214. data/lib/active_record/signed_id.rb +116 -0
  215. data/lib/active_record/statement_cache.rb +89 -36
  216. data/lib/active_record/store.rb +128 -43
  217. data/lib/active_record/suppressor.rb +61 -0
  218. data/lib/active_record/table_metadata.rb +81 -0
  219. data/lib/active_record/tasks/database_tasks.rb +364 -130
  220. data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
  221. data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
  222. data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
  223. data/lib/active_record/test_databases.rb +24 -0
  224. data/lib/active_record/test_fixtures.rb +287 -0
  225. data/lib/active_record/timestamp.rb +86 -43
  226. data/lib/active_record/touch_later.rb +65 -0
  227. data/lib/active_record/transactions.rb +182 -163
  228. data/lib/active_record/translation.rb +3 -1
  229. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  230. data/lib/active_record/type/date.rb +4 -45
  231. data/lib/active_record/type/date_time.rb +4 -49
  232. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  233. data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
  234. data/lib/active_record/type/internal/timezone.rb +17 -0
  235. data/lib/active_record/type/json.rb +30 -0
  236. data/lib/active_record/type/serialized.rb +27 -15
  237. data/lib/active_record/type/text.rb +2 -2
  238. data/lib/active_record/type/time.rb +21 -16
  239. data/lib/active_record/type/type_map.rb +16 -19
  240. data/lib/active_record/type/unsigned_integer.rb +9 -8
  241. data/lib/active_record/type.rb +84 -23
  242. data/lib/active_record/type_caster/connection.rb +33 -0
  243. data/lib/active_record/type_caster/map.rb +23 -0
  244. data/lib/active_record/type_caster.rb +9 -0
  245. data/lib/active_record/validations/absence.rb +25 -0
  246. data/lib/active_record/validations/associated.rb +12 -4
  247. data/lib/active_record/validations/length.rb +26 -0
  248. data/lib/active_record/validations/numericality.rb +35 -0
  249. data/lib/active_record/validations/presence.rb +14 -13
  250. data/lib/active_record/validations/uniqueness.rb +63 -56
  251. data/lib/active_record/validations.rb +39 -35
  252. data/lib/active_record/version.rb +3 -1
  253. data/lib/active_record.rb +42 -29
  254. data/lib/arel/alias_predication.rb +9 -0
  255. data/lib/arel/attributes/attribute.rb +41 -0
  256. data/lib/arel/collectors/bind.rb +29 -0
  257. data/lib/arel/collectors/composite.rb +39 -0
  258. data/lib/arel/collectors/plain_string.rb +20 -0
  259. data/lib/arel/collectors/sql_string.rb +27 -0
  260. data/lib/arel/collectors/substitute_binds.rb +35 -0
  261. data/lib/arel/crud.rb +42 -0
  262. data/lib/arel/delete_manager.rb +18 -0
  263. data/lib/arel/errors.rb +9 -0
  264. data/lib/arel/expressions.rb +29 -0
  265. data/lib/arel/factory_methods.rb +49 -0
  266. data/lib/arel/insert_manager.rb +49 -0
  267. data/lib/arel/math.rb +45 -0
  268. data/lib/arel/nodes/and.rb +32 -0
  269. data/lib/arel/nodes/ascending.rb +23 -0
  270. data/lib/arel/nodes/binary.rb +126 -0
  271. data/lib/arel/nodes/bind_param.rb +44 -0
  272. data/lib/arel/nodes/case.rb +55 -0
  273. data/lib/arel/nodes/casted.rb +62 -0
  274. data/lib/arel/nodes/comment.rb +29 -0
  275. data/lib/arel/nodes/count.rb +12 -0
  276. data/lib/arel/nodes/delete_statement.rb +45 -0
  277. data/lib/arel/nodes/descending.rb +23 -0
  278. data/lib/arel/nodes/equality.rb +15 -0
  279. data/lib/arel/nodes/extract.rb +24 -0
  280. data/lib/arel/nodes/false.rb +16 -0
  281. data/lib/arel/nodes/full_outer_join.rb +8 -0
  282. data/lib/arel/nodes/function.rb +44 -0
  283. data/lib/arel/nodes/grouping.rb +11 -0
  284. data/lib/arel/nodes/homogeneous_in.rb +76 -0
  285. data/lib/arel/nodes/in.rb +15 -0
  286. data/lib/arel/nodes/infix_operation.rb +92 -0
  287. data/lib/arel/nodes/inner_join.rb +8 -0
  288. data/lib/arel/nodes/insert_statement.rb +37 -0
  289. data/lib/arel/nodes/join_source.rb +20 -0
  290. data/lib/arel/nodes/matches.rb +18 -0
  291. data/lib/arel/nodes/named_function.rb +23 -0
  292. data/lib/arel/nodes/node.rb +51 -0
  293. data/lib/arel/nodes/node_expression.rb +13 -0
  294. data/lib/arel/nodes/ordering.rb +27 -0
  295. data/lib/arel/nodes/outer_join.rb +8 -0
  296. data/lib/arel/nodes/over.rb +15 -0
  297. data/lib/arel/nodes/regexp.rb +16 -0
  298. data/lib/arel/nodes/right_outer_join.rb +8 -0
  299. data/lib/arel/nodes/select_core.rb +67 -0
  300. data/lib/arel/nodes/select_statement.rb +41 -0
  301. data/lib/arel/nodes/sql_literal.rb +19 -0
  302. data/lib/arel/nodes/string_join.rb +11 -0
  303. data/lib/arel/nodes/table_alias.rb +31 -0
  304. data/lib/arel/nodes/terminal.rb +16 -0
  305. data/lib/arel/nodes/true.rb +16 -0
  306. data/lib/arel/nodes/unary.rb +44 -0
  307. data/lib/arel/nodes/unary_operation.rb +20 -0
  308. data/lib/arel/nodes/unqualified_column.rb +22 -0
  309. data/lib/arel/nodes/update_statement.rb +41 -0
  310. data/lib/arel/nodes/values_list.rb +9 -0
  311. data/lib/arel/nodes/window.rb +126 -0
  312. data/lib/arel/nodes/with.rb +11 -0
  313. data/lib/arel/nodes.rb +70 -0
  314. data/lib/arel/order_predications.rb +13 -0
  315. data/lib/arel/predications.rb +250 -0
  316. data/lib/arel/select_manager.rb +270 -0
  317. data/lib/arel/table.rb +118 -0
  318. data/lib/arel/tree_manager.rb +72 -0
  319. data/lib/arel/update_manager.rb +34 -0
  320. data/lib/arel/visitors/dot.rb +308 -0
  321. data/lib/arel/visitors/mysql.rb +93 -0
  322. data/lib/arel/visitors/postgresql.rb +120 -0
  323. data/lib/arel/visitors/sqlite.rb +38 -0
  324. data/lib/arel/visitors/to_sql.rb +899 -0
  325. data/lib/arel/visitors/visitor.rb +45 -0
  326. data/lib/arel/visitors.rb +13 -0
  327. data/lib/arel/window_predications.rb +9 -0
  328. data/lib/arel.rb +54 -0
  329. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  330. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  331. data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
  332. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
  333. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
  334. data/lib/rails/generators/active_record/migration.rb +35 -1
  335. data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
  336. data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
  337. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  338. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +172 -65
  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 -163
  349. data/lib/active_record/attribute_decorators.rb +0 -66
  350. data/lib/active_record/attribute_set/builder.rb +0 -106
  351. data/lib/active_record/attribute_set.rb +0 -81
  352. data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
  353. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  354. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  355. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  356. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  357. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  358. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  359. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  360. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  361. data/lib/active_record/type/big_integer.rb +0 -13
  362. data/lib/active_record/type/binary.rb +0 -50
  363. data/lib/active_record/type/boolean.rb +0 -31
  364. data/lib/active_record/type/decimal.rb +0 -64
  365. data/lib/active_record/type/decorator.rb +0 -14
  366. data/lib/active_record/type/float.rb +0 -19
  367. data/lib/active_record/type/integer.rb +0 -59
  368. data/lib/active_record/type/mutable.rb +0 -16
  369. data/lib/active_record/type/numeric.rb +0 -36
  370. data/lib/active_record/type/string.rb +0 -40
  371. data/lib/active_record/type/time_value.rb +0 -38
  372. data/lib/active_record/type/value.rb +0 -110
  373. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
  374. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,5 +1,6 @@
1
- module ActiveRecord
1
+ # frozen_string_literal: true
2
2
 
3
+ module ActiveRecord
3
4
  # Statement cache is used to cache a single statement in order to avoid creating the AST again.
4
5
  # Initializing the cache is done by passing the statement in the create block:
5
6
  #
@@ -7,12 +8,14 @@ module ActiveRecord
7
8
  # Book.where(name: "my book").where("author_id > 3")
8
9
  # end
9
10
  #
10
- # The cached statement is executed by using the +execute+ method:
11
+ # The cached statement is executed by using the
12
+ # {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
11
13
  #
12
- # cache.execute([], Book, Book.connection)
14
+ # cache.execute([], Book.connection)
13
15
  #
14
- # The relation returned by the block is cached, and for each +execute+ call the cached relation gets duped.
15
- # Database is queried when +to_a+ is called on the relation.
16
+ # The relation returned by the block is cached, and for each
17
+ # {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
18
+ # call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
16
19
  #
17
20
  # If you want to cache the statement without the values you can use the +bind+ method of the
18
21
  # block parameter.
@@ -23,7 +26,7 @@ module ActiveRecord
23
26
  #
24
27
  # And pass the bind values as the first argument of +execute+ call.
25
28
  #
26
- # cache.execute(["my book"], Book, Book.connection)
29
+ # cache.execute(["my book"], Book.connection)
27
30
  class StatementCache # :nodoc:
28
31
  class Substitute; end # :nodoc:
29
32
 
@@ -38,28 +41,69 @@ module ActiveRecord
38
41
  end
39
42
 
40
43
  class PartialQuery < Query # :nodoc:
41
- def initialize values
44
+ def initialize(values)
42
45
  @values = values
43
- @indexes = values.each_with_index.find_all { |thing,i|
44
- Arel::Nodes::BindParam === thing
46
+ @indexes = values.each_with_index.find_all { |thing, i|
47
+ Substitute === thing
45
48
  }.map(&:last)
46
49
  end
47
50
 
48
51
  def sql_for(binds, connection)
49
52
  val = @values.dup
50
- binds = binds.dup
51
- @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
53
+ @indexes.each do |i|
54
+ value = binds.shift
55
+ if ActiveModel::Attribute === value
56
+ value = value.value_for_database
57
+ end
58
+ val[i] = connection.quote(value)
59
+ end
52
60
  val.join
53
61
  end
54
62
  end
55
63
 
56
- def self.query(visitor, ast)
57
- Query.new visitor.accept(ast, Arel::Collectors::SQLString.new).value
64
+ class PartialQueryCollector
65
+ attr_accessor :preparable
66
+
67
+ def initialize
68
+ @parts = []
69
+ @binds = []
70
+ end
71
+
72
+ def <<(str)
73
+ @parts << str
74
+ self
75
+ end
76
+
77
+ def add_bind(obj)
78
+ @binds << obj
79
+ @parts << Substitute.new
80
+ self
81
+ end
82
+
83
+ def add_binds(binds, proc_for_binds = nil)
84
+ @binds.concat proc_for_binds ? binds.map(&proc_for_binds) : binds
85
+ binds.size.times do |i|
86
+ @parts << ", " unless i == 0
87
+ @parts << Substitute.new
88
+ end
89
+ self
90
+ end
91
+
92
+ def value
93
+ [@parts, @binds]
94
+ end
95
+ end
96
+
97
+ def self.query(sql)
98
+ Query.new(sql)
99
+ end
100
+
101
+ def self.partial_query(values)
102
+ PartialQuery.new(values)
58
103
  end
59
104
 
60
- def self.partial_query(visitor, ast, collector)
61
- collected = visitor.accept(ast, collector).value
62
- PartialQuery.new collected
105
+ def self.partial_query_collector
106
+ PartialQueryCollector.new
63
107
  end
64
108
 
65
109
  class Params # :nodoc:
@@ -67,45 +111,54 @@ module ActiveRecord
67
111
  end
68
112
 
69
113
  class BindMap # :nodoc:
70
- def initialize(bind_values)
71
- @indexes = []
72
- @bind_values = bind_values
114
+ def initialize(bound_attributes)
115
+ @indexes = []
116
+ @bound_attributes = bound_attributes
73
117
 
74
- bind_values.each_with_index do |(_, value), i|
75
- if Substitute === value
118
+ bound_attributes.each_with_index do |attr, i|
119
+ if ActiveModel::Attribute === attr && Substitute === attr.value
76
120
  @indexes << i
77
121
  end
78
122
  end
79
123
  end
80
124
 
81
125
  def bind(values)
82
- bvs = @bind_values.map { |pair| pair.dup }
83
- @indexes.each_with_index { |offset,i| bvs[offset][1] = values[i] }
84
- bvs
126
+ bas = @bound_attributes.dup
127
+ @indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
128
+ bas
85
129
  end
86
130
  end
87
131
 
88
- attr_reader :bind_map, :query_builder
89
-
90
- def self.create(connection, block = Proc.new)
91
- relation = block.call Params.new
92
- bind_map = BindMap.new relation.bind_values
93
- query_builder = connection.cacheable_query relation.arel
94
- new query_builder, bind_map
132
+ def self.create(connection, callable = nil, &block)
133
+ relation = (callable || block).call Params.new
134
+ query_builder, binds = connection.cacheable_query(self, relation.arel)
135
+ bind_map = BindMap.new(binds)
136
+ new(query_builder, bind_map, relation.klass)
95
137
  end
96
138
 
97
- def initialize(query_builder, bind_map)
139
+ def initialize(query_builder, bind_map, klass)
98
140
  @query_builder = query_builder
99
- @bind_map = bind_map
141
+ @bind_map = bind_map
142
+ @klass = klass
100
143
  end
101
144
 
102
- def execute(params, klass, connection)
145
+ def execute(params, connection, &block)
103
146
  bind_values = bind_map.bind params
104
147
 
105
148
  sql = query_builder.sql_for bind_values, connection
106
149
 
107
- klass.find_by_sql sql, bind_values
150
+ klass.find_by_sql(sql, bind_values, preparable: true, &block)
151
+ rescue ::RangeError
152
+ []
153
+ end
154
+
155
+ def self.unsupported_value?(value)
156
+ case value
157
+ when NilClass, Array, Range, Hash, Relation, Base then true
158
+ end
108
159
  end
109
- alias :call :execute
160
+
161
+ private
162
+ attr_reader :query_builder, :bind_map, :klass
110
163
  end
111
164
  end
@@ -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 (e.g. 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:
@@ -166,40 +251,40 @@ module ActiveRecord
166
251
  attribute = object.send(store_attribute)
167
252
  unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess)
168
253
  attribute = IndifferentCoder.as_indifferent_hash(attribute)
169
- object.send :"#{store_attribute}=", attribute
254
+ object.public_send :"#{store_attribute}=", attribute
170
255
  end
171
256
  attribute
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,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class TableMetadata # :nodoc:
5
+ delegate :join_primary_key, :join_foreign_key, :join_foreign_type, to: :reflection
6
+
7
+ def initialize(klass, arel_table, reflection = nil)
8
+ @klass = klass
9
+ @arel_table = arel_table
10
+ @reflection = reflection
11
+ end
12
+
13
+ def primary_key
14
+ klass&.primary_key
15
+ end
16
+
17
+ def type(column_name)
18
+ arel_table.type_for_attribute(column_name)
19
+ end
20
+
21
+ def has_column?(column_name)
22
+ klass&.columns_hash.key?(column_name)
23
+ end
24
+
25
+ def associated_with?(table_name)
26
+ klass&._reflect_on_association(table_name) || klass&._reflect_on_association(table_name.singularize)
27
+ end
28
+
29
+ def associated_table(table_name)
30
+ reflection = klass._reflect_on_association(table_name) || klass._reflect_on_association(table_name.singularize)
31
+
32
+ if !reflection && table_name == arel_table.name
33
+ return self
34
+ end
35
+
36
+ if reflection
37
+ association_klass = reflection.klass unless reflection.polymorphic?
38
+ elsif block_given?
39
+ association_klass = yield table_name
40
+ end
41
+
42
+ if association_klass
43
+ arel_table = association_klass.arel_table
44
+ arel_table = arel_table.alias(table_name) if arel_table.name != table_name
45
+ TableMetadata.new(association_klass, arel_table, reflection)
46
+ else
47
+ type_caster = TypeCaster::Connection.new(klass, table_name)
48
+ arel_table = Arel::Table.new(table_name, type_caster: type_caster)
49
+ TableMetadata.new(nil, arel_table, reflection)
50
+ end
51
+ end
52
+
53
+ def polymorphic_association?
54
+ reflection&.polymorphic?
55
+ end
56
+
57
+ def through_association?
58
+ reflection&.through_reflection?
59
+ end
60
+
61
+ def reflect_on_aggregation(aggregation_name)
62
+ klass&.reflect_on_aggregation(aggregation_name)
63
+ end
64
+ alias :aggregated_with? :reflect_on_aggregation
65
+
66
+ def predicate_builder
67
+ if klass
68
+ predicate_builder = klass.predicate_builder.dup
69
+ predicate_builder.instance_variable_set(:@table, self)
70
+ predicate_builder
71
+ else
72
+ PredicateBuilder.new(self)
73
+ end
74
+ end
75
+
76
+ attr_reader :arel_table
77
+
78
+ private
79
+ attr_reader :klass, :reflection
80
+ end
81
+ end