activerecord 4.2.11.1 → 5.0.0

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

Potentially problematic release.


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

Files changed (246) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +1282 -1195
  3. data/MIT-LICENSE +2 -2
  4. data/README.rdoc +7 -8
  5. data/examples/performance.rb +2 -3
  6. data/examples/simple.rb +0 -1
  7. data/lib/active_record.rb +8 -4
  8. data/lib/active_record/aggregations.rb +35 -24
  9. data/lib/active_record/association_relation.rb +3 -3
  10. data/lib/active_record/associations.rb +317 -209
  11. data/lib/active_record/associations/alias_tracker.rb +19 -16
  12. data/lib/active_record/associations/association.rb +11 -9
  13. data/lib/active_record/associations/association_scope.rb +73 -102
  14. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  15. data/lib/active_record/associations/builder/association.rb +28 -34
  16. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  17. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  18. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  19. data/lib/active_record/associations/builder/has_many.rb +4 -4
  20. data/lib/active_record/associations/builder/has_one.rb +11 -6
  21. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  22. data/lib/active_record/associations/collection_association.rb +49 -41
  23. data/lib/active_record/associations/collection_proxy.rb +67 -27
  24. data/lib/active_record/associations/foreign_association.rb +1 -1
  25. data/lib/active_record/associations/has_many_association.rb +20 -71
  26. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  27. data/lib/active_record/associations/has_one_association.rb +12 -5
  28. data/lib/active_record/associations/join_dependency.rb +29 -19
  29. data/lib/active_record/associations/join_dependency/join_association.rb +16 -10
  30. data/lib/active_record/associations/preloader.rb +14 -4
  31. data/lib/active_record/associations/preloader/association.rb +46 -52
  32. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  33. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  34. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  35. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  36. data/lib/active_record/associations/singular_association.rb +7 -1
  37. data/lib/active_record/associations/through_association.rb +11 -3
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  40. data/lib/active_record/attribute_assignment.rb +19 -140
  41. data/lib/active_record/attribute_decorators.rb +6 -5
  42. data/lib/active_record/attribute_methods.rb +76 -47
  43. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  44. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  45. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  46. data/lib/active_record/attribute_methods/query.rb +2 -2
  47. data/lib/active_record/attribute_methods/read.rb +31 -59
  48. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  49. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  50. data/lib/active_record/attribute_methods/write.rb +13 -37
  51. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attribute_set/builder.rb +6 -4
  54. data/lib/active_record/attributes.rb +199 -81
  55. data/lib/active_record/autosave_association.rb +49 -16
  56. data/lib/active_record/base.rb +32 -23
  57. data/lib/active_record/callbacks.rb +39 -43
  58. data/lib/active_record/coders/json.rb +1 -1
  59. data/lib/active_record/coders/yaml_column.rb +20 -8
  60. data/lib/active_record/collection_cache_key.rb +40 -0
  61. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  62. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  63. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  64. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  65. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -10
  66. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  67. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  68. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  69. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  70. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +380 -141
  71. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  72. data/lib/active_record/connection_adapters/abstract_adapter.rb +141 -59
  73. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +401 -370
  74. data/lib/active_record/connection_adapters/column.rb +28 -43
  75. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  76. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  77. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  78. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  79. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  80. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  83. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  84. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  85. data/lib/active_record/connection_adapters/mysql2_adapter.rb +29 -166
  86. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  87. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  88. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  89. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  90. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -57
  91. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  92. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  93. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  94. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  95. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  96. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  97. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  98. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  99. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  100. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  101. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  102. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  103. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  104. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  105. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  106. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  107. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  108. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  109. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  110. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  111. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  112. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  113. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  114. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  115. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  116. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  117. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  118. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +149 -192
  119. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  120. data/lib/active_record/connection_handling.rb +37 -14
  121. data/lib/active_record/core.rb +89 -107
  122. data/lib/active_record/counter_cache.rb +13 -24
  123. data/lib/active_record/dynamic_matchers.rb +1 -20
  124. data/lib/active_record/enum.rb +113 -76
  125. data/lib/active_record/errors.rb +87 -48
  126. data/lib/active_record/explain_registry.rb +1 -1
  127. data/lib/active_record/explain_subscriber.rb +1 -1
  128. data/lib/active_record/fixture_set/file.rb +26 -5
  129. data/lib/active_record/fixtures.rb +76 -40
  130. data/lib/active_record/gem_version.rb +4 -4
  131. data/lib/active_record/inheritance.rb +32 -40
  132. data/lib/active_record/integration.rb +4 -4
  133. data/lib/active_record/internal_metadata.rb +56 -0
  134. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  135. data/lib/active_record/locale/en.yml +3 -2
  136. data/lib/active_record/locking/optimistic.rb +15 -15
  137. data/lib/active_record/locking/pessimistic.rb +1 -1
  138. data/lib/active_record/log_subscriber.rb +43 -21
  139. data/lib/active_record/migration.rb +363 -133
  140. data/lib/active_record/migration/command_recorder.rb +59 -18
  141. data/lib/active_record/migration/compatibility.rb +126 -0
  142. data/lib/active_record/model_schema.rb +129 -41
  143. data/lib/active_record/nested_attributes.rb +58 -29
  144. data/lib/active_record/null_relation.rb +16 -8
  145. data/lib/active_record/persistence.rb +121 -80
  146. data/lib/active_record/query_cache.rb +15 -18
  147. data/lib/active_record/querying.rb +10 -9
  148. data/lib/active_record/railtie.rb +23 -16
  149. data/lib/active_record/railties/controller_runtime.rb +1 -1
  150. data/lib/active_record/railties/databases.rake +69 -46
  151. data/lib/active_record/readonly_attributes.rb +1 -1
  152. data/lib/active_record/reflection.rb +282 -115
  153. data/lib/active_record/relation.rb +176 -116
  154. data/lib/active_record/relation/batches.rb +139 -34
  155. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  156. data/lib/active_record/relation/calculations.rb +79 -108
  157. data/lib/active_record/relation/delegation.rb +7 -20
  158. data/lib/active_record/relation/finder_methods.rb +163 -81
  159. data/lib/active_record/relation/from_clause.rb +32 -0
  160. data/lib/active_record/relation/merger.rb +16 -42
  161. data/lib/active_record/relation/predicate_builder.rb +120 -107
  162. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
  163. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  164. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  165. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  166. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  167. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  168. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  169. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  170. data/lib/active_record/relation/query_attribute.rb +19 -0
  171. data/lib/active_record/relation/query_methods.rb +308 -244
  172. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  173. data/lib/active_record/relation/spawn_methods.rb +4 -7
  174. data/lib/active_record/relation/where_clause.rb +174 -0
  175. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  176. data/lib/active_record/result.rb +4 -3
  177. data/lib/active_record/runtime_registry.rb +1 -1
  178. data/lib/active_record/sanitization.rb +95 -66
  179. data/lib/active_record/schema.rb +26 -22
  180. data/lib/active_record/schema_dumper.rb +62 -38
  181. data/lib/active_record/schema_migration.rb +11 -14
  182. data/lib/active_record/scoping.rb +32 -15
  183. data/lib/active_record/scoping/default.rb +23 -9
  184. data/lib/active_record/scoping/named.rb +49 -28
  185. data/lib/active_record/secure_token.rb +38 -0
  186. data/lib/active_record/serialization.rb +2 -4
  187. data/lib/active_record/statement_cache.rb +16 -14
  188. data/lib/active_record/store.rb +8 -3
  189. data/lib/active_record/suppressor.rb +58 -0
  190. data/lib/active_record/table_metadata.rb +68 -0
  191. data/lib/active_record/tasks/database_tasks.rb +57 -43
  192. data/lib/active_record/tasks/mysql_database_tasks.rb +6 -14
  193. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  194. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  195. data/lib/active_record/timestamp.rb +20 -9
  196. data/lib/active_record/touch_later.rb +58 -0
  197. data/lib/active_record/transactions.rb +138 -56
  198. data/lib/active_record/type.rb +66 -17
  199. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  200. data/lib/active_record/type/date.rb +2 -45
  201. data/lib/active_record/type/date_time.rb +2 -49
  202. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  203. data/lib/active_record/type/internal/timezone.rb +15 -0
  204. data/lib/active_record/type/serialized.rb +15 -14
  205. data/lib/active_record/type/time.rb +10 -16
  206. data/lib/active_record/type/type_map.rb +4 -4
  207. data/lib/active_record/type_caster.rb +7 -0
  208. data/lib/active_record/type_caster/connection.rb +29 -0
  209. data/lib/active_record/type_caster/map.rb +19 -0
  210. data/lib/active_record/validations.rb +33 -32
  211. data/lib/active_record/validations/absence.rb +23 -0
  212. data/lib/active_record/validations/associated.rb +10 -3
  213. data/lib/active_record/validations/length.rb +24 -0
  214. data/lib/active_record/validations/presence.rb +11 -12
  215. data/lib/active_record/validations/uniqueness.rb +30 -29
  216. data/lib/rails/generators/active_record/migration.rb +7 -0
  217. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  218. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  219. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  220. data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
  221. data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
  222. data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
  223. metadata +59 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
  225. data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
  226. data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
  227. data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
  228. data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
  229. data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
  230. data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
  231. data/lib/active_record/serializers/xml_serializer.rb +0 -193
  232. data/lib/active_record/type/big_integer.rb +0 -13
  233. data/lib/active_record/type/binary.rb +0 -50
  234. data/lib/active_record/type/boolean.rb +0 -31
  235. data/lib/active_record/type/decimal.rb +0 -64
  236. data/lib/active_record/type/decimal_without_scale.rb +0 -11
  237. data/lib/active_record/type/decorator.rb +0 -14
  238. data/lib/active_record/type/float.rb +0 -19
  239. data/lib/active_record/type/integer.rb +0 -59
  240. data/lib/active_record/type/mutable.rb +0 -16
  241. data/lib/active_record/type/numeric.rb +0 -36
  242. data/lib/active_record/type/string.rb +0 -40
  243. data/lib/active_record/type/text.rb +0 -11
  244. data/lib/active_record/type/time_value.rb +0 -38
  245. data/lib/active_record/type/unsigned_integer.rb +0 -15
  246. data/lib/active_record/type/value.rb +0 -110
@@ -5,15 +5,36 @@ module ActiveRecord
5
5
  # knows how to invert the following commands:
6
6
  #
7
7
  # * add_column
8
+ # * add_foreign_key
8
9
  # * add_index
10
+ # * add_reference
9
11
  # * add_timestamps
10
- # * create_table
12
+ # * change_column
13
+ # * change_column_default (must supply a :from and :to option)
14
+ # * change_column_null
11
15
  # * create_join_table
16
+ # * create_table
17
+ # * disable_extension
18
+ # * drop_join_table
19
+ # * drop_table (must supply a block)
20
+ # * enable_extension
21
+ # * remove_column (must supply a type)
22
+ # * remove_columns (must specify at least one column name or more)
23
+ # * remove_foreign_key (must supply a second table)
24
+ # * remove_index
25
+ # * remove_reference
12
26
  # * remove_timestamps
13
27
  # * rename_column
14
28
  # * rename_index
15
29
  # * rename_table
16
30
  class CommandRecorder
31
+ ReversibleAndIrreversibleMethods = [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
32
+ :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
33
+ :change_column_default, :add_reference, :remove_reference, :transaction,
34
+ :drop_join_table, :drop_table, :execute_block, :enable_extension, :disable_extension,
35
+ :change_column, :execute, :remove_columns, :change_column_null,
36
+ :add_foreign_key, :remove_foreign_key
37
+ ]
17
38
  include JoinTable
18
39
 
19
40
  attr_accessor :commands, :delegate, :reverting
@@ -41,7 +62,7 @@ module ActiveRecord
41
62
  @reverting = !@reverting
42
63
  end
43
64
 
44
- # record +command+. +command+ should be a method name and arguments.
65
+ # Record +command+. +command+ should be a method name and arguments.
45
66
  # For example:
46
67
  #
47
68
  # recorder.record(:method_name, [:arg1, :arg2])
@@ -62,7 +83,12 @@ module ActiveRecord
62
83
  # invert the +command+.
63
84
  def inverse_of(command, args, &block)
64
85
  method = :"invert_#{command}"
65
- raise IrreversibleMigration unless respond_to?(method, true)
86
+ raise IrreversibleMigration, <<-MSG.strip_heredoc unless respond_to?(method, true)
87
+ This migration uses #{command}, which is not automatically reversible.
88
+ To make the migration reversible you can either:
89
+ 1. Define #up and #down methods in place of the #change method.
90
+ 2. Use the #reversible method to define reversible behavior.
91
+ MSG
66
92
  send(method, args, &block)
67
93
  end
68
94
 
@@ -70,14 +96,7 @@ module ActiveRecord
70
96
  super || delegate.respond_to?(*args)
71
97
  end
72
98
 
73
- [:create_table, :create_join_table, :rename_table, :add_column, :remove_column,
74
- :rename_index, :rename_column, :add_index, :remove_index, :add_timestamps, :remove_timestamps,
75
- :change_column_default, :add_reference, :remove_reference, :transaction,
76
- :drop_join_table, :drop_table, :execute_block, :enable_extension,
77
- :change_column, :execute, :remove_columns, :change_column_null,
78
- :add_foreign_key, :remove_foreign_key
79
- # irreversible methods need to be here too
80
- ].each do |method|
99
+ ReversibleAndIrreversibleMethods.each do |method|
81
100
  class_eval <<-EOV, __FILE__, __LINE__ + 1
82
101
  def #{method}(*args, &block) # def create_table(*args, &block)
83
102
  record(:"#{method}", args, &block) # record(:create_table, args, &block)
@@ -151,19 +170,31 @@ module ActiveRecord
151
170
  end
152
171
 
153
172
  def invert_remove_index(args)
154
- table, options = *args
155
-
156
- unless options && options.is_a?(Hash) && options[:column]
157
- raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
173
+ table, options_or_column = *args
174
+ if (options = options_or_column).is_a?(Hash)
175
+ unless options[:column]
176
+ raise ActiveRecord::IrreversibleMigration, "remove_index is only reversible if given a :column option."
177
+ end
178
+ options = options.dup
179
+ [:add_index, [table, options.delete(:column), options]]
180
+ elsif (column = options_or_column).present?
181
+ [:add_index, [table, column]]
158
182
  end
159
-
160
- options = options.dup
161
- [:add_index, [table, options.delete(:column), options]]
162
183
  end
163
184
 
164
185
  alias :invert_add_belongs_to :invert_add_reference
165
186
  alias :invert_remove_belongs_to :invert_remove_reference
166
187
 
188
+ def invert_change_column_default(args)
189
+ table, column, options = *args
190
+
191
+ unless options && options.is_a?(Hash) && options.has_key?(:from) && options.has_key?(:to)
192
+ raise ActiveRecord::IrreversibleMigration, "change_column_default is only reversible if given a :from and :to option."
193
+ end
194
+
195
+ [:change_column_default, [table, column, from: options[:to], to: options[:from]]]
196
+ end
197
+
167
198
  def invert_change_column_null(args)
168
199
  args[2] = !args[2]
169
200
  [:change_column_null, args]
@@ -184,6 +215,16 @@ module ActiveRecord
184
215
  [:remove_foreign_key, [from_table, options]]
185
216
  end
186
217
 
218
+ def invert_remove_foreign_key(args)
219
+ from_table, to_table, remove_options = args
220
+ raise ActiveRecord::IrreversibleMigration, "remove_foreign_key is only reversible if given a second table" if to_table.nil? || to_table.is_a?(Hash)
221
+
222
+ reversed_args = [from_table, to_table]
223
+ reversed_args << remove_options if remove_options
224
+
225
+ [:add_foreign_key, reversed_args]
226
+ end
227
+
187
228
  # Forwards any missing method call to the \target.
188
229
  def method_missing(method, *args, &block)
189
230
  if @delegate.respond_to?(method)
@@ -0,0 +1,126 @@
1
+ module ActiveRecord
2
+ class Migration
3
+ module Compatibility # :nodoc: all
4
+ def self.find(version)
5
+ version = version.to_s
6
+ name = "V#{version.tr('.', '_')}"
7
+ unless const_defined?(name)
8
+ versions = constants.grep(/\AV[0-9_]+\z/).map { |s| s.to_s.delete('V').tr('_', '.').inspect }
9
+ raise ArgumentError, "Unknown migration version #{version.inspect}; expected one of #{versions.sort.join(', ')}"
10
+ end
11
+ const_get(name)
12
+ end
13
+
14
+ V5_0 = Current
15
+
16
+ module FourTwoShared
17
+ module TableDefinition
18
+ def references(*, **options)
19
+ options[:index] ||= false
20
+ super
21
+ end
22
+ alias :belongs_to :references
23
+
24
+ def timestamps(*, **options)
25
+ options[:null] = true if options[:null].nil?
26
+ super
27
+ end
28
+ end
29
+
30
+ def create_table(table_name, options = {})
31
+ if block_given?
32
+ super(table_name, options) do |t|
33
+ class << t
34
+ prepend TableDefinition
35
+ end
36
+ yield t
37
+ end
38
+ else
39
+ super
40
+ end
41
+ end
42
+
43
+ def change_table(table_name, options = {})
44
+ if block_given?
45
+ super(table_name, options) do |t|
46
+ class << t
47
+ prepend TableDefinition
48
+ end
49
+ yield t
50
+ end
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ def add_reference(*, **options)
57
+ options[:index] ||= false
58
+ super
59
+ end
60
+ alias :add_belongs_to :add_reference
61
+
62
+ def add_timestamps(*, **options)
63
+ options[:null] = true if options[:null].nil?
64
+ super
65
+ end
66
+
67
+ def index_exists?(table_name, column_name, options = {})
68
+ column_names = Array(column_name).map(&:to_s)
69
+ options[:name] =
70
+ if options[:name].present?
71
+ options[:name].to_s
72
+ else
73
+ index_name(table_name, column: column_names)
74
+ end
75
+ super
76
+ end
77
+
78
+ def remove_index(table_name, options = {})
79
+ options = { column: options } unless options.is_a?(Hash)
80
+ options[:name] = index_name_for_remove(table_name, options)
81
+ super(table_name, options)
82
+ end
83
+
84
+ private
85
+
86
+ def index_name_for_remove(table_name, options = {})
87
+ index_name = index_name(table_name, options)
88
+
89
+ unless index_name_exists?(table_name, index_name, true)
90
+ if options.is_a?(Hash) && options.has_key?(:name)
91
+ options_without_column = options.dup
92
+ options_without_column.delete :column
93
+ index_name_without_column = index_name(table_name, options_without_column)
94
+
95
+ return index_name_without_column if index_name_exists?(table_name, index_name_without_column, false)
96
+ end
97
+
98
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' does not exist"
99
+ end
100
+
101
+ index_name
102
+ end
103
+ end
104
+
105
+ class V4_2 < V5_0
106
+ # 4.2 is defined as a module because it needs to be shared with
107
+ # Legacy. When the time comes, V5_0 should be defined straight
108
+ # in its class.
109
+ include FourTwoShared
110
+ end
111
+
112
+ module Legacy
113
+ include FourTwoShared
114
+
115
+ def migrate(*)
116
+ ActiveSupport::Deprecation.warn \
117
+ "Directly inheriting from ActiveRecord::Migration is deprecated. " \
118
+ "Please specify the Rails release the migration was written for:\n" \
119
+ "\n" \
120
+ " class #{self.class.name} < ActiveRecord::Migration[4.2]"
121
+ super
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end
@@ -42,6 +42,19 @@ module ActiveRecord
42
42
  class_attribute :schema_migrations_table_name, instance_accessor: false
43
43
  self.schema_migrations_table_name = "schema_migrations"
44
44
 
45
+ ##
46
+ # :singleton-method:
47
+ # Accessor for the name of the internal metadata table. By default, the value is "ar_internal_metadata"
48
+ class_attribute :internal_metadata_table_name, instance_accessor: false
49
+ self.internal_metadata_table_name = "ar_internal_metadata"
50
+
51
+ ##
52
+ # :singleton-method:
53
+ # Accessor for an array of names of environments where destructive actions should be prohibited. By default,
54
+ # the value is ["production"]
55
+ class_attribute :protected_environments, instance_accessor: false
56
+ self.protected_environments = ["production"]
57
+
45
58
  ##
46
59
  # :singleton-method:
47
60
  # Indicates whether table names should be the pluralized versions of the corresponding class names.
@@ -50,6 +63,13 @@ module ActiveRecord
50
63
  class_attribute :pluralize_table_names, instance_writer: false
51
64
  self.pluralize_table_names = true
52
65
 
66
+ ##
67
+ # :singleton-method:
68
+ # Accessor for the list of columns names the model should ignore. Ignored columns won't have attribute
69
+ # accessors defined, and won't be referenced in SQL queries.
70
+ class_attribute :ignored_columns, instance_accessor: false
71
+ self.ignored_columns = [].freeze
72
+
53
73
  self.inheritance_column = 'type'
54
74
 
55
75
  delegate :type_for_attribute, to: :class
@@ -111,17 +131,6 @@ module ActiveRecord
111
131
  # class Mouse < ActiveRecord::Base
112
132
  # self.table_name = "mice"
113
133
  # 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
134
  def table_name
126
135
  reset_table_name unless defined?(@table_name)
127
136
  @table_name
@@ -132,9 +141,6 @@ module ActiveRecord
132
141
  # class Project < ActiveRecord::Base
133
142
  # self.table_name = "project"
134
143
  # 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
144
  def table_name=(value)
139
145
  value = value && value.to_s
140
146
 
@@ -147,7 +153,7 @@ module ActiveRecord
147
153
  @quoted_table_name = nil
148
154
  @arel_table = nil
149
155
  @sequence_name = nil unless defined?(@explicit_sequence_name) && @explicit_sequence_name
150
- @relation = Relation.create(self, arel_table)
156
+ @predicate_builder = nil
151
157
  end
152
158
 
153
159
  # Returns a quoted version of the table name, used to construct SQL statements.
@@ -225,39 +231,71 @@ module ActiveRecord
225
231
  @explicit_sequence_name = true
226
232
  end
227
233
 
234
+ # Determines if the primary key values should be selected from their
235
+ # corresponding sequence before the insert statement.
236
+ def prefetch_primary_key?
237
+ connection.prefetch_primary_key?(table_name)
238
+ end
239
+
240
+ # Returns the next value that will be used as the primary key on
241
+ # an insert statement.
242
+ def next_sequence_value
243
+ connection.next_sequence_value(sequence_name)
244
+ end
245
+
228
246
  # Indicates whether the table associated with this class exists
229
247
  def table_exists?
230
- connection.schema_cache.table_exists?(table_name)
248
+ connection.schema_cache.data_source_exists?(table_name)
231
249
  end
232
250
 
233
251
  def attributes_builder # :nodoc:
234
- @attributes_builder ||= AttributeSet::Builder.new(column_types, primary_key)
252
+ @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key)
235
253
  end
236
254
 
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
255
+ def columns_hash # :nodoc:
256
+ load_schema
257
+ @columns_hash
258
+ end
259
+
260
+ def columns
261
+ load_schema
262
+ @columns ||= columns_hash.values
263
+ end
264
+
265
+ def attribute_types # :nodoc:
266
+ load_schema
267
+ @attribute_types ||= Hash.new(Type::Value.new)
241
268
  end
242
269
 
243
- def type_for_attribute(attr_name) # :nodoc:
244
- column_types[attr_name]
270
+ # Returns the type of the attribute with the given name, after applying
271
+ # all modifiers. This method is the only valid source of information for
272
+ # anything related to the types of a model's attributes. This method will
273
+ # access the database and load the model's schema if it is required.
274
+ #
275
+ # The return value of this method will implement the interface described
276
+ # by ActiveModel::Type::Value (though the object itself may not subclass
277
+ # it).
278
+ #
279
+ # +attr_name+ The name of the attribute to retrieve the type for. Must be
280
+ # a string
281
+ def type_for_attribute(attr_name)
282
+ attribute_types[attr_name]
245
283
  end
246
284
 
247
285
  # Returns a hash where the keys are column names and the values are
248
- # default values when instantiating the AR object for this table.
286
+ # default values when instantiating the Active Record object for this table.
249
287
  def column_defaults
250
- _default_attributes.dup.to_hash
288
+ load_schema
289
+ _default_attributes.to_hash
251
290
  end
252
291
 
253
292
  def _default_attributes # :nodoc:
254
- @default_attributes ||= attributes_builder.build_from_database(
255
- raw_default_values)
293
+ @default_attributes ||= AttributeSet.new({})
256
294
  end
257
295
 
258
296
  # Returns an array of column names as strings.
259
297
  def column_names
260
- @column_names ||= columns.map { |column| column.name }
298
+ @column_names ||= columns.map(&:name)
261
299
  end
262
300
 
263
301
  # Returns an array of column objects where the primary id, all columns ending in "_id" or "_count",
@@ -273,7 +311,7 @@ module ActiveRecord
273
311
  # when just after creating a table you want to populate it with some default
274
312
  # values, eg:
275
313
  #
276
- # class CreateJobLevels < ActiveRecord::Migration
314
+ # class CreateJobLevels < ActiveRecord::Migration[5.0]
277
315
  # def up
278
316
  # create_table :job_levels do |t|
279
317
  # t.integer :id
@@ -295,21 +333,53 @@ module ActiveRecord
295
333
  def reset_column_information
296
334
  connection.clear_cache!
297
335
  undefine_attribute_methods
298
- connection.schema_cache.clear_table_cache!(table_name)
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
336
+ connection.schema_cache.clear_data_source_cache!(table_name)
307
337
 
308
- initialize_find_by_cache
338
+ reload_schema_from_cache
309
339
  end
310
340
 
311
341
  private
312
342
 
343
+ def schema_loaded?
344
+ defined?(@columns_hash) && @columns_hash
345
+ end
346
+
347
+ def load_schema
348
+ unless schema_loaded?
349
+ load_schema!
350
+ end
351
+ end
352
+
353
+ def load_schema!
354
+ @columns_hash = connection.schema_cache.columns_hash(table_name).except(*ignored_columns)
355
+ @columns_hash.each do |name, column|
356
+ warn_if_deprecated_type(column)
357
+ define_attribute(
358
+ name,
359
+ connection.lookup_cast_type_from_column(column),
360
+ default: column.default,
361
+ user_provided_default: false
362
+ )
363
+ end
364
+ end
365
+
366
+ def reload_schema_from_cache
367
+ @arel_engine = nil
368
+ @arel_table = nil
369
+ @column_names = nil
370
+ @attribute_types = nil
371
+ @content_columns = nil
372
+ @default_attributes = nil
373
+ @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column
374
+ @attributes_builder = nil
375
+ @columns = nil
376
+ @columns_hash = nil
377
+ @attribute_names = nil
378
+ direct_descendants.each do |descendant|
379
+ descendant.send(:reload_schema_from_cache)
380
+ end
381
+ end
382
+
313
383
  # Guesses the table name, but does not decorate it with prefix and suffix information.
314
384
  def undecorated_table_name(class_name = base_class.name)
315
385
  table_name = class_name.to_s.demodulize.underscore
@@ -334,8 +404,26 @@ module ActiveRecord
334
404
  end
335
405
  end
336
406
 
337
- def raw_default_values
338
- columns_hash.transform_values(&:default)
407
+ def warn_if_deprecated_type(column)
408
+ return if attributes_to_define_after_schema_loads.key?(column.name)
409
+ if column.respond_to?(:oid) && column.sql_type.start_with?("point")
410
+ if column.array?
411
+ array_arguments = ", array: true"
412
+ else
413
+ array_arguments = ""
414
+ end
415
+ ActiveSupport::Deprecation.warn(<<-WARNING.strip_heredoc)
416
+ The behavior of the `:point` type will be changing in Rails 5.1 to
417
+ return a `Point` object, rather than an `Array`. If you'd like to
418
+ keep the old behavior, you can add this line to #{self.name}:
419
+
420
+ attribute :#{column.name}, :legacy_point#{array_arguments}
421
+
422
+ If you'd like the new behavior today, you can add this line:
423
+
424
+ attribute :#{column.name}, :point#{array_arguments}
425
+ WARNING
426
+ end
339
427
  end
340
428
  end
341
429
  end