activerecord 4.2.6 → 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 +4 -4
  2. data/CHANGELOG.md +1307 -1105
  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/aggregations.rb +37 -23
  8. data/lib/active_record/association_relation.rb +3 -3
  9. data/lib/active_record/associations/alias_tracker.rb +19 -16
  10. data/lib/active_record/associations/association.rb +11 -9
  11. data/lib/active_record/associations/association_scope.rb +73 -102
  12. data/lib/active_record/associations/belongs_to_association.rb +21 -32
  13. data/lib/active_record/associations/builder/association.rb +28 -34
  14. data/lib/active_record/associations/builder/belongs_to.rb +43 -18
  15. data/lib/active_record/associations/builder/collection_association.rb +7 -19
  16. data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +14 -11
  17. data/lib/active_record/associations/builder/has_many.rb +4 -4
  18. data/lib/active_record/associations/builder/has_one.rb +11 -6
  19. data/lib/active_record/associations/builder/singular_association.rb +3 -10
  20. data/lib/active_record/associations/collection_association.rb +50 -31
  21. data/lib/active_record/associations/collection_proxy.rb +69 -29
  22. data/lib/active_record/associations/foreign_association.rb +1 -1
  23. data/lib/active_record/associations/has_many_association.rb +20 -71
  24. data/lib/active_record/associations/has_many_through_association.rb +8 -47
  25. data/lib/active_record/associations/has_one_association.rb +12 -5
  26. data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
  27. data/lib/active_record/associations/join_dependency.rb +29 -19
  28. data/lib/active_record/associations/preloader/association.rb +46 -52
  29. data/lib/active_record/associations/preloader/collection_association.rb +0 -6
  30. data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
  31. data/lib/active_record/associations/preloader/has_one.rb +0 -8
  32. data/lib/active_record/associations/preloader/through_association.rb +27 -14
  33. data/lib/active_record/associations/preloader.rb +14 -4
  34. data/lib/active_record/associations/singular_association.rb +7 -1
  35. data/lib/active_record/associations/through_association.rb +11 -3
  36. data/lib/active_record/associations.rb +317 -209
  37. data/lib/active_record/attribute/user_provided_default.rb +28 -0
  38. data/lib/active_record/attribute.rb +68 -18
  39. data/lib/active_record/attribute_assignment.rb +20 -141
  40. data/lib/active_record/attribute_decorators.rb +6 -5
  41. data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
  42. data/lib/active_record/attribute_methods/dirty.rb +46 -86
  43. data/lib/active_record/attribute_methods/primary_key.rb +2 -2
  44. data/lib/active_record/attribute_methods/query.rb +2 -2
  45. data/lib/active_record/attribute_methods/read.rb +31 -59
  46. data/lib/active_record/attribute_methods/serialization.rb +13 -16
  47. data/lib/active_record/attribute_methods/time_zone_conversion.rb +61 -14
  48. data/lib/active_record/attribute_methods/write.rb +14 -38
  49. data/lib/active_record/attribute_methods.rb +70 -45
  50. data/lib/active_record/attribute_mutation_tracker.rb +70 -0
  51. data/lib/active_record/attribute_set/builder.rb +6 -4
  52. data/lib/active_record/attribute_set.rb +30 -3
  53. data/lib/active_record/attributes.rb +199 -80
  54. data/lib/active_record/autosave_association.rb +49 -16
  55. data/lib/active_record/base.rb +32 -23
  56. data/lib/active_record/callbacks.rb +39 -43
  57. data/lib/active_record/coders/json.rb +1 -1
  58. data/lib/active_record/coders/yaml_column.rb +20 -8
  59. data/lib/active_record/collection_cache_key.rb +40 -0
  60. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +452 -182
  61. data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
  62. data/lib/active_record/connection_adapters/abstract/database_statements.rb +65 -61
  63. data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -2
  64. data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
  65. data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
  66. data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
  67. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +236 -185
  68. data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
  69. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +378 -140
  70. data/lib/active_record/connection_adapters/abstract/transaction.rb +51 -34
  71. data/lib/active_record/connection_adapters/abstract_adapter.rb +153 -59
  72. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +405 -362
  73. data/lib/active_record/connection_adapters/column.rb +28 -43
  74. data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
  75. data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
  76. data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
  77. data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
  78. data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
  79. data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
  80. data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
  81. data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
  82. data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
  83. data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
  84. data/lib/active_record/connection_adapters/mysql2_adapter.rb +25 -176
  85. data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
  86. data/lib/active_record/connection_adapters/postgresql/database_statements.rb +10 -72
  87. data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
  88. data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
  89. data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
  90. data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
  91. data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
  92. data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
  93. data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
  94. data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
  95. data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
  96. data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
  97. data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
  98. data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
  99. data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
  100. data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
  101. data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
  102. data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
  103. data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
  104. data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
  105. data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
  106. data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
  107. data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
  108. data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
  109. data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -148
  110. data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
  111. data/lib/active_record/connection_adapters/postgresql_adapter.rb +248 -160
  112. data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
  113. data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
  114. data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
  115. data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
  116. data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
  117. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +148 -203
  118. data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
  119. data/lib/active_record/connection_handling.rb +37 -14
  120. data/lib/active_record/core.rb +89 -107
  121. data/lib/active_record/counter_cache.rb +13 -24
  122. data/lib/active_record/dynamic_matchers.rb +1 -20
  123. data/lib/active_record/enum.rb +113 -76
  124. data/lib/active_record/errors.rb +87 -48
  125. data/lib/active_record/explain_registry.rb +1 -1
  126. data/lib/active_record/explain_subscriber.rb +1 -1
  127. data/lib/active_record/fixture_set/file.rb +26 -5
  128. data/lib/active_record/fixtures.rb +76 -40
  129. data/lib/active_record/gem_version.rb +3 -3
  130. data/lib/active_record/inheritance.rb +32 -40
  131. data/lib/active_record/integration.rb +4 -4
  132. data/lib/active_record/internal_metadata.rb +56 -0
  133. data/lib/active_record/legacy_yaml_adapter.rb +18 -2
  134. data/lib/active_record/locale/en.yml +3 -2
  135. data/lib/active_record/locking/optimistic.rb +15 -15
  136. data/lib/active_record/locking/pessimistic.rb +1 -1
  137. data/lib/active_record/log_subscriber.rb +43 -21
  138. data/lib/active_record/migration/command_recorder.rb +59 -18
  139. data/lib/active_record/migration/compatibility.rb +126 -0
  140. data/lib/active_record/migration.rb +364 -109
  141. data/lib/active_record/model_schema.rb +128 -38
  142. data/lib/active_record/nested_attributes.rb +58 -29
  143. data/lib/active_record/null_relation.rb +16 -8
  144. data/lib/active_record/persistence.rb +121 -80
  145. data/lib/active_record/query_cache.rb +15 -18
  146. data/lib/active_record/querying.rb +10 -9
  147. data/lib/active_record/railtie.rb +27 -18
  148. data/lib/active_record/railties/controller_runtime.rb +1 -1
  149. data/lib/active_record/railties/databases.rake +58 -45
  150. data/lib/active_record/readonly_attributes.rb +1 -1
  151. data/lib/active_record/reflection.rb +282 -115
  152. data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
  153. data/lib/active_record/relation/batches.rb +139 -34
  154. data/lib/active_record/relation/calculations.rb +80 -102
  155. data/lib/active_record/relation/delegation.rb +7 -20
  156. data/lib/active_record/relation/finder_methods.rb +163 -81
  157. data/lib/active_record/relation/from_clause.rb +32 -0
  158. data/lib/active_record/relation/merger.rb +16 -42
  159. data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -15
  160. data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
  161. data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
  162. data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
  163. data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
  164. data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
  165. data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
  166. data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
  167. data/lib/active_record/relation/predicate_builder.rb +120 -107
  168. data/lib/active_record/relation/query_attribute.rb +19 -0
  169. data/lib/active_record/relation/query_methods.rb +308 -244
  170. data/lib/active_record/relation/record_fetch_warning.rb +49 -0
  171. data/lib/active_record/relation/spawn_methods.rb +4 -7
  172. data/lib/active_record/relation/where_clause.rb +174 -0
  173. data/lib/active_record/relation/where_clause_factory.rb +38 -0
  174. data/lib/active_record/relation.rb +176 -116
  175. data/lib/active_record/result.rb +4 -3
  176. data/lib/active_record/runtime_registry.rb +1 -1
  177. data/lib/active_record/sanitization.rb +95 -66
  178. data/lib/active_record/schema.rb +26 -22
  179. data/lib/active_record/schema_dumper.rb +62 -38
  180. data/lib/active_record/schema_migration.rb +11 -17
  181. data/lib/active_record/scoping/default.rb +23 -9
  182. data/lib/active_record/scoping/named.rb +49 -28
  183. data/lib/active_record/scoping.rb +32 -15
  184. data/lib/active_record/secure_token.rb +38 -0
  185. data/lib/active_record/serialization.rb +2 -4
  186. data/lib/active_record/statement_cache.rb +16 -14
  187. data/lib/active_record/store.rb +8 -3
  188. data/lib/active_record/suppressor.rb +58 -0
  189. data/lib/active_record/table_metadata.rb +68 -0
  190. data/lib/active_record/tasks/database_tasks.rb +58 -41
  191. data/lib/active_record/tasks/mysql_database_tasks.rb +16 -20
  192. data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
  193. data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
  194. data/lib/active_record/timestamp.rb +20 -9
  195. data/lib/active_record/touch_later.rb +58 -0
  196. data/lib/active_record/transactions.rb +138 -56
  197. data/lib/active_record/type/adapter_specific_registry.rb +130 -0
  198. data/lib/active_record/type/date.rb +2 -41
  199. data/lib/active_record/type/date_time.rb +2 -49
  200. data/lib/active_record/type/internal/abstract_json.rb +29 -0
  201. data/lib/active_record/type/internal/timezone.rb +15 -0
  202. data/lib/active_record/type/serialized.rb +15 -14
  203. data/lib/active_record/type/time.rb +10 -16
  204. data/lib/active_record/type/type_map.rb +4 -4
  205. data/lib/active_record/type.rb +66 -17
  206. data/lib/active_record/type_caster/connection.rb +29 -0
  207. data/lib/active_record/type_caster/map.rb +19 -0
  208. data/lib/active_record/type_caster.rb +7 -0
  209. data/lib/active_record/validations/absence.rb +23 -0
  210. data/lib/active_record/validations/associated.rb +10 -3
  211. data/lib/active_record/validations/length.rb +24 -0
  212. data/lib/active_record/validations/presence.rb +11 -12
  213. data/lib/active_record/validations/uniqueness.rb +30 -29
  214. data/lib/active_record/validations.rb +33 -32
  215. data/lib/active_record.rb +7 -2
  216. data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
  217. data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
  218. data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -1
  219. data/lib/rails/generators/active_record/migration.rb +7 -0
  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 +58 -34
  224. data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
  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 -50
  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 -105
@@ -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
241
263
  end
242
264
 
243
- def type_for_attribute(attr_name) # :nodoc:
244
- column_types[attr_name]
265
+ def attribute_types # :nodoc:
266
+ load_schema
267
+ @attribute_types ||= Hash.new(Type::Value.new)
268
+ end
269
+
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
288
+ load_schema
250
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,19 +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)
336
+ connection.schema_cache.clear_data_source_cache!(table_name)
299
337
 
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
338
+ reload_schema_from_cache
307
339
  end
308
340
 
309
341
  private
310
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
+
311
383
  # Guesses the table name, but does not decorate it with prefix and suffix information.
312
384
  def undecorated_table_name(class_name = base_class.name)
313
385
  table_name = class_name.to_s.demodulize.underscore
@@ -332,8 +404,26 @@ module ActiveRecord
332
404
  end
333
405
  end
334
406
 
335
- def raw_default_values
336
- 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
337
427
  end
338
428
  end
339
429
  end
@@ -81,6 +81,9 @@ module ActiveRecord
81
81
  #
82
82
  # Note that the model will _not_ be destroyed until the parent is saved.
83
83
  #
84
+ # Also note that the model will not be destroyed unless you also specify
85
+ # its id in the updated hash.
86
+ #
84
87
  # === One-to-many
85
88
  #
86
89
  # Consider a member that has a number of posts:
@@ -111,7 +114,7 @@ module ActiveRecord
111
114
  # member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
112
115
  # member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
113
116
  #
114
- # You may also set a :reject_if proc to silently ignore any new record
117
+ # You may also set a +:reject_if+ proc to silently ignore any new record
115
118
  # hashes if they fail to pass your criteria. For example, the previous
116
119
  # example could be rewritten as:
117
120
  #
@@ -133,7 +136,7 @@ module ActiveRecord
133
136
  # member.posts.first.title # => 'Kari, the awesome Ruby documentation browser!'
134
137
  # member.posts.second.title # => 'The egalitarian assumption of the modern citizen'
135
138
  #
136
- # Alternatively, :reject_if also accepts a symbol for using methods:
139
+ # Alternatively, +:reject_if+ also accepts a symbol for using methods:
137
140
  #
138
141
  # class Member < ActiveRecord::Base
139
142
  # has_many :posts
@@ -144,8 +147,8 @@ module ActiveRecord
144
147
  # has_many :posts
145
148
  # accepts_nested_attributes_for :posts, reject_if: :reject_posts
146
149
  #
147
- # def reject_posts(attributed)
148
- # attributed['title'].blank?
150
+ # def reject_posts(attributes)
151
+ # attributes['title'].blank?
149
152
  # end
150
153
  # end
151
154
  #
@@ -163,6 +166,11 @@ module ActiveRecord
163
166
  # member.posts.first.title # => '[UPDATED] An, as of yet, undisclosed awesome Ruby documentation browser!'
164
167
  # member.posts.second.title # => '[UPDATED] other post'
165
168
  #
169
+ # However, the above applies if the parent model is being updated as well.
170
+ # For example, If you wanted to create a +member+ named _joe_ and wanted to
171
+ # update the +posts+ at the same time, that would give an
172
+ # ActiveRecord::RecordNotFound error.
173
+ #
166
174
  # By default the associated records are protected from being destroyed. If
167
175
  # you want to destroy any of the associated records through the attributes
168
176
  # hash, you have to enable it first using the <tt>:allow_destroy</tt>
@@ -187,38 +195,46 @@ module ActiveRecord
187
195
  # Nested attributes for an associated collection can also be passed in
188
196
  # the form of a hash of hashes instead of an array of hashes:
189
197
  #
190
- # Member.create(name: 'joe',
191
- # posts_attributes: { first: { title: 'Foo' },
192
- # second: { title: 'Bar' } })
198
+ # Member.create(
199
+ # name: 'joe',
200
+ # posts_attributes: {
201
+ # first: { title: 'Foo' },
202
+ # second: { title: 'Bar' }
203
+ # }
204
+ # )
193
205
  #
194
206
  # has the same effect as
195
207
  #
196
- # Member.create(name: 'joe',
197
- # posts_attributes: [ { title: 'Foo' },
198
- # { title: 'Bar' } ])
208
+ # Member.create(
209
+ # name: 'joe',
210
+ # posts_attributes: [
211
+ # { title: 'Foo' },
212
+ # { title: 'Bar' }
213
+ # ]
214
+ # )
199
215
  #
200
216
  # The keys of the hash which is the value for +:posts_attributes+ are
201
217
  # ignored in this case.
202
- # However, it is not allowed to use +'id'+ or +:id+ for one of
218
+ # However, it is not allowed to use <tt>'id'</tt> or <tt>:id</tt> for one of
203
219
  # such keys, otherwise the hash will be wrapped in an array and
204
220
  # interpreted as an attribute hash for a single post.
205
221
  #
206
222
  # Passing attributes for an associated collection in the form of a hash
207
223
  # of hashes can be used with hashes generated from HTTP/HTML parameters,
208
- # where there maybe no natural way to submit an array of hashes.
224
+ # where there may be no natural way to submit an array of hashes.
209
225
  #
210
226
  # === Saving
211
227
  #
212
228
  # All changes to models, including the destruction of those marked for
213
229
  # destruction, are saved and destroyed automatically and atomically when
214
230
  # the parent model is saved. This happens inside the transaction initiated
215
- # by the parents save method. See ActiveRecord::AutosaveAssociation.
231
+ # by the parent's save method. See ActiveRecord::AutosaveAssociation.
216
232
  #
217
233
  # === Validating the presence of a parent model
218
234
  #
219
235
  # If you want to validate that a child record is associated with a parent
220
- # record, you can use <tt>validates_presence_of</tt> and
221
- # <tt>inverse_of</tt> as this example illustrates:
236
+ # record, you can use the +validates_presence_of+ method and the +:inverse_of+
237
+ # key as this example illustrates:
222
238
  #
223
239
  # class Member < ActiveRecord::Base
224
240
  # has_many :posts, inverse_of: :member
@@ -230,7 +246,7 @@ module ActiveRecord
230
246
  # validates_presence_of :member
231
247
  # end
232
248
  #
233
- # Note that if you do not specify the <tt>inverse_of</tt> option, then
249
+ # Note that if you do not specify the +:inverse_of+ option, then
234
250
  # Active Record will try to automatically guess the inverse association
235
251
  # based on heuristics.
236
252
  #
@@ -264,29 +280,31 @@ module ActiveRecord
264
280
  # Allows you to specify a Proc or a Symbol pointing to a method
265
281
  # that checks whether a record should be built for a certain attribute
266
282
  # hash. The hash is passed to the supplied Proc or the method
267
- # and it should return either +true+ or +false+. When no :reject_if
283
+ # and it should return either +true+ or +false+. When no +:reject_if+
268
284
  # is specified, a record will be built for all attribute hashes that
269
285
  # do not have a <tt>_destroy</tt> value that evaluates to true.
270
286
  # Passing <tt>:all_blank</tt> instead of a Proc will create a proc
271
287
  # that will reject a record where all the attributes are blank excluding
272
- # any value for _destroy.
288
+ # any value for +_destroy+.
273
289
  # [:limit]
274
- # Allows you to specify the maximum number of the associated records that
275
- # can be processed with the nested attributes. Limit also can be specified as a
276
- # Proc or a Symbol pointing to a method that should return number. If the size of the
277
- # nested attributes array exceeds the specified limit, NestedAttributes::TooManyRecords
278
- # exception is raised. If omitted, any number associations can be processed.
279
- # Note that the :limit option is only applicable to one-to-many associations.
290
+ # Allows you to specify the maximum number of associated records that
291
+ # can be processed with the nested attributes. Limit also can be specified
292
+ # as a Proc or a Symbol pointing to a method that should return a number.
293
+ # If the size of the nested attributes array exceeds the specified limit,
294
+ # NestedAttributes::TooManyRecords exception is raised. If omitted, any
295
+ # number of associations can be processed.
296
+ # Note that the +:limit+ option is only applicable to one-to-many
297
+ # associations.
280
298
  # [:update_only]
281
299
  # For a one-to-one association, this option allows you to specify how
282
- # nested attributes are to be used when an associated record already
300
+ # nested attributes are going to be used when an associated record already
283
301
  # exists. In general, an existing record may either be updated with the
284
302
  # new set of attribute values or be replaced by a wholly new record
285
- # containing those values. By default the :update_only option is +false+
303
+ # containing those values. By default the +:update_only+ option is +false+
286
304
  # and the nested attributes are used to update the existing record only
287
305
  # if they include the record's <tt>:id</tt> value. Otherwise a new
288
306
  # record will be instantiated and used to replace the existing one.
289
- # However if the :update_only option is +true+, the nested attributes
307
+ # However if the +:update_only+ option is +true+, the nested attributes
290
308
  # are used to update the record's attributes always, regardless of
291
309
  # whether the <tt>:id</tt> is present. The option is ignored for collection
292
310
  # associations.
@@ -376,6 +394,9 @@ module ActiveRecord
376
394
  # then the existing record will be marked for destruction.
377
395
  def assign_nested_attributes_for_one_to_one_association(association_name, attributes)
378
396
  options = self.nested_attributes_options[association_name]
397
+ if attributes.respond_to?(:permitted?)
398
+ attributes = attributes.to_h
399
+ end
379
400
  attributes = attributes.with_indifferent_access
380
401
  existing_record = send(association_name)
381
402
 
@@ -432,6 +453,9 @@ module ActiveRecord
432
453
  # ])
433
454
  def assign_nested_attributes_for_collection_association(association_name, attributes_collection)
434
455
  options = self.nested_attributes_options[association_name]
456
+ if attributes_collection.respond_to?(:permitted?)
457
+ attributes_collection = attributes_collection.to_h
458
+ end
435
459
 
436
460
  unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
437
461
  raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
@@ -458,6 +482,9 @@ module ActiveRecord
458
482
  end
459
483
 
460
484
  attributes_collection.each do |attributes|
485
+ if attributes.respond_to?(:permitted?)
486
+ attributes = attributes.to_h
487
+ end
461
488
  attributes = attributes.with_indifferent_access
462
489
 
463
490
  if attributes['id'].blank?
@@ -516,7 +543,7 @@ module ActiveRecord
516
543
 
517
544
  # Determines if a hash contains a truthy _destroy key.
518
545
  def has_destroy_flag?(hash)
519
- Type::Boolean.new.type_cast_from_user(hash['_destroy'])
546
+ Type::Boolean.new.cast(hash['_destroy'])
520
547
  end
521
548
 
522
549
  # Determines if a new record should be rejected by checking
@@ -552,7 +579,9 @@ module ActiveRecord
552
579
  end
553
580
 
554
581
  def raise_nested_attributes_record_not_found!(association_name, record_id)
555
- raise RecordNotFound, "Couldn't find #{self.class._reflect_on_association(association_name).klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
582
+ model = self.class._reflect_on_association(association_name).klass.name
583
+ raise RecordNotFound.new("Couldn't find #{model} with ID=#{record_id} for #{self.class.name} with ID=#{id}",
584
+ model, 'id', record_id)
556
585
  end
557
586
  end
558
587
  end
@@ -1,9 +1,7 @@
1
- # -*- coding: utf-8 -*-
2
-
3
1
  module ActiveRecord
4
2
  module NullRelation # :nodoc:
5
3
  def exec_queries
6
- @records = []
4
+ @records = [].freeze
7
5
  end
8
6
 
9
7
  def pluck(*column_names)
@@ -14,7 +12,7 @@ module ActiveRecord
14
12
  0
15
13
  end
16
14
 
17
- def update_all(_updates, _conditions = nil, _options = {})
15
+ def update_all(_updates)
18
16
  0
19
17
  end
20
18
 
@@ -30,10 +28,18 @@ module ActiveRecord
30
28
  true
31
29
  end
32
30
 
31
+ def none?
32
+ true
33
+ end
34
+
33
35
  def any?
34
36
  false
35
37
  end
36
38
 
39
+ def one?
40
+ false
41
+ end
42
+
37
43
  def many?
38
44
  false
39
45
  end
@@ -62,9 +68,7 @@ module ActiveRecord
62
68
  calculate :maximum, nil
63
69
  end
64
70
 
65
- def calculate(operation, _column_name, _options = {})
66
- # TODO: Remove _options argument as soon we remove support to
67
- # activerecord-deprecated_finders.
71
+ def calculate(operation, _column_name)
68
72
  if [:count, :sum, :size].include? operation
69
73
  group_values.any? ? Hash.new : 0
70
74
  elsif [:average, :minimum, :maximum].include?(operation) && group_values.any?
@@ -74,8 +78,12 @@ module ActiveRecord
74
78
  end
75
79
  end
76
80
 
77
- def exists?(_id = false)
81
+ def exists?(_conditions = :none)
78
82
  false
79
83
  end
84
+
85
+ def or(other)
86
+ other.spawn
87
+ end
80
88
  end
81
89
  end