activerecord 6.0.0

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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1013 -0
  3. data/MIT-LICENSE +22 -0
  4. data/README.rdoc +219 -0
  5. data/examples/performance.rb +185 -0
  6. data/examples/simple.rb +15 -0
  7. data/lib/active_record.rb +195 -0
  8. data/lib/active_record/aggregations.rb +285 -0
  9. data/lib/active_record/association_relation.rb +40 -0
  10. data/lib/active_record/associations.rb +1865 -0
  11. data/lib/active_record/associations/alias_tracker.rb +81 -0
  12. data/lib/active_record/associations/association.rb +332 -0
  13. data/lib/active_record/associations/association_scope.rb +166 -0
  14. data/lib/active_record/associations/belongs_to_association.rb +124 -0
  15. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +36 -0
  16. data/lib/active_record/associations/builder/association.rb +136 -0
  17. data/lib/active_record/associations/builder/belongs_to.rb +130 -0
  18. data/lib/active_record/associations/builder/collection_association.rb +72 -0
  19. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +114 -0
  20. data/lib/active_record/associations/builder/has_many.rb +19 -0
  21. data/lib/active_record/associations/builder/has_one.rb +64 -0
  22. data/lib/active_record/associations/builder/singular_association.rb +44 -0
  23. data/lib/active_record/associations/collection_association.rb +498 -0
  24. data/lib/active_record/associations/collection_proxy.rb +1128 -0
  25. data/lib/active_record/associations/foreign_association.rb +20 -0
  26. data/lib/active_record/associations/has_many_association.rb +136 -0
  27. data/lib/active_record/associations/has_many_through_association.rb +220 -0
  28. data/lib/active_record/associations/has_one_association.rb +118 -0
  29. data/lib/active_record/associations/has_one_through_association.rb +45 -0
  30. data/lib/active_record/associations/join_dependency.rb +258 -0
  31. data/lib/active_record/associations/join_dependency/join_association.rb +80 -0
  32. data/lib/active_record/associations/join_dependency/join_base.rb +23 -0
  33. data/lib/active_record/associations/join_dependency/join_part.rb +71 -0
  34. data/lib/active_record/associations/preloader.rb +201 -0
  35. data/lib/active_record/associations/preloader/association.rb +133 -0
  36. data/lib/active_record/associations/preloader/through_association.rb +116 -0
  37. data/lib/active_record/associations/singular_association.rb +59 -0
  38. data/lib/active_record/associations/through_association.rb +121 -0
  39. data/lib/active_record/attribute_assignment.rb +85 -0
  40. data/lib/active_record/attribute_decorators.rb +90 -0
  41. data/lib/active_record/attribute_methods.rb +420 -0
  42. data/lib/active_record/attribute_methods/before_type_cast.rb +81 -0
  43. data/lib/active_record/attribute_methods/dirty.rb +221 -0
  44. data/lib/active_record/attribute_methods/primary_key.rb +136 -0
  45. data/lib/active_record/attribute_methods/query.rb +41 -0
  46. data/lib/active_record/attribute_methods/read.rb +47 -0
  47. data/lib/active_record/attribute_methods/serialization.rb +90 -0
  48. data/lib/active_record/attribute_methods/time_zone_conversion.rb +91 -0
  49. data/lib/active_record/attribute_methods/write.rb +61 -0
  50. data/lib/active_record/attributes.rb +279 -0
  51. data/lib/active_record/autosave_association.rb +508 -0
  52. data/lib/active_record/base.rb +328 -0
  53. data/lib/active_record/callbacks.rb +339 -0
  54. data/lib/active_record/coders/json.rb +15 -0
  55. data/lib/active_record/coders/yaml_column.rb +50 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1165 -0
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +85 -0
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +512 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +154 -0
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +251 -0
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +713 -0
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1475 -0
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +761 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +821 -0
  69. data/lib/active_record/connection_adapters/column.rb +95 -0
  70. data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
  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 +200 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -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 +264 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +146 -0
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +949 -0
  117. data/lib/active_record/connection_adapters/schema_cache.rb +141 -0
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -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 +103 -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 +557 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +267 -0
  129. data/lib/active_record/core.rb +599 -0
  130. data/lib/active_record/counter_cache.rb +193 -0
  131. data/lib/active_record/database_configurations.rb +233 -0
  132. data/lib/active_record/database_configurations/database_config.rb +37 -0
  133. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  134. data/lib/active_record/database_configurations/url_config.rb +79 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +122 -0
  137. data/lib/active_record/enum.rb +274 -0
  138. data/lib/active_record/errors.rb +388 -0
  139. data/lib/active_record/explain.rb +50 -0
  140. data/lib/active_record/explain_registry.rb +32 -0
  141. data/lib/active_record/explain_subscriber.rb +34 -0
  142. data/lib/active_record/fixture_set/file.rb +82 -0
  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 +153 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +47 -0
  147. data/lib/active_record/fixtures.rb +738 -0
  148. data/lib/active_record/gem_version.rb +17 -0
  149. data/lib/active_record/inheritance.rb +293 -0
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +207 -0
  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 +48 -0
  155. data/lib/active_record/locking/optimistic.rb +197 -0
  156. data/lib/active_record/locking/pessimistic.rb +89 -0
  157. data/lib/active_record/log_subscriber.rb +118 -0
  158. data/lib/active_record/middleware/database_selector.rb +75 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
  160. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  161. data/lib/active_record/migration.rb +1397 -0
  162. data/lib/active_record/migration/command_recorder.rb +284 -0
  163. data/lib/active_record/migration/compatibility.rb +244 -0
  164. data/lib/active_record/migration/join_table.rb +17 -0
  165. data/lib/active_record/model_schema.rb +542 -0
  166. data/lib/active_record/nested_attributes.rb +600 -0
  167. data/lib/active_record/no_touching.rb +65 -0
  168. data/lib/active_record/null_relation.rb +68 -0
  169. data/lib/active_record/persistence.rb +967 -0
  170. data/lib/active_record/query_cache.rb +52 -0
  171. data/lib/active_record/querying.rb +82 -0
  172. data/lib/active_record/railtie.rb +263 -0
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +7 -0
  175. data/lib/active_record/railties/controller_runtime.rb +51 -0
  176. data/lib/active_record/railties/databases.rake +527 -0
  177. data/lib/active_record/readonly_attributes.rb +24 -0
  178. data/lib/active_record/reflection.rb +1042 -0
  179. data/lib/active_record/relation.rb +859 -0
  180. data/lib/active_record/relation/batches.rb +290 -0
  181. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  182. data/lib/active_record/relation/calculations.rb +424 -0
  183. data/lib/active_record/relation/delegation.rb +130 -0
  184. data/lib/active_record/relation/finder_methods.rb +552 -0
  185. data/lib/active_record/relation/from_clause.rb +26 -0
  186. data/lib/active_record/relation/merger.rb +184 -0
  187. data/lib/active_record/relation/predicate_builder.rb +150 -0
  188. data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
  189. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  190. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  191. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  192. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  193. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  194. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  195. data/lib/active_record/relation/query_attribute.rb +50 -0
  196. data/lib/active_record/relation/query_methods.rb +1359 -0
  197. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  198. data/lib/active_record/relation/spawn_methods.rb +77 -0
  199. data/lib/active_record/relation/where_clause.rb +190 -0
  200. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  201. data/lib/active_record/result.rb +168 -0
  202. data/lib/active_record/runtime_registry.rb +24 -0
  203. data/lib/active_record/sanitization.rb +214 -0
  204. data/lib/active_record/schema.rb +61 -0
  205. data/lib/active_record/schema_dumper.rb +270 -0
  206. data/lib/active_record/schema_migration.rb +60 -0
  207. data/lib/active_record/scoping.rb +106 -0
  208. data/lib/active_record/scoping/default.rb +151 -0
  209. data/lib/active_record/scoping/named.rb +217 -0
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +22 -0
  212. data/lib/active_record/statement_cache.rb +148 -0
  213. data/lib/active_record/store.rb +290 -0
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +75 -0
  216. data/lib/active_record/tasks/database_tasks.rb +506 -0
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +224 -0
  222. data/lib/active_record/timestamp.rb +167 -0
  223. data/lib/active_record/touch_later.rb +66 -0
  224. data/lib/active_record/transactions.rb +493 -0
  225. data/lib/active_record/translation.rb +24 -0
  226. data/lib/active_record/type.rb +78 -0
  227. data/lib/active_record/type/adapter_specific_registry.rb +129 -0
  228. data/lib/active_record/type/date.rb +9 -0
  229. data/lib/active_record/type/date_time.rb +9 -0
  230. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  231. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  232. data/lib/active_record/type/internal/timezone.rb +17 -0
  233. data/lib/active_record/type/json.rb +30 -0
  234. data/lib/active_record/type/serialized.rb +71 -0
  235. data/lib/active_record/type/text.rb +11 -0
  236. data/lib/active_record/type/time.rb +21 -0
  237. data/lib/active_record/type/type_map.rb +62 -0
  238. data/lib/active_record/type/unsigned_integer.rb +17 -0
  239. data/lib/active_record/type_caster.rb +9 -0
  240. data/lib/active_record/type_caster/connection.rb +34 -0
  241. data/lib/active_record/type_caster/map.rb +20 -0
  242. data/lib/active_record/validations.rb +94 -0
  243. data/lib/active_record/validations/absence.rb +25 -0
  244. data/lib/active_record/validations/associated.rb +60 -0
  245. data/lib/active_record/validations/length.rb +26 -0
  246. data/lib/active_record/validations/presence.rb +68 -0
  247. data/lib/active_record/validations/uniqueness.rb +226 -0
  248. data/lib/active_record/version.rb +10 -0
  249. data/lib/arel.rb +51 -0
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes.rb +22 -0
  252. data/lib/arel/attributes/attribute.rb +37 -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.rb +68 -0
  266. data/lib/arel/nodes/and.rb +32 -0
  267. data/lib/arel/nodes/ascending.rb +23 -0
  268. data/lib/arel/nodes/binary.rb +52 -0
  269. data/lib/arel/nodes/bind_param.rb +36 -0
  270. data/lib/arel/nodes/case.rb +55 -0
  271. data/lib/arel/nodes/casted.rb +50 -0
  272. data/lib/arel/nodes/comment.rb +29 -0
  273. data/lib/arel/nodes/count.rb +12 -0
  274. data/lib/arel/nodes/delete_statement.rb +45 -0
  275. data/lib/arel/nodes/descending.rb +23 -0
  276. data/lib/arel/nodes/equality.rb +18 -0
  277. data/lib/arel/nodes/extract.rb +24 -0
  278. data/lib/arel/nodes/false.rb +16 -0
  279. data/lib/arel/nodes/full_outer_join.rb +8 -0
  280. data/lib/arel/nodes/function.rb +44 -0
  281. data/lib/arel/nodes/grouping.rb +8 -0
  282. data/lib/arel/nodes/in.rb +8 -0
  283. data/lib/arel/nodes/infix_operation.rb +80 -0
  284. data/lib/arel/nodes/inner_join.rb +8 -0
  285. data/lib/arel/nodes/insert_statement.rb +37 -0
  286. data/lib/arel/nodes/join_source.rb +20 -0
  287. data/lib/arel/nodes/matches.rb +18 -0
  288. data/lib/arel/nodes/named_function.rb +23 -0
  289. data/lib/arel/nodes/node.rb +50 -0
  290. data/lib/arel/nodes/node_expression.rb +13 -0
  291. data/lib/arel/nodes/outer_join.rb +8 -0
  292. data/lib/arel/nodes/over.rb +15 -0
  293. data/lib/arel/nodes/regexp.rb +16 -0
  294. data/lib/arel/nodes/right_outer_join.rb +8 -0
  295. data/lib/arel/nodes/select_core.rb +67 -0
  296. data/lib/arel/nodes/select_statement.rb +41 -0
  297. data/lib/arel/nodes/sql_literal.rb +16 -0
  298. data/lib/arel/nodes/string_join.rb +11 -0
  299. data/lib/arel/nodes/table_alias.rb +27 -0
  300. data/lib/arel/nodes/terminal.rb +16 -0
  301. data/lib/arel/nodes/true.rb +16 -0
  302. data/lib/arel/nodes/unary.rb +45 -0
  303. data/lib/arel/nodes/unary_operation.rb +20 -0
  304. data/lib/arel/nodes/unqualified_column.rb +22 -0
  305. data/lib/arel/nodes/update_statement.rb +41 -0
  306. data/lib/arel/nodes/values_list.rb +9 -0
  307. data/lib/arel/nodes/window.rb +126 -0
  308. data/lib/arel/nodes/with.rb +11 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +257 -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.rb +20 -0
  316. data/lib/arel/visitors/depth_first.rb +204 -0
  317. data/lib/arel/visitors/dot.rb +297 -0
  318. data/lib/arel/visitors/ibm_db.rb +34 -0
  319. data/lib/arel/visitors/informix.rb +62 -0
  320. data/lib/arel/visitors/mssql.rb +157 -0
  321. data/lib/arel/visitors/mysql.rb +83 -0
  322. data/lib/arel/visitors/oracle.rb +159 -0
  323. data/lib/arel/visitors/oracle12.rb +66 -0
  324. data/lib/arel/visitors/postgresql.rb +110 -0
  325. data/lib/arel/visitors/sqlite.rb +39 -0
  326. data/lib/arel/visitors/to_sql.rb +889 -0
  327. data/lib/arel/visitors/visitor.rb +46 -0
  328. data/lib/arel/visitors/where_sql.rb +23 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/rails/generators/active_record.rb +19 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -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.rb +48 -0
  334. data/lib/rails/generators/active_record/migration/migration_generator.rb +75 -0
  335. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  336. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
  337. data/lib/rails/generators/active_record/model/model_generator.rb +49 -0
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record/model/templates/module.rb.tt +7 -0
  340. metadata +415 -0
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Associations
5
+ # = Active Record Belongs To Association
6
+ class BelongsToAssociation < SingularAssociation #:nodoc:
7
+ def handle_dependency
8
+ return unless load_target
9
+
10
+ case options[:dependent]
11
+ when :destroy
12
+ target.destroy
13
+ raise ActiveRecord::Rollback unless target.destroyed?
14
+ else
15
+ target.send(options[:dependent])
16
+ end
17
+ end
18
+
19
+ def inversed_from(record)
20
+ replace_keys(record)
21
+ super
22
+ end
23
+
24
+ def default(&block)
25
+ writer(owner.instance_exec(&block)) if reader.nil?
26
+ end
27
+
28
+ def reset
29
+ super
30
+ @updated = false
31
+ end
32
+
33
+ def updated?
34
+ @updated
35
+ end
36
+
37
+ def decrement_counters
38
+ update_counters(-1)
39
+ end
40
+
41
+ def increment_counters
42
+ update_counters(1)
43
+ end
44
+
45
+ def decrement_counters_before_last_save
46
+ if reflection.polymorphic?
47
+ model_was = owner.attribute_before_last_save(reflection.foreign_type).try(:constantize)
48
+ else
49
+ model_was = klass
50
+ end
51
+
52
+ foreign_key_was = owner.attribute_before_last_save(reflection.foreign_key)
53
+
54
+ if foreign_key_was && model_was < ActiveRecord::Base
55
+ update_counters_via_scope(model_was, foreign_key_was, -1)
56
+ end
57
+ end
58
+
59
+ def target_changed?
60
+ owner.saved_change_to_attribute?(reflection.foreign_key)
61
+ end
62
+
63
+ private
64
+ def replace(record)
65
+ if record
66
+ raise_on_type_mismatch!(record)
67
+ set_inverse_instance(record)
68
+ @updated = true
69
+ end
70
+
71
+ replace_keys(record)
72
+
73
+ self.target = record
74
+ end
75
+
76
+ def update_counters(by)
77
+ if require_counter_update? && foreign_key_present?
78
+ if target && !stale_target?
79
+ target.increment!(reflection.counter_cache_column, by, touch: reflection.options[:touch])
80
+ else
81
+ update_counters_via_scope(klass, owner._read_attribute(reflection.foreign_key), by)
82
+ end
83
+ end
84
+ end
85
+
86
+ def update_counters_via_scope(klass, foreign_key, by)
87
+ scope = klass.unscoped.where!(primary_key(klass) => foreign_key)
88
+ scope.update_counters(reflection.counter_cache_column => by, touch: reflection.options[:touch])
89
+ end
90
+
91
+ def find_target?
92
+ !loaded? && foreign_key_present? && klass
93
+ end
94
+
95
+ def require_counter_update?
96
+ reflection.counter_cache_column && owner.persisted?
97
+ end
98
+
99
+ def replace_keys(record)
100
+ owner[reflection.foreign_key] = record ? record._read_attribute(primary_key(record.class)) : nil
101
+ end
102
+
103
+ def primary_key(klass)
104
+ reflection.association_primary_key(klass)
105
+ end
106
+
107
+ def foreign_key_present?
108
+ owner._read_attribute(reflection.foreign_key)
109
+ end
110
+
111
+ # NOTE - for now, we're only supporting inverse setting from belongs_to back onto
112
+ # has_one associations.
113
+ def invertible_for?(record)
114
+ inverse = inverse_reflection_for(record)
115
+ inverse && inverse.has_one?
116
+ end
117
+
118
+ def stale_state
119
+ result = owner._read_attribute(reflection.foreign_key) { |n| owner.send(:missing_attribute, n, caller) }
120
+ result && result.to_s
121
+ end
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ module Associations
5
+ # = Active Record Belongs To Polymorphic Association
6
+ class BelongsToPolymorphicAssociation < BelongsToAssociation #:nodoc:
7
+ def klass
8
+ type = owner[reflection.foreign_type]
9
+ type.presence && type.constantize
10
+ end
11
+
12
+ def target_changed?
13
+ super || owner.saved_change_to_attribute?(reflection.foreign_type)
14
+ end
15
+
16
+ private
17
+ def replace_keys(record)
18
+ super
19
+ owner[reflection.foreign_type] = record ? record.class.polymorphic_name : nil
20
+ end
21
+
22
+ def inverse_reflection_for(record)
23
+ reflection.polymorphic_inverse_of(record.class)
24
+ end
25
+
26
+ def raise_on_type_mismatch!(record)
27
+ # A polymorphic association cannot have a type mismatch, by definition
28
+ end
29
+
30
+ def stale_state
31
+ foreign_key = super
32
+ foreign_key && [foreign_key.to_s, owner[reflection.foreign_type].to_s]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,136 @@
1
+ # frozen_string_literal: true
2
+
3
+ # This is the parent Association class which defines the variables
4
+ # used by all associations.
5
+ #
6
+ # The hierarchy is defined as follows:
7
+ # Association
8
+ # - SingularAssociation
9
+ # - BelongsToAssociation
10
+ # - HasOneAssociation
11
+ # - CollectionAssociation
12
+ # - HasManyAssociation
13
+
14
+ module ActiveRecord::Associations::Builder # :nodoc:
15
+ class Association #:nodoc:
16
+ class << self
17
+ attr_accessor :extensions
18
+ end
19
+ self.extensions = []
20
+
21
+ VALID_OPTIONS = [:class_name, :anonymous_class, :foreign_key, :validate] # :nodoc:
22
+
23
+ def self.build(model, name, scope, options, &block)
24
+ if model.dangerous_attribute_method?(name)
25
+ raise ArgumentError, "You tried to define an association named #{name} on the model #{model.name}, but " \
26
+ "this will conflict with a method #{name} already defined by Active Record. " \
27
+ "Please choose a different association name."
28
+ end
29
+
30
+ reflection = create_reflection(model, name, scope, options, &block)
31
+ define_accessors model, reflection
32
+ define_callbacks model, reflection
33
+ define_validations model, reflection
34
+ reflection
35
+ end
36
+
37
+ def self.create_reflection(model, name, scope, options, &block)
38
+ raise ArgumentError, "association names must be a Symbol" unless name.kind_of?(Symbol)
39
+
40
+ validate_options(options)
41
+
42
+ extension = define_extensions(model, name, &block)
43
+ options[:extend] = [*options[:extend], extension] if extension
44
+
45
+ scope = build_scope(scope)
46
+
47
+ ActiveRecord::Reflection.create(macro, name, scope, options, model)
48
+ end
49
+
50
+ def self.build_scope(scope)
51
+ if scope && scope.arity == 0
52
+ proc { instance_exec(&scope) }
53
+ else
54
+ scope
55
+ end
56
+ end
57
+
58
+ def self.macro
59
+ raise NotImplementedError
60
+ end
61
+
62
+ def self.valid_options(options)
63
+ VALID_OPTIONS + Association.extensions.flat_map(&:valid_options)
64
+ end
65
+
66
+ def self.validate_options(options)
67
+ options.assert_valid_keys(valid_options(options))
68
+ end
69
+
70
+ def self.define_extensions(model, name)
71
+ end
72
+
73
+ def self.define_callbacks(model, reflection)
74
+ if dependent = reflection.options[:dependent]
75
+ check_dependent_options(dependent)
76
+ add_destroy_callbacks(model, reflection)
77
+ end
78
+
79
+ Association.extensions.each do |extension|
80
+ extension.build model, reflection
81
+ end
82
+ end
83
+
84
+ # Defines the setter and getter methods for the association
85
+ # class Post < ActiveRecord::Base
86
+ # has_many :comments
87
+ # end
88
+ #
89
+ # Post.first.comments and Post.first.comments= methods are defined by this method...
90
+ def self.define_accessors(model, reflection)
91
+ mixin = model.generated_association_methods
92
+ name = reflection.name
93
+ define_readers(mixin, name)
94
+ define_writers(mixin, name)
95
+ end
96
+
97
+ def self.define_readers(mixin, name)
98
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
99
+ def #{name}
100
+ association(:#{name}).reader
101
+ end
102
+ CODE
103
+ end
104
+
105
+ def self.define_writers(mixin, name)
106
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
107
+ def #{name}=(value)
108
+ association(:#{name}).writer(value)
109
+ end
110
+ CODE
111
+ end
112
+
113
+ def self.define_validations(model, reflection)
114
+ # noop
115
+ end
116
+
117
+ def self.valid_dependent_options
118
+ raise NotImplementedError
119
+ end
120
+
121
+ def self.check_dependent_options(dependent)
122
+ unless valid_dependent_options.include? dependent
123
+ raise ArgumentError, "The :dependent option must be one of #{valid_dependent_options}, but is :#{dependent}"
124
+ end
125
+ end
126
+
127
+ def self.add_destroy_callbacks(model, reflection)
128
+ name = reflection.name
129
+ model.before_destroy lambda { |o| o.association(name).handle_dependency }
130
+ end
131
+
132
+ private_class_method :build_scope, :macro, :valid_options, :validate_options, :define_extensions,
133
+ :define_callbacks, :define_accessors, :define_readers, :define_writers, :define_validations,
134
+ :valid_dependent_options, :check_dependent_options, :add_destroy_callbacks
135
+ end
136
+ end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord::Associations::Builder # :nodoc:
4
+ class BelongsTo < SingularAssociation #:nodoc:
5
+ def self.macro
6
+ :belongs_to
7
+ end
8
+
9
+ def self.valid_options(options)
10
+ super + [:polymorphic, :touch, :counter_cache, :optional, :default]
11
+ end
12
+
13
+ def self.valid_dependent_options
14
+ [:destroy, :delete]
15
+ end
16
+
17
+ def self.define_callbacks(model, reflection)
18
+ super
19
+ add_counter_cache_callbacks(model, reflection) if reflection.options[:counter_cache]
20
+ add_touch_callbacks(model, reflection) if reflection.options[:touch]
21
+ add_default_callbacks(model, reflection) if reflection.options[:default]
22
+ end
23
+
24
+ def self.add_counter_cache_callbacks(model, reflection)
25
+ cache_column = reflection.counter_cache_column
26
+
27
+ model.after_update lambda { |record|
28
+ association = association(reflection.name)
29
+
30
+ if association.target_changed?
31
+ association.increment_counters
32
+ association.decrement_counters_before_last_save
33
+ end
34
+ }
35
+
36
+ klass = reflection.class_name.safe_constantize
37
+ klass.attr_readonly cache_column if klass && klass.respond_to?(:attr_readonly)
38
+ end
39
+
40
+ def self.touch_record(o, changes, foreign_key, name, touch, touch_method) # :nodoc:
41
+ old_foreign_id = changes[foreign_key] && changes[foreign_key].first
42
+
43
+ if old_foreign_id
44
+ association = o.association(name)
45
+ reflection = association.reflection
46
+ if reflection.polymorphic?
47
+ foreign_type = reflection.foreign_type
48
+ klass = changes[foreign_type] && changes[foreign_type].first || o.public_send(foreign_type)
49
+ klass = klass.constantize
50
+ else
51
+ klass = association.klass
52
+ end
53
+ primary_key = reflection.association_primary_key(klass)
54
+ old_record = klass.find_by(primary_key => old_foreign_id)
55
+
56
+ if old_record
57
+ if touch != true
58
+ old_record.send(touch_method, touch)
59
+ else
60
+ old_record.send(touch_method)
61
+ end
62
+ end
63
+ end
64
+
65
+ record = o.send name
66
+ if record && record.persisted?
67
+ if touch != true
68
+ record.send(touch_method, touch)
69
+ else
70
+ record.send(touch_method)
71
+ end
72
+ end
73
+ end
74
+
75
+ def self.add_touch_callbacks(model, reflection)
76
+ foreign_key = reflection.foreign_key
77
+ name = reflection.name
78
+ touch = reflection.options[:touch]
79
+
80
+ callback = lambda { |changes_method| lambda { |record|
81
+ BelongsTo.touch_record(record, record.send(changes_method), foreign_key, name, touch, belongs_to_touch_method)
82
+ }}
83
+
84
+ if reflection.counter_cache_column
85
+ touch_callback = callback.(:saved_changes)
86
+ update_callback = lambda { |record|
87
+ instance_exec(record, &touch_callback) unless association(reflection.name).target_changed?
88
+ }
89
+ model.after_update update_callback, if: :saved_changes?
90
+ else
91
+ model.after_create callback.(:saved_changes), if: :saved_changes?
92
+ model.after_update callback.(:saved_changes), if: :saved_changes?
93
+ model.after_destroy callback.(:changes_to_save)
94
+ end
95
+
96
+ model.after_touch callback.(:changes_to_save)
97
+ end
98
+
99
+ def self.add_default_callbacks(model, reflection)
100
+ model.before_validation lambda { |o|
101
+ o.association(reflection.name).default(&reflection.options[:default])
102
+ }
103
+ end
104
+
105
+ def self.add_destroy_callbacks(model, reflection)
106
+ model.after_destroy lambda { |o| o.association(reflection.name).handle_dependency }
107
+ end
108
+
109
+ def self.define_validations(model, reflection)
110
+ if reflection.options.key?(:required)
111
+ reflection.options[:optional] = !reflection.options.delete(:required)
112
+ end
113
+
114
+ if reflection.options[:optional].nil?
115
+ required = model.belongs_to_required_by_default
116
+ else
117
+ required = !reflection.options[:optional]
118
+ end
119
+
120
+ super
121
+
122
+ if required
123
+ model.validates_presence_of reflection.name, message: :required
124
+ end
125
+ end
126
+
127
+ private_class_method :macro, :valid_options, :valid_dependent_options, :define_callbacks, :define_validations,
128
+ :add_counter_cache_callbacks, :add_touch_callbacks, :add_default_callbacks, :add_destroy_callbacks
129
+ end
130
+ end
@@ -0,0 +1,72 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_record/associations"
4
+
5
+ module ActiveRecord::Associations::Builder # :nodoc:
6
+ class CollectionAssociation < Association #:nodoc:
7
+ CALLBACKS = [:before_add, :after_add, :before_remove, :after_remove]
8
+
9
+ def self.valid_options(options)
10
+ super + [:table_name, :before_add,
11
+ :after_add, :before_remove, :after_remove, :extend]
12
+ end
13
+
14
+ def self.define_callbacks(model, reflection)
15
+ super
16
+ name = reflection.name
17
+ options = reflection.options
18
+ CALLBACKS.each { |callback_name|
19
+ define_callback(model, callback_name, name, options)
20
+ }
21
+ end
22
+
23
+ def self.define_extensions(model, name, &block)
24
+ if block_given?
25
+ extension_module_name = "#{name.to_s.camelize}AssociationExtension"
26
+ extension = Module.new(&block)
27
+ model.const_set(extension_module_name, extension)
28
+ end
29
+ end
30
+
31
+ def self.define_callback(model, callback_name, name, options)
32
+ full_callback_name = "#{callback_name}_for_#{name}"
33
+
34
+ # TODO : why do i need method_defined? I think its because of the inheritance chain
35
+ model.class_attribute full_callback_name unless model.method_defined?(full_callback_name)
36
+ callbacks = Array(options[callback_name.to_sym]).map do |callback|
37
+ case callback
38
+ when Symbol
39
+ ->(method, owner, record) { owner.send(callback, record) }
40
+ when Proc
41
+ ->(method, owner, record) { callback.call(owner, record) }
42
+ else
43
+ ->(method, owner, record) { callback.send(method, owner, record) }
44
+ end
45
+ end
46
+ model.send "#{full_callback_name}=", callbacks
47
+ end
48
+
49
+ # Defines the setter and getter methods for the collection_singular_ids.
50
+ def self.define_readers(mixin, name)
51
+ super
52
+
53
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
54
+ def #{name.to_s.singularize}_ids
55
+ association(:#{name}).ids_reader
56
+ end
57
+ CODE
58
+ end
59
+
60
+ def self.define_writers(mixin, name)
61
+ super
62
+
63
+ mixin.class_eval <<-CODE, __FILE__, __LINE__ + 1
64
+ def #{name.to_s.singularize}_ids=(ids)
65
+ association(:#{name}).ids_writer(ids)
66
+ end
67
+ CODE
68
+ end
69
+
70
+ private_class_method :valid_options, :define_callback, :define_extensions, :define_readers, :define_writers
71
+ end
72
+ end