activerecord 4.2.0 → 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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1537 -789
- data/MIT-LICENSE +2 -2
- data/README.rdoc +7 -8
- data/examples/performance.rb +2 -3
- data/examples/simple.rb +0 -1
- data/lib/active_record/aggregations.rb +37 -23
- data/lib/active_record/association_relation.rb +16 -3
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +23 -9
- data/lib/active_record/associations/association_scope.rb +74 -102
- data/lib/active_record/associations/belongs_to_association.rb +26 -29
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +43 -18
- data/lib/active_record/associations/builder/collection_association.rb +12 -20
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +22 -15
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +11 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -10
- data/lib/active_record/associations/collection_association.rb +61 -33
- data/lib/active_record/associations/collection_proxy.rb +81 -35
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +21 -57
- data/lib/active_record/associations/has_many_through_association.rb +15 -45
- data/lib/active_record/associations/has_one_association.rb +13 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +20 -8
- data/lib/active_record/associations/join_dependency.rb +37 -21
- data/lib/active_record/associations/preloader/association.rb +51 -53
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +27 -14
- data/lib/active_record/associations/preloader.rb +18 -8
- data/lib/active_record/associations/singular_association.rb +8 -8
- data/lib/active_record/associations/through_association.rb +22 -9
- data/lib/active_record/associations.rb +321 -212
- data/lib/active_record/attribute/user_provided_default.rb +28 -0
- data/lib/active_record/attribute.rb +79 -15
- data/lib/active_record/attribute_assignment.rb +20 -141
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods/before_type_cast.rb +6 -1
- data/lib/active_record/attribute_methods/dirty.rb +51 -81
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +31 -59
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +65 -14
- data/lib/active_record/attribute_methods/write.rb +14 -38
- data/lib/active_record/attribute_methods.rb +70 -45
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set/builder.rb +37 -15
- data/lib/active_record/attribute_set.rb +34 -3
- data/lib/active_record/attributes.rb +199 -73
- data/lib/active_record/autosave_association.rb +73 -25
- data/lib/active_record/base.rb +35 -27
- data/lib/active_record/callbacks.rb +39 -43
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +40 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +457 -181
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +83 -59
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -9
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +61 -39
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +246 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +72 -17
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +438 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +53 -40
- data/lib/active_record/connection_adapters/abstract_adapter.rb +166 -66
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +429 -335
- data/lib/active_record/connection_adapters/column.rb +28 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +15 -27
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +50 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +125 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +70 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +51 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +67 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +93 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +26 -177
- data/lib/active_record/connection_adapters/postgresql/column.rb +5 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +11 -73
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +27 -56
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -13
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +31 -17
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +17 -5
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +26 -18
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +248 -154
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +258 -170
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +48 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +22 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +150 -209
- data/lib/active_record/connection_adapters/statement_pool.rb +31 -12
- data/lib/active_record/connection_handling.rb +38 -15
- data/lib/active_record/core.rb +109 -114
- data/lib/active_record/counter_cache.rb +14 -25
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +115 -79
- data/lib/active_record/errors.rb +88 -48
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +2 -2
- data/lib/active_record/fixture_set/file.rb +26 -5
- data/lib/active_record/fixtures.rb +84 -46
- data/lib/active_record/gem_version.rb +2 -2
- data/lib/active_record/inheritance.rb +32 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/internal_metadata.rb +56 -0
- data/lib/active_record/legacy_yaml_adapter.rb +46 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +27 -25
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +43 -21
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +126 -0
- data/lib/active_record/migration.rb +372 -114
- data/lib/active_record/model_schema.rb +128 -38
- data/lib/active_record/nested_attributes.rb +71 -32
- data/lib/active_record/no_touching.rb +1 -1
- data/lib/active_record/null_relation.rb +16 -8
- data/lib/active_record/persistence.rb +124 -80
- data/lib/active_record/query_cache.rb +15 -18
- data/lib/active_record/querying.rb +10 -9
- data/lib/active_record/railtie.rb +28 -19
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +67 -51
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +318 -139
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/batches.rb +139 -34
- data/lib/active_record/relation/calculations.rb +80 -102
- data/lib/active_record/relation/delegation.rb +7 -20
- data/lib/active_record/relation/finder_methods.rb +167 -97
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +38 -41
- data/lib/active_record/relation/predicate_builder/array_handler.rb +12 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +88 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +33 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +124 -82
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +323 -257
- data/lib/active_record/relation/record_fetch_warning.rb +49 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -10
- data/lib/active_record/relation/where_clause.rb +174 -0
- data/lib/active_record/relation/where_clause_factory.rb +38 -0
- data/lib/active_record/relation.rb +176 -115
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +95 -66
- data/lib/active_record/schema.rb +26 -22
- data/lib/active_record/schema_dumper.rb +62 -38
- data/lib/active_record/schema_migration.rb +11 -17
- data/lib/active_record/scoping/default.rb +24 -9
- data/lib/active_record/scoping/named.rb +49 -28
- data/lib/active_record/scoping.rb +32 -15
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +16 -14
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +58 -0
- data/lib/active_record/table_metadata.rb +68 -0
- data/lib/active_record/tasks/database_tasks.rb +59 -42
- data/lib/active_record/tasks/mysql_database_tasks.rb +32 -26
- data/lib/active_record/tasks/postgresql_database_tasks.rb +29 -9
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +20 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +159 -67
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -41
- data/lib/active_record/type/date_time.rb +2 -38
- data/lib/active_record/type/hash_lookup_type_map.rb +8 -2
- data/lib/active_record/type/internal/abstract_json.rb +29 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +21 -14
- data/lib/active_record/type/time.rb +10 -16
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/validations/absence.rb +23 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +24 -0
- data/lib/active_record/validations/presence.rb +11 -12
- data/lib/active_record/validations/uniqueness.rb +29 -18
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record.rb +9 -2
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -6
- data/lib/rails/generators/active_record/migration/templates/migration.rb +8 -7
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +32 -15
- data/lib/rails/generators/active_record/model/templates/application_record.rb +5 -0
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +60 -34
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -30
- data/lib/active_record/type/decimal.rb +0 -40
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -55
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -36
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -101
@@ -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
|
-
@
|
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.
|
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(
|
252
|
+
@attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key)
|
235
253
|
end
|
236
254
|
|
237
|
-
def
|
238
|
-
|
239
|
-
|
240
|
-
|
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
|
244
|
-
|
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
|
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 ||=
|
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
|
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.
|
336
|
+
connection.schema_cache.clear_data_source_cache!(table_name)
|
299
337
|
|
300
|
-
|
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
|
336
|
-
|
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
|
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,
|
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(
|
148
|
-
#
|
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(
|
191
|
-
#
|
192
|
-
#
|
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(
|
197
|
-
#
|
198
|
-
#
|
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
|
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
|
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
|
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
|
221
|
-
#
|
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
|
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
|
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
|
275
|
-
# can be processed with the nested attributes. Limit also can be specified
|
276
|
-
# Proc or a Symbol pointing to a method that should return number.
|
277
|
-
# nested attributes array exceeds the specified limit,
|
278
|
-
# exception is raised. If omitted, any
|
279
|
-
#
|
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
|
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
|
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.
|
@@ -307,7 +325,7 @@ module ActiveRecord
|
|
307
325
|
attr_names.each do |association_name|
|
308
326
|
if reflection = _reflect_on_association(association_name)
|
309
327
|
reflection.autosave = true
|
310
|
-
|
328
|
+
define_autosave_validation_callbacks(reflection)
|
311
329
|
|
312
330
|
nested_attributes_options = self.nested_attributes_options.dup
|
313
331
|
nested_attributes_options[association_name.to_sym] = options
|
@@ -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,14 +543,14 @@ 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.
|
546
|
+
Type::Boolean.new.cast(hash['_destroy'])
|
520
547
|
end
|
521
548
|
|
522
549
|
# Determines if a new record should be rejected by checking
|
523
550
|
# has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
|
524
551
|
# association and evaluates to +true+.
|
525
552
|
def reject_new_record?(association_name, attributes)
|
526
|
-
|
553
|
+
will_be_destroyed?(association_name, attributes) || call_reject_if(association_name, attributes)
|
527
554
|
end
|
528
555
|
|
529
556
|
# Determines if a record with the particular +attributes+ should be
|
@@ -532,7 +559,8 @@ module ActiveRecord
|
|
532
559
|
#
|
533
560
|
# Returns false if there is a +destroy_flag+ on the attributes.
|
534
561
|
def call_reject_if(association_name, attributes)
|
535
|
-
return false if
|
562
|
+
return false if will_be_destroyed?(association_name, attributes)
|
563
|
+
|
536
564
|
case callback = self.nested_attributes_options[association_name][:reject_if]
|
537
565
|
when Symbol
|
538
566
|
method(callback).arity == 0 ? send(callback) : send(callback, attributes)
|
@@ -541,8 +569,19 @@ module ActiveRecord
|
|
541
569
|
end
|
542
570
|
end
|
543
571
|
|
572
|
+
# Only take into account the destroy flag if <tt>:allow_destroy</tt> is true
|
573
|
+
def will_be_destroyed?(association_name, attributes)
|
574
|
+
allow_destroy?(association_name) && has_destroy_flag?(attributes)
|
575
|
+
end
|
576
|
+
|
577
|
+
def allow_destroy?(association_name)
|
578
|
+
self.nested_attributes_options[association_name][:allow_destroy]
|
579
|
+
end
|
580
|
+
|
544
581
|
def raise_nested_attributes_record_not_found!(association_name, record_id)
|
545
|
-
|
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)
|
546
585
|
end
|
547
586
|
end
|
548
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
|
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
|
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?(
|
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
|