activerecord 3.2.22.5 → 5.2.8

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 (275) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +657 -621
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +41 -46
  5. data/examples/performance.rb +55 -42
  6. data/examples/simple.rb +6 -5
  7. data/lib/active_record/aggregations.rb +264 -236
  8. data/lib/active_record/association_relation.rb +40 -0
  9. data/lib/active_record/associations/alias_tracker.rb +47 -42
  10. data/lib/active_record/associations/association.rb +127 -75
  11. data/lib/active_record/associations/association_scope.rb +126 -92
  12. data/lib/active_record/associations/belongs_to_association.rb +78 -27
  13. data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -4
  14. data/lib/active_record/associations/builder/association.rb +117 -32
  15. data/lib/active_record/associations/builder/belongs_to.rb +135 -60
  16. data/lib/active_record/associations/builder/collection_association.rb +61 -54
  17. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +120 -42
  18. data/lib/active_record/associations/builder/has_many.rb +10 -64
  19. data/lib/active_record/associations/builder/has_one.rb +19 -51
  20. data/lib/active_record/associations/builder/singular_association.rb +28 -18
  21. data/lib/active_record/associations/collection_association.rb +226 -293
  22. data/lib/active_record/associations/collection_proxy.rb +1067 -69
  23. data/lib/active_record/associations/foreign_association.rb +13 -0
  24. data/lib/active_record/associations/has_many_association.rb +83 -47
  25. data/lib/active_record/associations/has_many_through_association.rb +98 -65
  26. data/lib/active_record/associations/has_one_association.rb +57 -20
  27. data/lib/active_record/associations/has_one_through_association.rb +18 -9
  28. data/lib/active_record/associations/join_dependency/join_association.rb +48 -126
  29. data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
  30. data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
  31. data/lib/active_record/associations/join_dependency.rb +212 -164
  32. data/lib/active_record/associations/preloader/association.rb +95 -89
  33. data/lib/active_record/associations/preloader/through_association.rb +84 -44
  34. data/lib/active_record/associations/preloader.rb +123 -111
  35. data/lib/active_record/associations/singular_association.rb +33 -24
  36. data/lib/active_record/associations/through_association.rb +60 -26
  37. data/lib/active_record/associations.rb +1759 -1506
  38. data/lib/active_record/attribute_assignment.rb +60 -193
  39. data/lib/active_record/attribute_decorators.rb +90 -0
  40. data/lib/active_record/attribute_methods/before_type_cast.rb +55 -8
  41. data/lib/active_record/attribute_methods/dirty.rb +113 -74
  42. data/lib/active_record/attribute_methods/primary_key.rb +106 -77
  43. data/lib/active_record/attribute_methods/query.rb +8 -5
  44. data/lib/active_record/attribute_methods/read.rb +63 -114
  45. data/lib/active_record/attribute_methods/serialization.rb +60 -90
  46. data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -43
  47. data/lib/active_record/attribute_methods/write.rb +43 -45
  48. data/lib/active_record/attribute_methods.rb +366 -149
  49. data/lib/active_record/attributes.rb +266 -0
  50. data/lib/active_record/autosave_association.rb +312 -225
  51. data/lib/active_record/base.rb +114 -505
  52. data/lib/active_record/callbacks.rb +145 -67
  53. data/lib/active_record/coders/json.rb +15 -0
  54. data/lib/active_record/coders/yaml_column.rb +32 -23
  55. data/lib/active_record/collection_cache_key.rb +53 -0
  56. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +883 -284
  57. data/lib/active_record/connection_adapters/abstract/database_limits.rb +16 -2
  58. data/lib/active_record/connection_adapters/abstract/database_statements.rb +350 -200
  59. data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -27
  60. data/lib/active_record/connection_adapters/abstract/quoting.rb +150 -65
  61. data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
  62. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +146 -0
  63. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +477 -284
  64. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +95 -0
  65. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1100 -310
  66. data/lib/active_record/connection_adapters/abstract/transaction.rb +283 -0
  67. data/lib/active_record/connection_adapters/abstract_adapter.rb +450 -118
  68. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +657 -446
  69. data/lib/active_record/connection_adapters/column.rb +50 -255
  70. data/lib/active_record/connection_adapters/connection_specification.rb +287 -0
  71. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +33 -0
  72. data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
  73. data/lib/active_record/connection_adapters/mysql/database_statements.rb +140 -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 +44 -0
  76. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +73 -0
  77. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +87 -0
  78. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +80 -0
  79. data/lib/active_record/connection_adapters/mysql/schema_statements.rb +148 -0
  80. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +35 -0
  81. data/lib/active_record/connection_adapters/mysql2_adapter.rb +59 -210
  82. data/lib/active_record/connection_adapters/postgresql/column.rb +44 -0
  83. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +163 -0
  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 +92 -0
  86. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +56 -0
  87. data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
  90. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
  91. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
  92. data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
  93. data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
  94. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
  95. data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
  96. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
  97. data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
  100. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
  103. data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +111 -0
  104. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +23 -0
  105. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
  106. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
  107. data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
  108. data/lib/active_record/connection_adapters/postgresql/quoting.rb +168 -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 +65 -0
  111. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +206 -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 +774 -0
  114. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +39 -0
  115. data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
  116. data/lib/active_record/connection_adapters/postgresql_adapter.rb +620 -1080
  117. data/lib/active_record/connection_adapters/schema_cache.rb +85 -36
  118. data/lib/active_record/connection_adapters/sql_type_metadata.rb +34 -0
  119. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
  120. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +67 -0
  121. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
  122. data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
  123. data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
  124. data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +106 -0
  125. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +545 -27
  126. data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
  127. data/lib/active_record/connection_handling.rb +145 -0
  128. data/lib/active_record/core.rb +559 -0
  129. data/lib/active_record/counter_cache.rb +200 -105
  130. data/lib/active_record/define_callbacks.rb +22 -0
  131. data/lib/active_record/dynamic_matchers.rb +107 -69
  132. data/lib/active_record/enum.rb +244 -0
  133. data/lib/active_record/errors.rb +245 -60
  134. data/lib/active_record/explain.rb +35 -71
  135. data/lib/active_record/explain_registry.rb +32 -0
  136. data/lib/active_record/explain_subscriber.rb +18 -9
  137. data/lib/active_record/fixture_set/file.rb +82 -0
  138. data/lib/active_record/fixtures.rb +418 -275
  139. data/lib/active_record/gem_version.rb +17 -0
  140. data/lib/active_record/inheritance.rb +209 -100
  141. data/lib/active_record/integration.rb +116 -21
  142. data/lib/active_record/internal_metadata.rb +45 -0
  143. data/lib/active_record/legacy_yaml_adapter.rb +48 -0
  144. data/lib/active_record/locale/en.yml +9 -1
  145. data/lib/active_record/locking/optimistic.rb +107 -94
  146. data/lib/active_record/locking/pessimistic.rb +20 -8
  147. data/lib/active_record/log_subscriber.rb +99 -34
  148. data/lib/active_record/migration/command_recorder.rb +199 -64
  149. data/lib/active_record/migration/compatibility.rb +217 -0
  150. data/lib/active_record/migration/join_table.rb +17 -0
  151. data/lib/active_record/migration.rb +893 -296
  152. data/lib/active_record/model_schema.rb +328 -175
  153. data/lib/active_record/nested_attributes.rb +338 -242
  154. data/lib/active_record/no_touching.rb +58 -0
  155. data/lib/active_record/null_relation.rb +68 -0
  156. data/lib/active_record/persistence.rb +557 -170
  157. data/lib/active_record/query_cache.rb +14 -43
  158. data/lib/active_record/querying.rb +36 -24
  159. data/lib/active_record/railtie.rb +147 -52
  160. data/lib/active_record/railties/console_sandbox.rb +5 -4
  161. data/lib/active_record/railties/controller_runtime.rb +13 -6
  162. data/lib/active_record/railties/databases.rake +206 -488
  163. data/lib/active_record/readonly_attributes.rb +4 -6
  164. data/lib/active_record/reflection.rb +734 -228
  165. data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
  166. data/lib/active_record/relation/batches.rb +249 -52
  167. data/lib/active_record/relation/calculations.rb +330 -284
  168. data/lib/active_record/relation/delegation.rb +135 -37
  169. data/lib/active_record/relation/finder_methods.rb +450 -287
  170. data/lib/active_record/relation/from_clause.rb +26 -0
  171. data/lib/active_record/relation/merger.rb +193 -0
  172. data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
  173. data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
  174. data/lib/active_record/relation/predicate_builder/base_handler.rb +19 -0
  175. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +20 -0
  176. data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
  177. data/lib/active_record/relation/predicate_builder/range_handler.rb +42 -0
  178. data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
  179. data/lib/active_record/relation/predicate_builder.rb +132 -43
  180. data/lib/active_record/relation/query_attribute.rb +45 -0
  181. data/lib/active_record/relation/query_methods.rb +1037 -221
  182. data/lib/active_record/relation/record_fetch_warning.rb +51 -0
  183. data/lib/active_record/relation/spawn_methods.rb +48 -151
  184. data/lib/active_record/relation/where_clause.rb +186 -0
  185. data/lib/active_record/relation/where_clause_factory.rb +34 -0
  186. data/lib/active_record/relation.rb +451 -359
  187. data/lib/active_record/result.rb +129 -20
  188. data/lib/active_record/runtime_registry.rb +24 -0
  189. data/lib/active_record/sanitization.rb +164 -136
  190. data/lib/active_record/schema.rb +31 -19
  191. data/lib/active_record/schema_dumper.rb +154 -107
  192. data/lib/active_record/schema_migration.rb +56 -0
  193. data/lib/active_record/scoping/default.rb +108 -98
  194. data/lib/active_record/scoping/named.rb +125 -112
  195. data/lib/active_record/scoping.rb +77 -123
  196. data/lib/active_record/secure_token.rb +40 -0
  197. data/lib/active_record/serialization.rb +10 -6
  198. data/lib/active_record/statement_cache.rb +121 -0
  199. data/lib/active_record/store.rb +175 -16
  200. data/lib/active_record/suppressor.rb +61 -0
  201. data/lib/active_record/table_metadata.rb +82 -0
  202. data/lib/active_record/tasks/database_tasks.rb +337 -0
  203. data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
  204. data/lib/active_record/tasks/postgresql_database_tasks.rb +143 -0
  205. data/lib/active_record/tasks/sqlite_database_tasks.rb +83 -0
  206. data/lib/active_record/timestamp.rb +80 -41
  207. data/lib/active_record/touch_later.rb +64 -0
  208. data/lib/active_record/transactions.rb +240 -119
  209. data/lib/active_record/translation.rb +2 -0
  210. data/lib/active_record/type/adapter_specific_registry.rb +136 -0
  211. data/lib/active_record/type/date.rb +9 -0
  212. data/lib/active_record/type/date_time.rb +9 -0
  213. data/lib/active_record/type/decimal_without_scale.rb +15 -0
  214. data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
  215. data/lib/active_record/type/internal/timezone.rb +17 -0
  216. data/lib/active_record/type/json.rb +30 -0
  217. data/lib/active_record/type/serialized.rb +71 -0
  218. data/lib/active_record/type/text.rb +11 -0
  219. data/lib/active_record/type/time.rb +21 -0
  220. data/lib/active_record/type/type_map.rb +62 -0
  221. data/lib/active_record/type/unsigned_integer.rb +17 -0
  222. data/lib/active_record/type.rb +79 -0
  223. data/lib/active_record/type_caster/connection.rb +33 -0
  224. data/lib/active_record/type_caster/map.rb +23 -0
  225. data/lib/active_record/type_caster.rb +9 -0
  226. data/lib/active_record/validations/absence.rb +25 -0
  227. data/lib/active_record/validations/associated.rb +35 -18
  228. data/lib/active_record/validations/length.rb +26 -0
  229. data/lib/active_record/validations/presence.rb +68 -0
  230. data/lib/active_record/validations/uniqueness.rb +133 -75
  231. data/lib/active_record/validations.rb +53 -43
  232. data/lib/active_record/version.rb +7 -7
  233. data/lib/active_record.rb +89 -57
  234. data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
  235. data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
  236. data/lib/rails/generators/active_record/migration/migration_generator.rb +61 -8
  237. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
  238. data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +46 -0
  239. data/lib/rails/generators/active_record/migration.rb +28 -8
  240. data/lib/rails/generators/active_record/model/model_generator.rb +23 -22
  241. data/lib/rails/generators/active_record/model/templates/model.rb.tt +13 -0
  242. data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
  243. data/lib/rails/generators/active_record.rb +10 -16
  244. metadata +141 -62
  245. data/examples/associations.png +0 -0
  246. data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
  247. data/lib/active_record/associations/join_helper.rb +0 -55
  248. data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
  249. data/lib/active_record/associations/preloader/collection_association.rb +0 -24
  250. data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
  251. data/lib/active_record/associations/preloader/has_many.rb +0 -17
  252. data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
  253. data/lib/active_record/associations/preloader/has_one.rb +0 -23
  254. data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
  255. data/lib/active_record/associations/preloader/singular_association.rb +0 -21
  256. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
  257. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
  258. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -441
  259. data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
  260. data/lib/active_record/dynamic_finder_match.rb +0 -68
  261. data/lib/active_record/dynamic_scope_match.rb +0 -23
  262. data/lib/active_record/fixtures/file.rb +0 -65
  263. data/lib/active_record/identity_map.rb +0 -162
  264. data/lib/active_record/observer.rb +0 -121
  265. data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
  266. data/lib/active_record/serializers/xml_serializer.rb +0 -203
  267. data/lib/active_record/session_store.rb +0 -360
  268. data/lib/active_record/test_case.rb +0 -73
  269. data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
  270. data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
  271. data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
  272. data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
  273. data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
  274. data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
  275. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,47 +1,134 @@
1
- require 'active_support/concern'
1
+ # frozen_string_literal: true
2
+
3
+ require "monitor"
2
4
 
3
5
  module ActiveRecord
4
6
  module ModelSchema
5
7
  extend ActiveSupport::Concern
6
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
+
7
105
  included do
8
- ##
9
- # :singleton-method:
10
- # Accessor for the prefix type that will be prepended to every primary key column name.
11
- # The options are :table_name and :table_name_with_underscore. If the first is specified,
12
- # the Product class will look for "productid" instead of "id" as the primary column. If the
13
- # latter is specified, the Product class will look for "product_id" instead of "id". Remember
14
- # that this is a global setting for all Active Records.
15
- cattr_accessor :primary_key_prefix_type, :instance_writer => false
16
- self.primary_key_prefix_type = nil
17
-
18
- ##
19
- # :singleton-method:
20
- # Accessor for the name of the prefix string to prepend to every table name. So if set
21
- # to "basecamp_", all table names will be named like "basecamp_projects", "basecamp_people",
22
- # etc. This is a convenient way of creating a namespace for tables in a shared database.
23
- # By default, the prefix is the empty string.
24
- #
25
- # If you are organising your models within modules you can add a prefix to the models within
26
- # a namespace by defining a singleton method in the parent module called table_name_prefix which
27
- # returns your chosen prefix.
28
- class_attribute :table_name_prefix, :instance_writer => false
29
- self.table_name_prefix = ""
30
-
31
- ##
32
- # :singleton-method:
33
- # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp",
34
- # "people_basecamp"). By default, the suffix is the empty string.
35
- class_attribute :table_name_suffix, :instance_writer => false
36
- self.table_name_suffix = ""
37
-
38
- ##
39
- # :singleton-method:
40
- # Indicates whether table names should be the pluralized versions of the corresponding class names.
41
- # If true, the default table name for a Product class will be +products+. If false, it would just be +product+.
42
- # See table_name for the full rules on table/class naming. This is true, by default.
43
- class_attribute :pluralize_table_names, :instance_writer => false
44
- self.pluralize_table_names = true
106
+ mattr_accessor :primary_key_prefix_type, instance_writer: false
107
+
108
+ class_attribute :table_name_prefix, instance_writer: false, default: ""
109
+ class_attribute :table_name_suffix, instance_writer: false, default: ""
110
+ class_attribute :schema_migrations_table_name, instance_accessor: false, default: "schema_migrations"
111
+ class_attribute :internal_metadata_table_name, instance_accessor: false, default: "ar_internal_metadata"
112
+ class_attribute :pluralize_table_names, instance_writer: false, default: true
113
+
114
+ self.protected_environments = ["production"]
115
+ self.inheritance_column = "type"
116
+ self.ignored_columns = [].freeze
117
+
118
+ delegate :type_for_attribute, to: :class
119
+
120
+ initialize_load_schema_monitor
121
+ end
122
+
123
+ # Derives the join table name for +first_table+ and +second_table+. The
124
+ # table names appear in alphabetical order. A common prefix is removed
125
+ # (useful for namespaced models like Music::Artist and Music::Record):
126
+ #
127
+ # artists, records => artists_records
128
+ # records, artists => artists_records
129
+ # music_artists, music_records => music_artists_records
130
+ def self.derive_join_table_name(first_table, second_table) # :nodoc:
131
+ [first_table.to_s, second_table.to_s].sort.join("\0").gsub(/^(.*_)(.+)\0\1(.+)/, '\1\2_\3').tr("\0", "_")
45
132
  end
46
133
 
47
134
  module ClassMethods
@@ -89,47 +176,29 @@ module ActiveRecord
89
176
  # class Mouse < ActiveRecord::Base
90
177
  # self.table_name = "mice"
91
178
  # end
92
- #
93
- # Alternatively, you can override the table_name method to define your
94
- # own computation. (Possibly using <tt>super</tt> to manipulate the default
95
- # table name.) Example:
96
- #
97
- # class Post < ActiveRecord::Base
98
- # def self.table_name
99
- # "special_" + super
100
- # end
101
- # end
102
- # Post.table_name # => "special_posts"
103
179
  def table_name
104
180
  reset_table_name unless defined?(@table_name)
105
181
  @table_name
106
182
  end
107
183
 
108
- def original_table_name #:nodoc:
109
- deprecated_original_property_getter :table_name
110
- end
111
-
112
184
  # Sets the table name explicitly. Example:
113
185
  #
114
186
  # class Project < ActiveRecord::Base
115
187
  # self.table_name = "project"
116
188
  # end
117
- #
118
- # You can also just define your own <tt>self.table_name</tt> method; see
119
- # the documentation for ActiveRecord::Base#table_name.
120
189
  def table_name=(value)
121
- @original_table_name = @table_name if defined?(@table_name)
122
- @table_name = value && value.to_s
123
- @quoted_table_name = nil
124
- @arel_table = nil
125
- @relation = Relation.new(self, arel_table)
126
- end
190
+ value = value && value.to_s
191
+
192
+ if defined?(@table_name)
193
+ return if value == @table_name
194
+ reset_column_information if connected?
195
+ end
127
196
 
128
- def set_table_name(value = nil, &block) #:nodoc:
129
- deprecated_property_setter :table_name, value, block
197
+ @table_name = value
130
198
  @quoted_table_name = nil
131
199
  @arel_table = nil
132
- @relation = Relation.new(self, arel_table)
200
+ @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
201
+ @predicate_builder = nil
133
202
  end
134
203
 
135
204
  # Returns a quoted version of the table name, used to construct SQL statements.
@@ -139,45 +208,71 @@ module ActiveRecord
139
208
 
140
209
  # Computes the table name, (re)sets it internally, and returns it.
141
210
  def reset_table_name #:nodoc:
142
- if abstract_class?
143
- self.table_name = if superclass == Base || superclass.abstract_class?
144
- nil
145
- else
146
- superclass.table_name
147
- end
211
+ self.table_name = if abstract_class?
212
+ superclass == Base ? nil : superclass.table_name
148
213
  elsif superclass.abstract_class?
149
- self.table_name = superclass.table_name || compute_table_name
214
+ superclass.table_name || compute_table_name
150
215
  else
151
- self.table_name = compute_table_name
216
+ compute_table_name
152
217
  end
153
218
  end
154
219
 
155
220
  def full_table_name_prefix #:nodoc:
156
- (parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
221
+ (parents.detect { |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix
157
222
  end
158
223
 
159
- # The name of the column containing the object's class when Single Table Inheritance is used
160
- def inheritance_column
161
- if self == Base
162
- (@inheritance_column ||= nil) || 'type'
224
+ def full_table_name_suffix #:nodoc:
225
+ (parents.detect { |p| p.respond_to?(:table_name_suffix) } || self).table_name_suffix
226
+ end
227
+
228
+ # The array of names of environments where destructive actions should be prohibited. By default,
229
+ # the value is <tt>["production"]</tt>.
230
+ def protected_environments
231
+ if defined?(@protected_environments)
232
+ @protected_environments
163
233
  else
164
- (@inheritance_column ||= nil) || superclass.inheritance_column
234
+ superclass.protected_environments
165
235
  end
166
236
  end
167
237
 
168
- def original_inheritance_column #:nodoc:
169
- deprecated_original_property_getter :inheritance_column
238
+ # Sets an array of names of environments where destructive actions should be prohibited.
239
+ def protected_environments=(environments)
240
+ @protected_environments = environments.map(&:to_s)
241
+ end
242
+
243
+ # Defines the name of the table column which will store the class name on single-table
244
+ # inheritance situations.
245
+ #
246
+ # The default inheritance column name is +type+, which means it's a
247
+ # reserved word inside Active Record. To be able to use single-table
248
+ # inheritance with another column name, or to use the column +type+ in
249
+ # your own model for something else, you can set +inheritance_column+:
250
+ #
251
+ # self.inheritance_column = 'zoink'
252
+ def inheritance_column
253
+ (@inheritance_column ||= nil) || superclass.inheritance_column
170
254
  end
171
255
 
172
256
  # Sets the value of inheritance_column
173
257
  def inheritance_column=(value)
174
- @original_inheritance_column = inheritance_column
175
- @inheritance_column = value.to_s
258
+ @inheritance_column = value.to_s
176
259
  @explicit_inheritance_column = true
177
260
  end
178
261
 
179
- def set_inheritance_column(value = nil, &block) #:nodoc:
180
- deprecated_property_setter :inheritance_column, value, block
262
+ # The list of columns names the model should ignore. Ignored columns won't have attribute
263
+ # accessors defined, and won't be referenced in SQL queries.
264
+ def ignored_columns
265
+ if defined?(@ignored_columns)
266
+ @ignored_columns
267
+ else
268
+ superclass.ignored_columns
269
+ end
270
+ end
271
+
272
+ # Sets the columns names the model should ignore. Ignored columns won't have attribute
273
+ # accessors defined, and won't be referenced in SQL queries.
274
+ def ignored_columns=(columns)
275
+ @ignored_columns = columns.map(&:to_s)
181
276
  end
182
277
 
183
278
  def sequence_name
@@ -188,20 +283,17 @@ module ActiveRecord
188
283
  end
189
284
  end
190
285
 
191
- def original_sequence_name #:nodoc:
192
- deprecated_original_property_getter :sequence_name
193
- end
194
-
195
286
  def reset_sequence_name #:nodoc:
196
- self.sequence_name = connection.default_sequence_name(table_name, primary_key)
287
+ @explicit_sequence_name = false
288
+ @sequence_name = connection.default_sequence_name(table_name, primary_key)
197
289
  end
198
290
 
199
291
  # Sets the name of the sequence to use when generating ids to the given
200
- # value, or (if the value is nil or false) to the value returned by the
292
+ # value, or (if the value is +nil+ or +false+) to the value returned by the
201
293
  # given block. This is required for Oracle and is useful for any
202
294
  # database which relies on sequences for primary key generation.
203
295
  #
204
- # If a sequence name is not explicitly set when using Oracle or Firebird,
296
+ # If a sequence name is not explicitly set when using Oracle,
205
297
  # it will default to the commonly used pattern of: #{table_name}_seq
206
298
  #
207
299
  # If a sequence name is not explicitly set when using PostgreSQL, it
@@ -211,61 +303,99 @@ module ActiveRecord
211
303
  # self.sequence_name = "projectseq" # default would have been "project_seq"
212
304
  # end
213
305
  def sequence_name=(value)
214
- @original_sequence_name = @sequence_name if defined?(@sequence_name)
215
306
  @sequence_name = value.to_s
307
+ @explicit_sequence_name = true
216
308
  end
217
309
 
218
- def set_sequence_name(value = nil, &block) #:nodoc:
219
- deprecated_property_setter :sequence_name, value, block
310
+ # Determines if the primary key values should be selected from their
311
+ # corresponding sequence before the insert statement.
312
+ def prefetch_primary_key?
313
+ connection.prefetch_primary_key?(table_name)
314
+ end
315
+
316
+ # Returns the next value that will be used as the primary key on
317
+ # an insert statement.
318
+ def next_sequence_value
319
+ connection.next_sequence_value(sequence_name)
220
320
  end
221
321
 
222
322
  # Indicates whether the table associated with this class exists
223
323
  def table_exists?
224
- connection.schema_cache.table_exists?(table_name)
324
+ connection.schema_cache.data_source_exists?(table_name)
225
325
  end
226
326
 
227
- # Returns an array of column objects for the table associated with this class.
228
- def columns
229
- @columns ||= connection.schema_cache.columns[table_name].map do |col|
230
- col = col.dup
231
- col.primary = (col.name == primary_key)
232
- col
327
+ def attributes_builder # :nodoc:
328
+ unless defined?(@attributes_builder) && @attributes_builder
329
+ defaults = _default_attributes.except(*(column_names - [primary_key]))
330
+ @attributes_builder = ActiveModel::AttributeSet::Builder.new(attribute_types, defaults)
233
331
  end
332
+ @attributes_builder
333
+ end
334
+
335
+ def columns_hash # :nodoc:
336
+ load_schema
337
+ @columns_hash
234
338
  end
235
339
 
236
- # Returns a hash of column objects for the table associated with this class.
237
- def columns_hash
238
- @columns_hash ||= Hash[columns.map { |c| [c.name, c] }]
340
+ def columns
341
+ load_schema
342
+ @columns ||= columns_hash.values
343
+ end
344
+
345
+ def attribute_types # :nodoc:
346
+ load_schema
347
+ @attribute_types ||= Hash.new(Type.default_value)
348
+ end
349
+
350
+ def yaml_encoder # :nodoc:
351
+ @yaml_encoder ||= ActiveModel::AttributeSet::YAMLEncoder.new(attribute_types)
352
+ end
353
+
354
+ # Returns the type of the attribute with the given name, after applying
355
+ # all modifiers. This method is the only valid source of information for
356
+ # anything related to the types of a model's attributes. This method will
357
+ # access the database and load the model's schema if it is required.
358
+ #
359
+ # The return value of this method will implement the interface described
360
+ # by ActiveModel::Type::Value (though the object itself may not subclass
361
+ # it).
362
+ #
363
+ # +attr_name+ The name of the attribute to retrieve the type for. Must be
364
+ # a string or a symbol.
365
+ def type_for_attribute(attr_name, &block)
366
+ attr_name = attr_name.to_s
367
+ if block
368
+ attribute_types.fetch(attr_name, &block)
369
+ else
370
+ attribute_types[attr_name]
371
+ end
239
372
  end
240
373
 
241
374
  # Returns a hash where the keys are column names and the values are
242
- # default values when instantiating the AR object for this table.
375
+ # default values when instantiating the Active Record object for this table.
243
376
  def column_defaults
244
- @column_defaults ||= Hash[columns.map { |c| [c.name, c.default] }]
377
+ load_schema
378
+ @column_defaults ||= _default_attributes.deep_dup.to_hash
379
+ end
380
+
381
+ def _default_attributes # :nodoc:
382
+ load_schema
383
+ @default_attributes ||= ActiveModel::AttributeSet.new({})
245
384
  end
246
385
 
247
386
  # Returns an array of column names as strings.
248
387
  def column_names
249
- @column_names ||= columns.map { |column| column.name }
388
+ @column_names ||= columns.map(&:name)
250
389
  end
251
390
 
252
391
  # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
253
392
  # and columns used for single table inheritance have been removed.
254
393
  def content_columns
255
- @content_columns ||= columns.reject { |c| c.primary || c.name =~ /(_id|_count)$/ || c.name == inheritance_column }
256
- end
257
-
258
- # Returns a hash of all the methods added to query each of the columns in the table with the name of the method as the key
259
- # and true as the value. This makes it possible to do O(1) lookups in respond_to? to check if a given method for attribute
260
- # is available.
261
- def column_methods_hash #:nodoc:
262
- @dynamic_methods_hash ||= column_names.inject(Hash.new(false)) do |methods, attr|
263
- attr_name = attr.to_s
264
- methods[attr.to_sym] = attr_name
265
- methods["#{attr}=".to_sym] = attr_name
266
- methods["#{attr}?".to_sym] = attr_name
267
- methods["#{attr}_before_type_cast".to_sym] = attr_name
268
- methods
394
+ @content_columns ||= columns.reject do |c|
395
+ c.name == primary_key ||
396
+ c.name == inheritance_column ||
397
+ c.name.end_with?("_id") ||
398
+ c.name.end_with?("_count")
269
399
  end
270
400
  end
271
401
 
@@ -276,7 +406,7 @@ module ActiveRecord
276
406
  # when just after creating a table you want to populate it with some default
277
407
  # values, eg:
278
408
  #
279
- # class CreateJobLevels < ActiveRecord::Migration
409
+ # class CreateJobLevels < ActiveRecord::Migration[5.0]
280
410
  # def up
281
411
  # create_table :job_levels do |t|
282
412
  # t.integer :id
@@ -287,7 +417,7 @@ module ActiveRecord
287
417
  #
288
418
  # JobLevel.reset_column_information
289
419
  # %w{assistant executive manager director}.each do |type|
290
- # JobLevel.create(:name => type)
420
+ # JobLevel.create(name: type)
291
421
  # end
292
422
  # end
293
423
  #
@@ -297,72 +427,95 @@ module ActiveRecord
297
427
  # end
298
428
  def reset_column_information
299
429
  connection.clear_cache!
300
- undefine_attribute_methods
301
- connection.schema_cache.clear_table_cache!(table_name) if table_exists?
430
+ ([self] + descendants).each(&:undefine_attribute_methods)
431
+ connection.schema_cache.clear_data_source_cache!(table_name)
302
432
 
303
- @column_names = @content_columns = @column_defaults = @columns = @columns_hash = nil
304
- @dynamic_methods_hash = nil
305
- @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
306
- @arel_engine = @relation = nil
433
+ reload_schema_from_cache
434
+ initialize_find_by_cache
307
435
  end
308
436
 
309
- def clear_cache! # :nodoc:
310
- connection.schema_cache.clear!
311
- end
437
+ protected
438
+
439
+ def initialize_load_schema_monitor
440
+ @load_schema_monitor = Monitor.new
441
+ end
312
442
 
313
443
  private
314
444
 
315
- # Guesses the table name, but does not decorate it with prefix and suffix information.
316
- def undecorated_table_name(class_name = base_class.name)
317
- table_name = class_name.to_s.demodulize.underscore
318
- table_name = table_name.pluralize if pluralize_table_names
319
- table_name
320
- end
445
+ def inherited(child_class)
446
+ super
447
+ child_class.initialize_load_schema_monitor
448
+ end
321
449
 
322
- # Computes and returns a table name according to default conventions.
323
- def compute_table_name
324
- base = base_class
325
- if self == base
326
- # Nested classes are prefixed with singular parent table name.
327
- if parent < ActiveRecord::Base && !parent.abstract_class?
328
- contained = parent.table_name
329
- contained = contained.singularize if parent.pluralize_table_names
330
- contained += '_'
331
- end
332
- "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{table_name_suffix}"
333
- else
334
- # STI subclasses always use their superclass' table.
335
- base.table_name
450
+ def schema_loaded?
451
+ defined?(@schema_loaded) && @schema_loaded
336
452
  end
337
- end
338
453
 
339
- def deprecated_property_setter(property, value, block)
340
- if block
341
- ActiveSupport::Deprecation.warn(
342
- "Calling set_#{property} is deprecated. If you need to lazily evaluate " \
343
- "the #{property}, define your own `self.#{property}` class method. You can use `super` " \
344
- "to get the default #{property} where you would have called `original_#{property}`."
345
- )
454
+ def load_schema
455
+ return if schema_loaded?
456
+ @load_schema_monitor.synchronize do
457
+ return if defined?(@columns_hash) && @columns_hash
346
458
 
347
- define_attr_method property, value, false, &block
348
- else
349
- ActiveSupport::Deprecation.warn(
350
- "Calling set_#{property} is deprecated. Please use `self.#{property} = 'the_name'` instead."
351
- )
459
+ load_schema!
352
460
 
353
- define_attr_method property, value, false
461
+ @schema_loaded = true
462
+ end
354
463
  end
355
- end
356
464
 
357
- def deprecated_original_property_getter(property)
358
- ActiveSupport::Deprecation.warn("original_#{property} is deprecated. Define self.#{property} and call super instead.")
465
+ def load_schema!
466
+ @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
467
+ @columns_hash.each do |name, column|
468
+ define_attribute(
469
+ name,
470
+ connection.lookup_cast_type_from_column(column),
471
+ default: column.default,
472
+ user_provided_default: false
473
+ )
474
+ end
475
+ end
359
476
 
360
- if !instance_variable_defined?("@original_#{property}") && respond_to?("reset_#{property}")
361
- send("reset_#{property}")
362
- else
363
- instance_variable_get("@original_#{property}")
477
+ def reload_schema_from_cache
478
+ @arel_table = nil
479
+ @column_names = nil
480
+ @attribute_types = nil
481
+ @content_columns = nil
482
+ @default_attributes = nil
483
+ @column_defaults = nil
484
+ @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
485
+ @attributes_builder = nil
486
+ @columns = nil
487
+ @columns_hash = nil
488
+ @schema_loaded = false
489
+ @attribute_names = nil
490
+ @yaml_encoder = nil
491
+ direct_descendants.each do |descendant|
492
+ descendant.send(:reload_schema_from_cache)
493
+ end
494
+ end
495
+
496
+ # Guesses the table name, but does not decorate it with prefix and suffix information.
497
+ def undecorated_table_name(class_name = base_class.name)
498
+ table_name = class_name.to_s.demodulize.underscore
499
+ pluralize_table_names ? table_name.pluralize : table_name
500
+ end
501
+
502
+ # Computes and returns a table name according to default conventions.
503
+ def compute_table_name
504
+ base = base_class
505
+ if self == base
506
+ # Nested classes are prefixed with singular parent table name.
507
+ if parent < Base && !parent.abstract_class?
508
+ contained = parent.table_name
509
+ contained = contained.singularize if parent.pluralize_table_names
510
+ contained += "_"
511
+ end
512
+
513
+ "#{full_table_name_prefix}#{contained}#{undecorated_table_name(name)}#{full_table_name_suffix}"
514
+ else
515
+ # STI subclasses always use their superclass' table.
516
+ base.table_name
517
+ end
364
518
  end
365
- end
366
519
  end
367
520
  end
368
521
  end