activerecord 6.0.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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +1086 -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 +49 -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 +340 -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 +262 -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 +512 -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 +1175 -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 +516 -0
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +155 -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 +772 -0
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +830 -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 +202 -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 +184 -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 +953 -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 +120 -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 +561 -0
  127. data/lib/active_record/connection_adapters/statement_pool.rb +61 -0
  128. data/lib/active_record/connection_handling.rb +274 -0
  129. data/lib/active_record/core.rb +603 -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 +88 -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 +545 -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 +860 -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 +561 -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 +1371 -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 +58 -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 +418 -0
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActiveRecord
4
+ class Migration
5
+ module JoinTable #:nodoc:
6
+ private
7
+
8
+ def find_join_table_name(table_1, table_2, options = {})
9
+ options.delete(:table_name) || join_table_name(table_1, table_2)
10
+ end
11
+
12
+ def join_table_name(table_1, table_2)
13
+ ModelSchema.derive_join_table_name(table_1, table_2).to_sym
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,545 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+
5
+ module ActiveRecord
6
+ module ModelSchema
7
+ extend ActiveSupport::Concern
8
+
9
+ ##
10
+ # :singleton-method: primary_key_prefix_type
11
+ # :call-seq: primary_key_prefix_type
12
+ #
13
+ # The prefix type that will be prepended to every primary key column name.
14
+ # The options are +:table_name+ and +:table_name_with_underscore+. If the first is specified,
15
+ # the Product class will look for "productid" instead of "id" as the primary column. If the
16
+ # latter is specified, the Product class will look for "product_id" instead of "id". Remember
17
+ # that this is a global setting for all Active Records.
18
+
19
+ ##
20
+ # :singleton-method: primary_key_prefix_type=
21
+ # :call-seq: primary_key_prefix_type=(prefix_type)
22
+ #
23
+ # Sets the prefix type that will be prepended to every primary key column name.
24
+ # The options are +:table_name+ and +:table_name_with_underscore+. If the first is specified,
25
+ # the Product class will look for "productid" instead of "id" as the primary column. If the
26
+ # latter is specified, the Product class will look for "product_id" instead of "id". Remember
27
+ # that this is a global setting for all Active Records.
28
+
29
+ ##
30
+ # :singleton-method: table_name_prefix
31
+ # :call-seq: table_name_prefix
32
+ #
33
+ # The prefix string to prepend to every table name.
34
+
35
+ ##
36
+ # :singleton-method: table_name_prefix=
37
+ # :call-seq: table_name_prefix=(prefix)
38
+ #
39
+ # Sets the prefix string to prepend to every table name. So if set to "basecamp_", all table
40
+ # names will be named like "basecamp_projects", "basecamp_people", etc. This is a convenient
41
+ # way of creating a namespace for tables in a shared database. By default, the prefix is the
42
+ # empty string.
43
+ #
44
+ # If you are organising your models within modules you can add a prefix to the models within
45
+ # a namespace by defining a singleton method in the parent module called table_name_prefix which
46
+ # returns your chosen prefix.
47
+
48
+ ##
49
+ # :singleton-method: table_name_suffix
50
+ # :call-seq: table_name_suffix
51
+ #
52
+ # The suffix string to append to every table name.
53
+
54
+ ##
55
+ # :singleton-method: table_name_suffix=
56
+ # :call-seq: table_name_suffix=(suffix)
57
+ #
58
+ # Works like +table_name_prefix=+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
59
+ # "people_basecamp"). By default, the suffix is the empty string.
60
+ #
61
+ # If you are organising your models within modules, you can add a suffix to the models within
62
+ # a namespace by defining a singleton method in the parent module called table_name_suffix which
63
+ # returns your chosen suffix.
64
+
65
+ ##
66
+ # :singleton-method: schema_migrations_table_name
67
+ # :call-seq: schema_migrations_table_name
68
+ #
69
+ # The name of the schema migrations table. By default, the value is <tt>"schema_migrations"</tt>.
70
+
71
+ ##
72
+ # :singleton-method: schema_migrations_table_name=
73
+ # :call-seq: schema_migrations_table_name=(table_name)
74
+ #
75
+ # Sets the name of the schema migrations table.
76
+
77
+ ##
78
+ # :singleton-method: internal_metadata_table_name
79
+ # :call-seq: internal_metadata_table_name
80
+ #
81
+ # The name of the internal metadata table. By default, the value is <tt>"ar_internal_metadata"</tt>.
82
+
83
+ ##
84
+ # :singleton-method: internal_metadata_table_name=
85
+ # :call-seq: internal_metadata_table_name=(table_name)
86
+ #
87
+ # Sets the name of the internal metadata table.
88
+
89
+ ##
90
+ # :singleton-method: pluralize_table_names
91
+ # :call-seq: pluralize_table_names
92
+ #
93
+ # Indicates whether table names should be the pluralized versions of the corresponding class names.
94
+ # If true, the default table name for a Product class will be "products". If false, it would just be "product".
95
+ # See table_name for the full rules on table/class naming. This is true, by default.
96
+
97
+ ##
98
+ # :singleton-method: pluralize_table_names=
99
+ # :call-seq: pluralize_table_names=(value)
100
+ #
101
+ # Set whether table names should be the pluralized versions of the corresponding class names.
102
+ # If true, the default table name for a Product class will be "products". If false, it would just be "product".
103
+ # See table_name for the full rules on table/class naming. This is true, by default.
104
+
105
+ ##
106
+ # :singleton-method: implicit_order_column
107
+ # :call-seq: implicit_order_column
108
+ #
109
+ # The name of the column records are ordered by if no explicit order clause
110
+ # is used during an ordered finder call. If not set the primary key is used.
111
+
112
+ ##
113
+ # :singleton-method: implicit_order_column=
114
+ # :call-seq: implicit_order_column=(column_name)
115
+ #
116
+ # Sets the column to sort records by when no explicit order clause is used
117
+ # during an ordered finder call. Useful when the primary key is not an
118
+ # auto-incrementing integer, for example when it's a UUID. Note that using
119
+ # a non-unique column can result in non-deterministic results.
120
+ included do
121
+ mattr_accessor :primary_key_prefix_type, instance_writer: false
122
+
123
+ class_attribute :table_name_prefix, instance_writer: false, default: ""
124
+ class_attribute :table_name_suffix, instance_writer: false, default: ""
125
+ class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
126
+ class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
127
+ class_attribute :pluralize_table_names, instance_writer: false, default: true
128
+ class_attribute :implicit_order_column, instance_accessor: false
129
+
130
+ self.protected_environments = ["production"]
131
+ self.inheritance_column = "type"
132
+ self.ignored_columns = [].freeze
133
+
134
+ delegate :type_for_attribute, to: :class
135
+
136
+ initialize_load_schema_monitor
137
+ end
138
+
139
+ # Derives the join table name for +first_table+ and +second_table+. The
140
+ # table names appear in alphabetical order. A common prefix is removed
141
+ # (useful for namespaced models like Music::Artist and Music::Record):
142
+ #
143
+ # artists, records => artists_records
144
+ # records, artists => artists_records
145
+ # music_artists, music_records => music_artists_records
146
+ def self.derive_join_table_name(first_table, second_table) # :nodoc:
147
+ [first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
148
+ end
149
+
150
+ module ClassMethods
151
+ # Guesses the table name (in forced lower-case) based on the name of the class in the
152
+ # inheritance hierarchy descending directly from ActiveRecord::Base. So if the hierarchy
153
+ # looks like: Reply < Message < ActiveRecord::Base, then Message is used
154
+ # to guess the table name even when called on Reply. The rules used to do the guess
155
+ # are handled by the Inflector class in Active Support, which knows almost all common
156
+ # English inflections. You can add new inflections in config/initializers/inflections.rb.
157
+ #
158
+ # Nested classes are given table names prefixed by the singular form of
159
+ # the parent's table name. Enclosing modules are not considered.
160
+ #
161
+ # ==== Examples
162
+ #
163
+ # class Invoice < ActiveRecord::Base
164
+ # end
165
+ #
166
+ # file class table_name
167
+ # invoice.rb Invoice invoices
168
+ #
169
+ # class Invoice < ActiveRecord::Base
170
+ # class Lineitem < ActiveRecord::Base
171
+ # end
172
+ # end
173
+ #
174
+ # file class table_name
175
+ # invoice.rb Invoice::Lineitem invoice_lineitems
176
+ #
177
+ # module Invoice
178
+ # class Lineitem < ActiveRecord::Base
179
+ # end
180
+ # end
181
+ #
182
+ # file class table_name
183
+ # invoice/lineitem.rb Invoice::Lineitem lineitems
184
+ #
185
+ # Additionally, the class-level +table_name_prefix+ is prepended and the
186
+ # +table_name_suffix+ is appended. So if you have "myapp_" as a prefix,
187
+ # the table name guess for an Invoice class becomes "myapp_invoices".
188
+ # Invoice::Lineitem becomes "myapp_invoice_lineitems".
189
+ #
190
+ # You can also set your own table name explicitly:
191
+ #
192
+ # class Mouse < ActiveRecord::Base
193
+ # self.table_name = "mice"
194
+ # end
195
+ def table_name
196
+ reset_table_name unless defined?(@table_name)
197
+ @table_name
198
+ end
199
+
200
+ # Sets the table name explicitly. Example:
201
+ #
202
+ # class Project < ActiveRecord::Base
203
+ # self.table_name = "project"
204
+ # end
205
+ def table_name=(value)
206
+ value = value && value.to_s
207
+
208
+ if defined?(@table_name)
209
+ return if value == @table_name
210
+ reset_column_information if connected?
211
+ end
212
+
213
+ @table_name = value
214
+ @quoted_table_name = nil
215
+ @arel_table = nil
216
+ @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
217
+ @predicate_builder = nil
218
+ end
219
+
220
+ # Returns a quoted version of the table name, used to construct SQL statements.
221
+ def quoted_table_name
222
+ @quoted_table_name ||= connection.quote_table_name(table_name)
223
+ end
224
+
225
+ # Computes the table name, (re)sets it internally, and returns it.
226
+ def reset_table_name #:nodoc:
227
+ self.table_name = if abstract_class?
228
+ superclass == Base ? nil : superclass.table_name
229
+ elsif superclass.abstract_class?
230
+ superclass.table_name || compute_table_name
231
+ else
232
+ compute_table_name
233
+ end
234
+ end
235
+
236
+ def full_table_name_prefix #:nodoc:
237
+ (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
238
+ end
239
+
240
+ def full_table_name_suffix #:nodoc:
241
+ (module_parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
242
+ end
243
+
244
+ # The array of names of environments where destructive actions should be prohibited. By default,
245
+ # the value is <tt>["production"]</tt>.
246
+ def protected_environments
247
+ if defined?(@protected_environments)
248
+ @protected_environments
249
+ else
250
+ superclass.protected_environments
251
+ end
252
+ end
253
+
254
+ # Sets an array of names of environments where destructive actions should be prohibited.
255
+ def protected_environments=(environments)
256
+ @protected_environments = environments.map(&:to_s)
257
+ end
258
+
259
+ # Defines the name of the table column which will store the class name on single-table
260
+ # inheritance situations.
261
+ #
262
+ # The default inheritance column name is +type+, which means it's a
263
+ # reserved word inside Active Record. To be able to use single-table
264
+ # inheritance with another column name, or to use the column +type+ in
265
+ # your own model for something else, you can set +inheritance_column+:
266
+ #
267
+ # self.inheritance_column = 'zoink'
268
+ def inheritance_column
269
+ (@inheritance_column ||= nil) || superclass.inheritance_column
270
+ end
271
+
272
+ # Sets the value of inheritance_column
273
+ def inheritance_column=(value)
274
+ @inheritance_column = value.to_s
275
+ @explicit_inheritance_column = true
276
+ end
277
+
278
+ # The list of columns names the model should ignore. Ignored columns won't have attribute
279
+ # accessors defined, and won't be referenced in SQL queries.
280
+ def ignored_columns
281
+ if defined?(@ignored_columns)
282
+ @ignored_columns
283
+ else
284
+ superclass.ignored_columns
285
+ end
286
+ end
287
+
288
+ # Sets the columns names the model should ignore. Ignored columns won't have attribute
289
+ # accessors defined, and won't be referenced in SQL queries.
290
+ def ignored_columns=(columns)
291
+ @ignored_columns = columns.map(&:to_s)
292
+ end
293
+
294
+ def sequence_name
295
+ if base_class?
296
+ @sequence_name ||= reset_sequence_name
297
+ else
298
+ (@sequence_name ||= nil) || base_class.sequence_name
299
+ end
300
+ end
301
+
302
+ def reset_sequence_name #:nodoc:
303
+ @explicit_sequence_name = false
304
+ @sequence_name = connection.default_sequence_name(table_name, primary_key)
305
+ end
306
+
307
+ # Sets the name of the sequence to use when generating ids to the given
308
+ # value, or (if the value is +nil+ or +false+) to the value returned by the
309
+ # given block. This is required for Oracle and is useful for any
310
+ # database which relies on sequences for primary key generation.
311
+ #
312
+ # If a sequence name is not explicitly set when using Oracle,
313
+ # it will default to the commonly used pattern of: #{table_name}_seq
314
+ #
315
+ # If a sequence name is not explicitly set when using PostgreSQL, it
316
+ # will discover the sequence corresponding to your primary key for you.
317
+ #
318
+ # class Project < ActiveRecord::Base
319
+ # self.sequence_name = "projectseq" # default would have been "project_seq"
320
+ # end
321
+ def sequence_name=(value)
322
+ @sequence_name = value.to_s
323
+ @explicit_sequence_name = true
324
+ end
325
+
326
+ # Determines if the primary key values should be selected from their
327
+ # corresponding sequence before the insert statement.
328
+ def prefetch_primary_key?
329
+ connection.prefetch_primary_key?(table_name)
330
+ end
331
+
332
+ # Returns the next value that will be used as the primary key on
333
+ # an insert statement.
334
+ def next_sequence_value
335
+ connection.next_sequence_value(sequence_name)
336
+ end
337
+
338
+ # Indicates whether the table associated with this class exists
339
+ def table_exists?
340
+ connection.schema_cache.data_source_exists?(table_name)
341
+ end
342
+
343
+ def attributes_builder # :nodoc:
344
+ unless defined?(@attributes_builder) && @attributes_builder
345
+ defaults = _default_attributes.except(*(column_names - [primary_key]))
346
+ @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
347
+ end
348
+ @attributes_builder
349
+ end
350
+
351
+ def columns_hash # :nodoc:
352
+ load_schema
353
+ @columns_hash
354
+ end
355
+
356
+ def columns
357
+ load_schema
358
+ @columns ||= columns_hash.values
359
+ end
360
+
361
+ def attribute_types # :nodoc:
362
+ load_schema
363
+ @attribute_types ||= Hash.new(Type.default_value)
364
+ end
365
+
366
+ def yaml_encoder # :nodoc:
367
+ @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
368
+ end
369
+
370
+ # Returns the type of the attribute with the given name, after applying
371
+ # all modifiers. This method is the only valid source of information for
372
+ # anything related to the types of a model's attributes. This method will
373
+ # access the database and load the model's schema if it is required.
374
+ #
375
+ # The return value of this method will implement the interface described
376
+ # by ActiveModel::Type::Value (though the object itself may not subclass
377
+ # it).
378
+ #
379
+ # +attr_name+ The name of the attribute to retrieve the type for. Must be
380
+ # a string or a symbol.
381
+ def type_for_attribute(attr_name, &block)
382
+ attr_name = attr_name.to_s
383
+ if block
384
+ attribute_types.fetch(attr_name, &block)
385
+ else
386
+ attribute_types[attr_name]
387
+ end
388
+ end
389
+
390
+ # Returns a hash where the keys are column names and the values are
391
+ # default values when instantiating the Active Record object for this table.
392
+ def column_defaults
393
+ load_schema
394
+ @column_defaults ||= _default_attributes.deep_dup.to_hash
395
+ end
396
+
397
+ def _default_attributes # :nodoc:
398
+ load_schema
399
+ @default_attributes ||= ActiveModel::AttributeSet.new({})
400
+ end
401
+
402
+ # Returns an array of column names as strings.
403
+ def column_names
404
+ @column_names ||= columns.map(&:name)
405
+ end
406
+
407
+ def symbol_column_to_string(name_symbol) # :nodoc:
408
+ @symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
409
+ @symbol_column_to_string_name_hash[name_symbol]
410
+ end
411
+
412
+ # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
413
+ # and columns used for single table inheritance have been removed.
414
+ def content_columns
415
+ @content_columns ||= columns.reject do |c|
416
+ c.name == primary_key ||
417
+ c.name == inheritance_column ||
418
+ c.name.end_with?("_id") ||
419
+ c.name.end_with?("_count")
420
+ end
421
+ end
422
+
423
+ # Resets all the cached information about columns, which will cause them
424
+ # to be reloaded on the next request.
425
+ #
426
+ # The most common usage pattern for this method is probably in a migration,
427
+ # when just after creating a table you want to populate it with some default
428
+ # values, eg:
429
+ #
430
+ # class CreateJobLevels < ActiveRecord::Migration[5.0]
431
+ # def up
432
+ # create_table :job_levels do |t|
433
+ # t.integer :id
434
+ # t.string :name
435
+ #
436
+ # t.timestamps
437
+ # end
438
+ #
439
+ # JobLevel.reset_column_information
440
+ # %w{assistant executive manager director}.each do |type|
441
+ # JobLevel.create(name: type)
442
+ # end
443
+ # end
444
+ #
445
+ # def down
446
+ # drop_table :job_levels
447
+ # end
448
+ # end
449
+ def reset_column_information
450
+ connection.clear_cache!
451
+ ([self] + descendants).each(&:undefine_attribute_methods)
452
+ connection.schema_cache.clear_data_source_cache!(table_name)
453
+
454
+ reload_schema_from_cache
455
+ initialize_find_by_cache
456
+ end
457
+
458
+ protected
459
+
460
+ def initialize_load_schema_monitor
461
+ @load_schema_monitor = Monitor.new
462
+ end
463
+
464
+ private
465
+
466
+ def inherited(child_class)
467
+ super
468
+ child_class.initialize_load_schema_monitor
469
+ end
470
+
471
+ def schema_loaded?
472
+ defined?(@schema_loaded) && @schema_loaded
473
+ end
474
+
475
+ def load_schema
476
+ return if schema_loaded?
477
+ @load_schema_monitor.synchronize do
478
+ return if defined?(@columns_hash) && @columns_hash
479
+
480
+ load_schema!
481
+
482
+ @schema_loaded = true
483
+ rescue
484
+ reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
485
+ raise
486
+ end
487
+ end
488
+
489
+ def load_schema!
490
+ @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
491
+ @columns_hash.each do |name, column|
492
+ define_attribute(
493
+ name,
494
+ connection.lookup_cast_type_from_column(column),
495
+ default: column.default,
496
+ user_provided_default: false
497
+ )
498
+ end
499
+ end
500
+
501
+ def reload_schema_from_cache
502
+ @arel_table = nil
503
+ @column_names = nil
504
+ @symbol_column_to_string_name_hash = nil
505
+ @attribute_types = nil
506
+ @content_columns = nil
507
+ @default_attributes = nil
508
+ @column_defaults = nil
509
+ @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
510
+ @attributes_builder = nil
511
+ @columns = nil
512
+ @columns_hash = nil
513
+ @schema_loaded = false
514
+ @attribute_names = nil
515
+ @yaml_encoder = nil
516
+ direct_descendants.each do |descendant|
517
+ descendant.send(:reload_schema_from_cache)
518
+ end
519
+ end
520
+
521
+ # Guesses the table name, but does not decorate it with prefix and suffix information.
522
+ def undecorated_table_name(class_name = base_class.name)
523
+ table_name = class_name.to_s.demodulize.underscore
524
+ pluralize_table_names ? table_name.pluralize : table_name
525
+ end
526
+
527
+ # Computes and returns a table name according to default conventions.
528
+ def compute_table_name
529
+ if base_class?
530
+ # Nested classes are prefixed with singular parent table name.
531
+ if module_parent < Base && !module_parent.abstract_class?
532
+ contained = module_parent.table_name
533
+ contained = contained.singularize if module_parent.pluralize_table_names
534
+ contained += "_"
535
+ end
536
+
537
+ "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
538
+ else
539
+ # STI subclasses always use their superclass' table.
540
+ base_class.table_name
541
+ end
542
+ end
543
+ end
544
+ end
545
+ end