activerecord 4.2.0 → 6.0.5.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of activerecord might be problematic. Click here for more details.

Files changed (373) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +852 -801
  3. data/MIT-LICENSE +4 -2
  4. data/README.rdoc +14 -13
  5. data/examples/performance.rb +33 -32
  6. data/examples/simple.rb +5 -4
  7. data/lib/active_record/advisory_lock_base.rb +18 -0
  8. data/lib/active_record/aggregations.rb +267 -249
  9. data/lib/active_record/association_relation.rb +26 -6
  10. data/lib/active_record/associations/alias_tracker.rb +29 -36
  11. data/lib/active_record/associations/association.rb +137 -55
  12. data/lib/active_record/associations/association_scope.rb +110 -132
  13. data/lib/active_record/associations/belongs_to_association.rb +67 -54
  14. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
  15. data/lib/active_record/associations/builder/association.rb +27 -40
  16. data/lib/active_record/associations/builder/belongs_to.rb +69 -55
  17. data/lib/active_record/associations/builder/collection_association.rb +10 -29
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +58 -70
  19. data/lib/active_record/associations/builder/has_many.rb +8 -4
  20. data/lib/active_record/associations/builder/has_one.rb +46 -5
  21. data/lib/active_record/associations/builder/singular_association.rb +16 -10
  22. data/lib/active_record/associations/collection_association.rb +150 -275
  23. data/lib/active_record/associations/collection_proxy.rb +253 -152
  24. data/lib/active_record/associations/foreign_association.rb +20 -0
  25. data/lib/active_record/associations/has_many_association.rb +35 -84
  26. data/lib/active_record/associations/has_many_through_association.rb +62 -80
  27. data/lib/active_record/associations/has_one_association.rb +62 -49
  28. data/lib/active_record/associations/has_one_through_association.rb +20 -11
  29. data/lib/active_record/associations/join_dependency/join_association.rb +43 -78
  30. data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
  31. data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
  32. data/lib/active_record/associations/join_dependency.rb +159 -162
  33. data/lib/active_record/associations/preloader/association.rb +102 -113
  34. data/lib/active_record/associations/preloader/through_association.rb +85 -65
  35. data/lib/active_record/associations/preloader.rb +96 -95
  36. data/lib/active_record/associations/singular_association.rb +18 -45
  37. data/lib/active_record/associations/through_association.rb +49 -24
  38. data/lib/active_record/associations.rb +1737 -1596
  39. data/lib/active_record/attribute_assignment.rb +57 -185
  40. data/lib/active_record/attribute_decorators.rb +39 -17
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +14 -5
  42. data/lib/active_record/attribute_methods/dirty.rb +174 -134
  43. data/lib/active_record/attribute_methods/primary_key.rb +90 -84
  44. data/lib/active_record/attribute_methods/query.rb +6 -5
  45. data/lib/active_record/attribute_methods/read.rb +20 -77
  46. data/lib/active_record/attribute_methods/serialization.rb +40 -21
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -37
  48. data/lib/active_record/attribute_methods/write.rb +33 -56
  49. data/lib/active_record/attribute_methods.rb +124 -143
  50. data/lib/active_record/attributes.rb +213 -74
  51. data/lib/active_record/autosave_association.rb +125 -54
  52. data/lib/active_record/base.rb +60 -49
  53. data/lib/active_record/callbacks.rb +101 -76
  54. data/lib/active_record/coders/json.rb +3 -1
  55. data/lib/active_record/coders/yaml_column.rb +36 -13
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +810 -291
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +253 -108
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +83 -24
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +171 -53
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +6 -4
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -47
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +383 -239
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +736 -235
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +190 -87
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +487 -192
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +536 -600
  69. data/lib/active_record/connection_adapters/column.rb +56 -43
  70. data/lib/active_record/connection_adapters/connection_specification.rb +174 -153
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +196 -0
  74. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
  75. data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +71 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -196
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +71 -115
  84. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
  85. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +5 -2
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +5 -1
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +17 -13
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
  99. data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +9 -5
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +144 -47
  109. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
  110. data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
  112. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
  113. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +465 -291
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +565 -363
  117. data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
  119. data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +119 -0
  120. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  121. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  125. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
  126. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +299 -364
  127. data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
  128. data/lib/active_record/connection_handling.rb +167 -41
  129. data/lib/active_record/core.rb +277 -233
  130. data/lib/active_record/counter_cache.rb +71 -50
  131. data/lib/active_record/database_configurations/database_config.rb +37 -0
  132. data/lib/active_record/database_configurations/hash_config.rb +50 -0
  133. data/lib/active_record/database_configurations/url_config.rb +78 -0
  134. data/lib/active_record/database_configurations.rb +233 -0
  135. data/lib/active_record/define_callbacks.rb +22 -0
  136. data/lib/active_record/dynamic_matchers.rb +87 -106
  137. data/lib/active_record/enum.rb +172 -89
  138. data/lib/active_record/errors.rb +189 -53
  139. data/lib/active_record/explain.rb +22 -11
  140. data/lib/active_record/explain_registry.rb +4 -2
  141. data/lib/active_record/explain_subscriber.rb +11 -6
  142. data/lib/active_record/fixture_set/file.rb +35 -9
  143. data/lib/active_record/fixture_set/model_metadata.rb +33 -0
  144. data/lib/active_record/fixture_set/render_context.rb +17 -0
  145. data/lib/active_record/fixture_set/table_row.rb +152 -0
  146. data/lib/active_record/fixture_set/table_rows.rb +46 -0
  147. data/lib/active_record/fixtures.rb +225 -497
  148. data/lib/active_record/gem_version.rb +6 -4
  149. data/lib/active_record/inheritance.rb +158 -115
  150. data/lib/active_record/insert_all.rb +179 -0
  151. data/lib/active_record/integration.rb +123 -29
  152. data/lib/active_record/internal_metadata.rb +53 -0
  153. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  154. data/lib/active_record/locale/en.yml +3 -2
  155. data/lib/active_record/locking/optimistic.rb +99 -98
  156. data/lib/active_record/locking/pessimistic.rb +18 -6
  157. data/lib/active_record/log_subscriber.rb +76 -33
  158. data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
  159. data/lib/active_record/middleware/database_selector/resolver.rb +87 -0
  160. data/lib/active_record/middleware/database_selector.rb +74 -0
  161. data/lib/active_record/migration/command_recorder.rb +166 -91
  162. data/lib/active_record/migration/compatibility.rb +244 -0
  163. data/lib/active_record/migration/join_table.rb +8 -7
  164. data/lib/active_record/migration.rb +636 -290
  165. data/lib/active_record/model_schema.rb +344 -112
  166. data/lib/active_record/nested_attributes.rb +265 -215
  167. data/lib/active_record/no_touching.rb +15 -2
  168. data/lib/active_record/null_relation.rb +24 -38
  169. data/lib/active_record/persistence.rb +559 -125
  170. data/lib/active_record/query_cache.rb +19 -23
  171. data/lib/active_record/querying.rb +44 -30
  172. data/lib/active_record/railtie.rb +166 -47
  173. data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
  174. data/lib/active_record/railties/console_sandbox.rb +2 -0
  175. data/lib/active_record/railties/controller_runtime.rb +34 -33
  176. data/lib/active_record/railties/databases.rake +341 -202
  177. data/lib/active_record/readonly_attributes.rb +5 -4
  178. data/lib/active_record/reflection.rb +461 -302
  179. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  180. data/lib/active_record/relation/batches.rb +206 -55
  181. data/lib/active_record/relation/calculations.rb +270 -249
  182. data/lib/active_record/relation/delegation.rb +76 -84
  183. data/lib/active_record/relation/finder_methods.rb +287 -255
  184. data/lib/active_record/relation/from_clause.rb +30 -0
  185. data/lib/active_record/relation/merger.rb +86 -68
  186. data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -25
  187. data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
  188. data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
  189. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
  190. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
  191. data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
  192. data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
  193. data/lib/active_record/relation/predicate_builder.rb +112 -92
  194. data/lib/active_record/relation/query_attribute.rb +50 -0
  195. data/lib/active_record/relation/query_methods.rb +612 -392
  196. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  197. data/lib/active_record/relation/spawn_methods.rb +18 -17
  198. data/lib/active_record/relation/where_clause.rb +189 -0
  199. data/lib/active_record/relation/where_clause_factory.rb +33 -0
  200. data/lib/active_record/relation.rb +533 -340
  201. data/lib/active_record/result.rb +79 -43
  202. data/lib/active_record/runtime_registry.rb +6 -4
  203. data/lib/active_record/sanitization.rb +144 -121
  204. data/lib/active_record/schema.rb +21 -24
  205. data/lib/active_record/schema_dumper.rb +112 -93
  206. data/lib/active_record/schema_migration.rb +24 -20
  207. data/lib/active_record/scoping/default.rb +98 -82
  208. data/lib/active_record/scoping/named.rb +91 -33
  209. data/lib/active_record/scoping.rb +45 -27
  210. data/lib/active_record/secure_token.rb +40 -0
  211. data/lib/active_record/serialization.rb +5 -5
  212. data/lib/active_record/statement_cache.rb +73 -36
  213. data/lib/active_record/store.rb +127 -42
  214. data/lib/active_record/suppressor.rb +61 -0
  215. data/lib/active_record/table_metadata.rb +90 -0
  216. data/lib/active_record/tasks/database_tasks.rb +309 -99
  217. data/lib/active_record/tasks/mysql_database_tasks.rb +58 -89
  218. data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -31
  219. data/lib/active_record/tasks/sqlite_database_tasks.rb +37 -16
  220. data/lib/active_record/test_databases.rb +23 -0
  221. data/lib/active_record/test_fixtures.rb +243 -0
  222. data/lib/active_record/timestamp.rb +86 -41
  223. data/lib/active_record/touch_later.rb +65 -0
  224. data/lib/active_record/transactions.rb +222 -146
  225. data/lib/active_record/translation.rb +3 -1
  226. data/lib/active_record/type/adapter_specific_registry.rb +126 -0
  227. data/lib/active_record/type/date.rb +4 -41
  228. data/lib/active_record/type/date_time.rb +4 -38
  229. data/lib/active_record/type/decimal_without_scale.rb +6 -2
  230. data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
  231. data/lib/active_record/type/internal/timezone.rb +17 -0
  232. data/lib/active_record/type/json.rb +30 -0
  233. data/lib/active_record/type/serialized.rb +29 -15
  234. data/lib/active_record/type/text.rb +2 -2
  235. data/lib/active_record/type/time.rb +21 -16
  236. data/lib/active_record/type/type_map.rb +16 -19
  237. data/lib/active_record/type/unsigned_integer.rb +9 -8
  238. data/lib/active_record/type.rb +77 -23
  239. data/lib/active_record/type_caster/connection.rb +34 -0
  240. data/lib/active_record/type_caster/map.rb +20 -0
  241. data/lib/active_record/type_caster.rb +9 -0
  242. data/lib/active_record/validations/absence.rb +25 -0
  243. data/lib/active_record/validations/associated.rb +12 -4
  244. data/lib/active_record/validations/length.rb +26 -0
  245. data/lib/active_record/validations/presence.rb +14 -13
  246. data/lib/active_record/validations/uniqueness.rb +43 -46
  247. data/lib/active_record/validations.rb +38 -35
  248. data/lib/active_record/version.rb +3 -1
  249. data/lib/active_record.rb +44 -21
  250. data/lib/arel/alias_predication.rb +9 -0
  251. data/lib/arel/attributes/attribute.rb +37 -0
  252. data/lib/arel/attributes.rb +22 -0
  253. data/lib/arel/collectors/bind.rb +24 -0
  254. data/lib/arel/collectors/composite.rb +31 -0
  255. data/lib/arel/collectors/plain_string.rb +20 -0
  256. data/lib/arel/collectors/sql_string.rb +20 -0
  257. data/lib/arel/collectors/substitute_binds.rb +28 -0
  258. data/lib/arel/crud.rb +42 -0
  259. data/lib/arel/delete_manager.rb +18 -0
  260. data/lib/arel/errors.rb +9 -0
  261. data/lib/arel/expressions.rb +29 -0
  262. data/lib/arel/factory_methods.rb +49 -0
  263. data/lib/arel/insert_manager.rb +49 -0
  264. data/lib/arel/math.rb +45 -0
  265. data/lib/arel/nodes/and.rb +32 -0
  266. data/lib/arel/nodes/ascending.rb +23 -0
  267. data/lib/arel/nodes/binary.rb +52 -0
  268. data/lib/arel/nodes/bind_param.rb +36 -0
  269. data/lib/arel/nodes/case.rb +55 -0
  270. data/lib/arel/nodes/casted.rb +50 -0
  271. data/lib/arel/nodes/comment.rb +29 -0
  272. data/lib/arel/nodes/count.rb +12 -0
  273. data/lib/arel/nodes/delete_statement.rb +45 -0
  274. data/lib/arel/nodes/descending.rb +23 -0
  275. data/lib/arel/nodes/equality.rb +18 -0
  276. data/lib/arel/nodes/extract.rb +24 -0
  277. data/lib/arel/nodes/false.rb +16 -0
  278. data/lib/arel/nodes/full_outer_join.rb +8 -0
  279. data/lib/arel/nodes/function.rb +44 -0
  280. data/lib/arel/nodes/grouping.rb +8 -0
  281. data/lib/arel/nodes/in.rb +8 -0
  282. data/lib/arel/nodes/infix_operation.rb +80 -0
  283. data/lib/arel/nodes/inner_join.rb +8 -0
  284. data/lib/arel/nodes/insert_statement.rb +37 -0
  285. data/lib/arel/nodes/join_source.rb +20 -0
  286. data/lib/arel/nodes/matches.rb +18 -0
  287. data/lib/arel/nodes/named_function.rb +23 -0
  288. data/lib/arel/nodes/node.rb +50 -0
  289. data/lib/arel/nodes/node_expression.rb +13 -0
  290. data/lib/arel/nodes/outer_join.rb +8 -0
  291. data/lib/arel/nodes/over.rb +15 -0
  292. data/lib/arel/nodes/regexp.rb +16 -0
  293. data/lib/arel/nodes/right_outer_join.rb +8 -0
  294. data/lib/arel/nodes/select_core.rb +67 -0
  295. data/lib/arel/nodes/select_statement.rb +41 -0
  296. data/lib/arel/nodes/sql_literal.rb +16 -0
  297. data/lib/arel/nodes/string_join.rb +11 -0
  298. data/lib/arel/nodes/table_alias.rb +27 -0
  299. data/lib/arel/nodes/terminal.rb +16 -0
  300. data/lib/arel/nodes/true.rb +16 -0
  301. data/lib/arel/nodes/unary.rb +45 -0
  302. data/lib/arel/nodes/unary_operation.rb +20 -0
  303. data/lib/arel/nodes/unqualified_column.rb +22 -0
  304. data/lib/arel/nodes/update_statement.rb +41 -0
  305. data/lib/arel/nodes/values_list.rb +9 -0
  306. data/lib/arel/nodes/window.rb +126 -0
  307. data/lib/arel/nodes/with.rb +11 -0
  308. data/lib/arel/nodes.rb +68 -0
  309. data/lib/arel/order_predications.rb +13 -0
  310. data/lib/arel/predications.rb +256 -0
  311. data/lib/arel/select_manager.rb +271 -0
  312. data/lib/arel/table.rb +110 -0
  313. data/lib/arel/tree_manager.rb +72 -0
  314. data/lib/arel/update_manager.rb +34 -0
  315. data/lib/arel/visitors/depth_first.rb +203 -0
  316. data/lib/arel/visitors/dot.rb +296 -0
  317. data/lib/arel/visitors/ibm_db.rb +34 -0
  318. data/lib/arel/visitors/informix.rb +62 -0
  319. data/lib/arel/visitors/mssql.rb +156 -0
  320. data/lib/arel/visitors/mysql.rb +83 -0
  321. data/lib/arel/visitors/oracle.rb +158 -0
  322. data/lib/arel/visitors/oracle12.rb +65 -0
  323. data/lib/arel/visitors/postgresql.rb +109 -0
  324. data/lib/arel/visitors/sqlite.rb +38 -0
  325. data/lib/arel/visitors/to_sql.rb +888 -0
  326. data/lib/arel/visitors/visitor.rb +45 -0
  327. data/lib/arel/visitors/where_sql.rb +22 -0
  328. data/lib/arel/visitors.rb +20 -0
  329. data/lib/arel/window_predications.rb +9 -0
  330. data/lib/arel.rb +62 -0
  331. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
  332. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  333. data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
  334. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  335. data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -8
  336. data/lib/rails/generators/active_record/migration.rb +30 -1
  337. data/lib/rails/generators/active_record/model/model_generator.rb +18 -22
  338. data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
  339. data/lib/rails/generators/active_record.rb +7 -5
  340. metadata +174 -63
  341. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  342. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  343. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  344. data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
  345. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  346. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  347. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  348. data/lib/active_record/attribute.rb +0 -149
  349. data/lib/active_record/attribute_set/builder.rb +0 -86
  350. data/lib/active_record/attribute_set.rb +0 -77
  351. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  352. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  353. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  354. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  355. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
  356. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  357. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  358. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  359. data/lib/active_record/type/big_integer.rb +0 -13
  360. data/lib/active_record/type/binary.rb +0 -50
  361. data/lib/active_record/type/boolean.rb +0 -30
  362. data/lib/active_record/type/decimal.rb +0 -40
  363. data/lib/active_record/type/decorator.rb +0 -14
  364. data/lib/active_record/type/float.rb +0 -19
  365. data/lib/active_record/type/integer.rb +0 -55
  366. data/lib/active_record/type/mutable.rb +0 -16
  367. data/lib/active_record/type/numeric.rb +0 -36
  368. data/lib/active_record/type/string.rb +0 -36
  369. data/lib/active_record/type/time_value.rb +0 -38
  370. data/lib/active_record/type/value.rb +0 -101
  371. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
  372. data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
  373. /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,58 +1,139 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
4
+
1
5
  module ActiveRecord
2
6
  module ModelSchema
3
7
  extend ActiveSupport::Concern
4
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.
5
120
  included do
6
- ##
7
- # :singleton-method:
8
- # Accessor for the prefix type that will be prepended to every primary key column name.
9
- # The options are :table_name and :table_name_with_underscore. If the first is specified,
10
- # the Product class will look for "productid" instead of "id" as the primary column. If the
11
- # latter is specified, the Product class will look for "product_id" instead of "id". Remember
12
- # that this is a global setting for all Active Records.
13
121
  mattr_accessor :primary_key_prefix_type, instance_writer: false
14
122
 
15
- ##
16
- # :singleton-method:
17
- # Accessor for the name of the prefix string to prepend to every table name. So if set
18
- # to "basecamp_", all table names will be named like "basecamp_projects", "basecamp_people",
19
- # etc. This is a convenient way of creating a namespace for tables in a shared database.
20
- # By default, the prefix is the empty string.
21
- #
22
- # If you are organising your models within modules you can add a prefix to the models within
23
- # a namespace by defining a singleton method in the parent module called table_name_prefix which
24
- # returns your chosen prefix.
25
- class_attribute :table_name_prefix, instance_writer: false
26
- self.table_name_prefix = ""
27
-
28
- ##
29
- # :singleton-method:
30
- # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
31
- # "people_basecamp"). By default, the suffix is the empty string.
32
- #
33
- # If you are organising your models within modules, you can add a suffix to the models within
34
- # a namespace by defining a singleton method in the parent module called table_name_suffix which
35
- # returns your chosen suffix.
36
- class_attribute :table_name_suffix, instance_writer: false
37
- self.table_name_suffix = ""
38
-
39
- ##
40
- # :singleton-method:
41
- # Accessor for the name of the schema migrations table. By default, the value is "schema_migrations"
42
- class_attribute :schema_migrations_table_name, instance_accessor: false
43
- self.schema_migrations_table_name = "schema_migrations"
44
-
45
- ##
46
- # :singleton-method:
47
- # Indicates whether table names should be the pluralized versions of the corresponding class names.
48
- # If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
49
- # See table_name for the full rules on table/class naming. This is true, by default.
50
- class_attribute :pluralize_table_names, instance_writer: false
51
- self.pluralize_table_names = true
52
-
53
- self.inheritance_column = 'type'
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
54
133
 
55
134
  delegate :type_for_attribute, to: :class
135
+
136
+ initialize_load_schema_monitor
56
137
  end
57
138
 
58
139
  # Derives the join table name for +first_table+ and +second_table+. The
@@ -111,17 +192,6 @@ module ActiveRecord
111
192
  # class Mouse < ActiveRecord::Base
112
193
  # self.table_name = "mice"
113
194
  # end
114
- #
115
- # Alternatively, you can override the table_name method to define your
116
- # own computation. (Possibly using <tt>super</tt> to manipulate the default
117
- # table name.) Example:
118
- #
119
- # class Post < ActiveRecord::Base
120
- # def self.table_name
121
- # "special_" + super
122
- # end
123
- # end
124
- # Post.table_name # => "special_posts"
125
195
  def table_name
126
196
  reset_table_name unless defined?(@table_name)
127
197
  @table_name
@@ -132,9 +202,6 @@ module ActiveRecord
132
202
  # class Project < ActiveRecord::Base
133
203
  # self.table_name = "project"
134
204
  # end
135
- #
136
- # You can also just define your own <tt>self.table_name</tt> method; see
137
- # the documentation for ActiveRecord::Base#table_name.
138
205
  def table_name=(value)
139
206
  value = value && value.to_s
140
207
 
@@ -147,7 +214,7 @@ module ActiveRecord
147
214
  @quoted_table_name = nil
148
215
  @arel_table = nil
149
216
  @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
150
- @relation = Relation.create(self, arel_table)
217
+ @predicate_builder = nil
151
218
  end
152
219
 
153
220
  # Returns a quoted version of the table name, used to construct SQL statements.
@@ -167,11 +234,26 @@ module ActiveRecord
167
234
  end
168
235
 
169
236
  def full_table_name_prefix #:nodoc:
170
- (parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
237
+ (module_parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
171
238
  end
172
239
 
173
240
  def full_table_name_suffix #:nodoc:
174
- (parents.detect {|p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
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)
175
257
  end
176
258
 
177
259
  # Defines the name of the table column which will store the class name on single-table
@@ -193,8 +275,53 @@ module ActiveRecord
193
275
  @explicit_inheritance_column = true
194
276
  end
195
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
+ #
291
+ # A common usage pattern for this method is to ensure all references to an attribute
292
+ # have been removed and deployed, before a migration to drop the column from the database
293
+ # has been deployed and run. Using this two step approach to dropping columns ensures there
294
+ # is no code that raises errors due to having a cached schema in memory at the time the
295
+ # schema migration is run.
296
+ #
297
+ # For example, given a model where you want to drop the "category" attribute, first mark it
298
+ # as ignored:
299
+ #
300
+ # class Project < ActiveRecord::Base
301
+ # # schema:
302
+ # # id :bigint
303
+ # # name :string, limit: 255
304
+ # # category :string, limit: 255
305
+ #
306
+ # self.ignored_columns = [:category]
307
+ # end
308
+ #
309
+ # The schema still contains `category`, but now the model omits it, so any meta-driven code or
310
+ # schema caching will not attempt to use the column:
311
+ #
312
+ # Project.columns_hash["category"] => nil
313
+ #
314
+ # You will get an error if accessing that attribute directly, so ensure all usages of the
315
+ # column are removed (automated tests can help you find any usages).
316
+ #
317
+ # user = Project.create!(name: "First Project")
318
+ # user.category # => raises NoMethodError
319
+ def ignored_columns=(columns)
320
+ @ignored_columns = columns.map(&:to_s)
321
+ end
322
+
196
323
  def sequence_name
197
- if base_class == self
324
+ if base_class?
198
325
  @sequence_name ||= reset_sequence_name
199
326
  else
200
327
  (@sequence_name ||= nil) || base_class.sequence_name
@@ -207,7 +334,7 @@ module ActiveRecord
207
334
  end
208
335
 
209
336
  # Sets the name of the sequence to use when generating ids to the given
210
- # value, or (if the value is nil or false) to the value returned by the
337
+ # value, or (if the value is +nil+ or +false+) to the value returned by the
211
338
  # given block. This is required for Oracle and is useful for any
212
339
  # database which relies on sequences for primary key generation.
213
340
  #
@@ -225,45 +352,101 @@ module ActiveRecord
225
352
  @explicit_sequence_name = true
226
353
  end
227
354
 
355
+ # Determines if the primary key values should be selected from their
356
+ # corresponding sequence before the insert statement.
357
+ def prefetch_primary_key?
358
+ connection.prefetch_primary_key?(table_name)
359
+ end
360
+
361
+ # Returns the next value that will be used as the primary key on
362
+ # an insert statement.
363
+ def next_sequence_value
364
+ connection.next_sequence_value(sequence_name)
365
+ end
366
+
228
367
  # Indicates whether the table associated with this class exists
229
368
  def table_exists?
230
- connection.schema_cache.table_exists?(table_name)
369
+ connection.schema_cache.data_source_exists?(table_name)
231
370
  end
232
371
 
233
372
  def attributes_builder # :nodoc:
234
- @attributes_builder ||= AttributeSet::Builder.new(column_types, primary_key)
373
+ unless defined?(@attributes_builder) && @attributes_builder
374
+ defaults = _default_attributes.except(*(column_names - [primary_key]))
375
+ @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
376
+ end
377
+ @attributes_builder
235
378
  end
236
379
 
237
- def column_types # :nodoc:
238
- @column_types ||= columns_hash.transform_values(&:cast_type).tap do |h|
239
- h.default = Type::Value.new
240
- end
380
+ def columns_hash # :nodoc:
381
+ load_schema
382
+ @columns_hash
383
+ end
384
+
385
+ def columns
386
+ load_schema
387
+ @columns ||= columns_hash.values
388
+ end
389
+
390
+ def attribute_types # :nodoc:
391
+ load_schema
392
+ @attribute_types ||= Hash.new(Type.default_value)
393
+ end
394
+
395
+ def yaml_encoder # :nodoc:
396
+ @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
241
397
  end
242
398
 
243
- def type_for_attribute(attr_name) # :nodoc:
244
- column_types[attr_name]
399
+ # Returns the type of the attribute with the given name, after applying
400
+ # all modifiers. This method is the only valid source of information for
401
+ # anything related to the types of a model's attributes. This method will
402
+ # access the database and load the model's schema if it is required.
403
+ #
404
+ # The return value of this method will implement the interface described
405
+ # by ActiveModel::Type::Value (though the object itself may not subclass
406
+ # it).
407
+ #
408
+ # +attr_name+ The name of the attribute to retrieve the type for. Must be
409
+ # a string or a symbol.
410
+ def type_for_attribute(attr_name, &block)
411
+ attr_name = attr_name.to_s
412
+ if block
413
+ attribute_types.fetch(attr_name, &block)
414
+ else
415
+ attribute_types[attr_name]
416
+ end
245
417
  end
246
418
 
247
419
  # Returns a hash where the keys are column names and the values are
248
- # default values when instantiating the AR object for this table.
420
+ # default values when instantiating the Active Record object for this table.
249
421
  def column_defaults
250
- _default_attributes.to_hash
422
+ load_schema
423
+ @column_defaults ||= _default_attributes.deep_dup.to_hash
251
424
  end
252
425
 
253
426
  def _default_attributes # :nodoc:
254
- @default_attributes ||= attributes_builder.build_from_database(
255
- raw_default_values)
427
+ load_schema
428
+ @default_attributes ||= ActiveModel::AttributeSet.new({})
256
429
  end
257
430
 
258
431
  # Returns an array of column names as strings.
259
432
  def column_names
260
- @column_names ||= columns.map { |column| column.name }
433
+ @column_names ||= columns.map(&:name)
434
+ end
435
+
436
+ def symbol_column_to_string(name_symbol) # :nodoc:
437
+ @symbol_column_to_string_name_hash ||= column_names.index_by(&:to_sym)
438
+ @symbol_column_to_string_name_hash[name_symbol]
261
439
  end
262
440
 
263
441
  # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
264
442
  # and columns used for single table inheritance have been removed.
265
443
  def content_columns
266
- @content_columns ||= columns.reject { |c| c.name == primary_key || c.name =~ /(_id|_count)$/ || c.name == inheritance_column }
444
+ @content_columns ||= columns.reject do |c|
445
+ c.name == primary_key ||
446
+ c.name == inheritance_column ||
447
+ c.name.end_with?("_id") ||
448
+ c.name.end_with?("_count")
449
+ end
267
450
  end
268
451
 
269
452
  # Resets all the cached information about columns, which will cause them
@@ -273,7 +456,7 @@ module ActiveRecord
273
456
  # when just after creating a table you want to populate it with some default
274
457
  # values, eg:
275
458
  #
276
- # class CreateJobLevels < ActiveRecord::Migration
459
+ # class CreateJobLevels < ActiveRecord::Migration[5.0]
277
460
  # def up
278
461
  # create_table :job_levels do |t|
279
462
  # t.integer :id
@@ -294,47 +477,96 @@ module ActiveRecord
294
477
  # end
295
478
  def reset_column_information
296
479
  connection.clear_cache!
297
- undefine_attribute_methods
298
- connection.schema_cache.clear_table_cache!(table_name) if table_exists?
299
-
300
- @arel_engine = nil
301
- @column_names = nil
302
- @column_types = nil
303
- @content_columns = nil
304
- @default_attributes = nil
305
- @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
306
- @relation = nil
480
+ ([self] + descendants).each(&:undefine_attribute_methods)
481
+ connection.schema_cache.clear_data_source_cache!(table_name)
482
+
483
+ reload_schema_from_cache
484
+ initialize_find_by_cache
307
485
  end
308
486
 
487
+ protected
488
+ def initialize_load_schema_monitor
489
+ @load_schema_monitor = Monitor.new
490
+ end
491
+
309
492
  private
493
+ def inherited(child_class)
494
+ super
495
+ child_class.initialize_load_schema_monitor
496
+ end
310
497
 
311
- # Guesses the table name, but does not decorate it with prefix and suffix information.
312
- def undecorated_table_name(class_name = base_class.name)
313
- table_name = class_name.to_s.demodulize.underscore
314
- pluralize_table_names ? table_name.pluralize : table_name
315
- end
498
+ def schema_loaded?
499
+ defined?(@schema_loaded) && @schema_loaded
500
+ end
501
+
502
+ def load_schema
503
+ return if schema_loaded?
504
+ @load_schema_monitor.synchronize do
505
+ return if defined?(@columns_hash) && @columns_hash
506
+
507
+ load_schema!
316
508
 
317
- # Computes and returns a table name according to default conventions.
318
- def compute_table_name
319
- base = base_class
320
- if self == base
321
- # Nested classes are prefixed with singular parent table name.
322
- if parent < Base && !parent.abstract_class?
323
- contained = parent.table_name
324
- contained = contained.singularize if parent.pluralize_table_names
325
- contained += '_'
509
+ @schema_loaded = true
510
+ rescue
511
+ reload_schema_from_cache # If the schema loading failed half way through, we must reset the state.
512
+ raise
326
513
  end
514
+ end
327
515
 
328
- "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
329
- else
330
- # STI subclasses always use their superclass' table.
331
- base.table_name
516
+ def load_schema!
517
+ @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
518
+ @columns_hash.each do |name, column|
519
+ define_attribute(
520
+ name,
521
+ connection.lookup_cast_type_from_column(column),
522
+ default: column.default,
523
+ user_provided_default: false
524
+ )
525
+ end
332
526
  end
333
- end
334
527
 
335
- def raw_default_values
336
- columns_hash.transform_values(&:default)
337
- end
528
+ def reload_schema_from_cache
529
+ @arel_table = nil
530
+ @column_names = nil
531
+ @symbol_column_to_string_name_hash = nil
532
+ @attribute_types = nil
533
+ @content_columns = nil
534
+ @default_attributes = nil
535
+ @column_defaults = nil
536
+ @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
537
+ @attributes_builder = nil
538
+ @columns = nil
539
+ @columns_hash = nil
540
+ @schema_loaded = false
541
+ @attribute_names = nil
542
+ @yaml_encoder = nil
543
+ direct_descendants.each do |descendant|
544
+ descendant.send(:reload_schema_from_cache)
545
+ end
546
+ end
547
+
548
+ # Guesses the table name, but does not decorate it with prefix and suffix information.
549
+ def undecorated_table_name(class_name = base_class.name)
550
+ table_name = class_name.to_s.demodulize.underscore
551
+ pluralize_table_names ? table_name.pluralize : table_name
552
+ end
553
+
554
+ # Computes and returns a table name according to default conventions.
555
+ def compute_table_name
556
+ if base_class?
557
+ # Nested classes are prefixed with singular parent table name.
558
+ if module_parent < Base && !module_parent.abstract_class?
559
+ contained = module_parent.table_name
560
+ contained = contained.singularize if module_parent.pluralize_table_names
561
+ contained += "_"
562
+ end
563
+
564
+ "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
565
+ else
566
+ # STI subclasses always use their superclass' table.
567
+ base_class.table_name
568
+ end
569
+ end
338
570
  end
339
571
  end
340
572
  end