activerecord 5.1.5 → 5.2.8.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +655 -608
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -5
- data/examples/performance.rb +2 -0
- data/examples/simple.rb +2 -0
- data/lib/active_record/aggregations.rb +6 -5
- data/lib/active_record/association_relation.rb +7 -5
- data/lib/active_record/associations/alias_tracker.rb +19 -27
- data/lib/active_record/associations/association.rb +41 -37
- data/lib/active_record/associations/association_scope.rb +38 -50
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -8
- data/lib/active_record/associations/builder/association.rb +4 -7
- data/lib/active_record/associations/builder/belongs_to.rb +14 -5
- data/lib/active_record/associations/builder/collection_association.rb +3 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +3 -1
- data/lib/active_record/associations/builder/has_many.rb +2 -0
- data/lib/active_record/associations/builder/has_one.rb +2 -0
- data/lib/active_record/associations/builder/singular_association.rb +2 -0
- data/lib/active_record/associations/collection_association.rb +59 -47
- data/lib/active_record/associations/collection_proxy.rb +20 -49
- data/lib/active_record/associations/foreign_association.rb +2 -0
- data/lib/active_record/associations/has_many_association.rb +12 -1
- data/lib/active_record/associations/has_many_through_association.rb +36 -30
- data/lib/active_record/associations/has_one_association.rb +12 -1
- data/lib/active_record/associations/has_one_through_association.rb +13 -8
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -63
- data/lib/active_record/associations/join_dependency/join_base.rb +9 -8
- data/lib/active_record/associations/join_dependency/join_part.rb +9 -9
- data/lib/active_record/associations/join_dependency.rb +48 -93
- data/lib/active_record/associations/preloader/association.rb +45 -61
- data/lib/active_record/associations/preloader/through_association.rb +71 -79
- data/lib/active_record/associations/preloader.rb +18 -38
- data/lib/active_record/associations/singular_association.rb +14 -16
- data/lib/active_record/associations/through_association.rb +26 -11
- data/lib/active_record/associations.rb +40 -63
- data/lib/active_record/attribute_assignment.rb +2 -5
- data/lib/active_record/attribute_decorators.rb +3 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +2 -0
- data/lib/active_record/attribute_methods/dirty.rb +32 -216
- data/lib/active_record/attribute_methods/primary_key.rb +7 -6
- data/lib/active_record/attribute_methods/query.rb +2 -0
- data/lib/active_record/attribute_methods/read.rb +9 -3
- data/lib/active_record/attribute_methods/serialization.rb +23 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +6 -8
- data/lib/active_record/attribute_methods/write.rb +21 -9
- data/lib/active_record/attribute_methods.rb +65 -24
- data/lib/active_record/attributes.rb +7 -6
- data/lib/active_record/autosave_association.rb +35 -19
- data/lib/active_record/base.rb +2 -0
- data/lib/active_record/callbacks.rb +12 -6
- data/lib/active_record/coders/json.rb +2 -0
- data/lib/active_record/coders/yaml_column.rb +15 -1
- data/lib/active_record/collection_cache_key.rb +12 -8
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +142 -42
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +174 -33
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +15 -5
- data/lib/active_record/connection_adapters/abstract/quoting.rb +15 -32
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +14 -5
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +64 -6
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +31 -53
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +152 -81
- data/lib/active_record/connection_adapters/abstract/transaction.rb +66 -21
- data/lib/active_record/connection_adapters/abstract_adapter.rb +84 -97
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +110 -173
- data/lib/active_record/connection_adapters/column.rb +3 -1
- data/lib/active_record/connection_adapters/connection_specification.rb +17 -3
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +13 -2
- data/lib/active_record/connection_adapters/mysql/column.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +47 -2
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +9 -10
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +5 -3
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +7 -10
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +30 -30
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +106 -1
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/column.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +6 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +8 -2
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +19 -25
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +24 -11
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +20 -13
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +234 -112
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +66 -74
- data/lib/active_record/connection_adapters/schema_cache.rb +4 -2
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +24 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +6 -15
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +3 -2
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +75 -1
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +82 -95
- data/lib/active_record/connection_adapters/statement_pool.rb +2 -0
- data/lib/active_record/connection_handling.rb +4 -2
- data/lib/active_record/core.rb +51 -61
- data/lib/active_record/counter_cache.rb +20 -15
- data/lib/active_record/define_callbacks.rb +5 -3
- data/lib/active_record/dynamic_matchers.rb +9 -9
- data/lib/active_record/enum.rb +18 -13
- data/lib/active_record/errors.rb +60 -15
- data/lib/active_record/explain.rb +3 -1
- data/lib/active_record/explain_registry.rb +2 -0
- data/lib/active_record/explain_subscriber.rb +2 -0
- data/lib/active_record/fixture_set/file.rb +2 -0
- data/lib/active_record/fixtures.rb +67 -60
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +49 -19
- data/lib/active_record/integration.rb +58 -19
- data/lib/active_record/internal_metadata.rb +2 -0
- data/lib/active_record/legacy_yaml_adapter.rb +3 -1
- data/lib/active_record/locking/optimistic.rb +30 -42
- data/lib/active_record/locking/pessimistic.rb +9 -6
- data/lib/active_record/log_subscriber.rb +43 -0
- data/lib/active_record/migration/command_recorder.rb +11 -9
- data/lib/active_record/migration/compatibility.rb +47 -9
- data/lib/active_record/migration/join_table.rb +2 -0
- data/lib/active_record/migration.rb +189 -139
- data/lib/active_record/model_schema.rb +19 -24
- data/lib/active_record/nested_attributes.rb +18 -6
- data/lib/active_record/no_touching.rb +3 -1
- data/lib/active_record/null_relation.rb +2 -0
- data/lib/active_record/persistence.rb +198 -49
- data/lib/active_record/query_cache.rb +12 -14
- data/lib/active_record/querying.rb +4 -2
- data/lib/active_record/railtie.rb +80 -6
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +2 -0
- data/lib/active_record/railties/databases.rake +46 -36
- data/lib/active_record/readonly_attributes.rb +3 -2
- data/lib/active_record/reflection.rb +108 -194
- data/lib/active_record/relation/batches/batch_enumerator.rb +2 -0
- data/lib/active_record/relation/batches.rb +20 -5
- data/lib/active_record/relation/calculations.rb +46 -20
- data/lib/active_record/relation/delegation.rb +45 -27
- data/lib/active_record/relation/finder_methods.rb +77 -78
- data/lib/active_record/relation/from_clause.rb +2 -8
- data/lib/active_record/relation/merger.rb +53 -23
- data/lib/active_record/relation/predicate_builder/array_handler.rb +10 -7
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +46 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +2 -2
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +12 -1
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +56 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +26 -9
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +6 -0
- data/lib/active_record/relation/predicate_builder.rb +60 -79
- data/lib/active_record/relation/query_attribute.rb +28 -2
- data/lib/active_record/relation/query_methods.rb +129 -100
- data/lib/active_record/relation/record_fetch_warning.rb +2 -0
- data/lib/active_record/relation/spawn_methods.rb +4 -2
- data/lib/active_record/relation/where_clause.rb +65 -68
- data/lib/active_record/relation/where_clause_factory.rb +5 -48
- data/lib/active_record/relation.rb +120 -214
- data/lib/active_record/result.rb +2 -0
- data/lib/active_record/runtime_registry.rb +2 -0
- data/lib/active_record/sanitization.rb +129 -121
- data/lib/active_record/schema.rb +4 -2
- data/lib/active_record/schema_dumper.rb +36 -26
- data/lib/active_record/schema_migration.rb +2 -0
- data/lib/active_record/scoping/default.rb +8 -9
- data/lib/active_record/scoping/named.rb +23 -7
- data/lib/active_record/scoping.rb +9 -8
- data/lib/active_record/secure_token.rb +2 -0
- data/lib/active_record/serialization.rb +2 -0
- data/lib/active_record/statement_cache.rb +23 -13
- data/lib/active_record/store.rb +3 -1
- data/lib/active_record/suppressor.rb +2 -0
- data/lib/active_record/table_metadata.rb +12 -3
- data/lib/active_record/tasks/database_tasks.rb +26 -15
- data/lib/active_record/tasks/mysql_database_tasks.rb +9 -48
- data/lib/active_record/tasks/postgresql_database_tasks.rb +10 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +25 -3
- data/lib/active_record/timestamp.rb +13 -6
- data/lib/active_record/touch_later.rb +2 -0
- data/lib/active_record/transactions.rb +33 -28
- data/lib/active_record/translation.rb +2 -0
- data/lib/active_record/type/adapter_specific_registry.rb +2 -0
- data/lib/active_record/type/date.rb +2 -0
- data/lib/active_record/type/date_time.rb +2 -0
- data/lib/active_record/type/decimal_without_scale.rb +2 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +2 -0
- data/lib/active_record/type/internal/timezone.rb +2 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +6 -0
- data/lib/active_record/type/text.rb +2 -0
- data/lib/active_record/type/time.rb +2 -0
- data/lib/active_record/type/type_map.rb +2 -0
- data/lib/active_record/type/unsigned_integer.rb +2 -0
- data/lib/active_record/type.rb +4 -1
- data/lib/active_record/type_caster/connection.rb +2 -0
- data/lib/active_record/type_caster/map.rb +3 -1
- data/lib/active_record/type_caster.rb +2 -0
- data/lib/active_record/validations/absence.rb +2 -0
- data/lib/active_record/validations/associated.rb +2 -0
- data/lib/active_record/validations/length.rb +2 -0
- data/lib/active_record/validations/presence.rb +2 -0
- data/lib/active_record/validations/uniqueness.rb +36 -6
- data/lib/active_record/validations.rb +2 -0
- data/lib/active_record/version.rb +2 -0
- data/lib/active_record.rb +11 -4
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/{model/templates/application_record.rb → application_record/templates/application_record.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -1
- data/lib/rails/generators/active_record/migration/templates/{create_table_migration.rb → create_table_migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +0 -0
- data/lib/rails/generators/active_record/migration.rb +2 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +2 -23
- data/lib/rails/generators/active_record/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +3 -1
- metadata +26 -40
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -15
- data/lib/active_record/associations/preloader/collection_association.rb +0 -17
- data/lib/active_record/associations/preloader/has_many.rb +0 -15
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -15
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -18
- data/lib/active_record/attribute/user_provided_default.rb +0 -30
- data/lib/active_record/attribute.rb +0 -240
- data/lib/active_record/attribute_mutation_tracker.rb +0 -114
- data/lib/active_record/attribute_set/builder.rb +0 -124
- data/lib/active_record/attribute_set/yaml_encoder.rb +0 -41
- data/lib/active_record/attribute_set.rb +0 -113
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -10
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +0 -88
- data/lib/active_record/relation/predicate_builder/polymorphic_array_handler.rb +0 -59
- data/lib/active_record/type/internal/abstract_json.rb +0 -37
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record \Persistence
|
3
5
|
module Persistence
|
@@ -69,6 +71,142 @@ module ActiveRecord
|
|
69
71
|
klass.allocate.init_with("attributes" => attributes, "new_record" => false, &block)
|
70
72
|
end
|
71
73
|
|
74
|
+
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
75
|
+
# The resulting object is returned whether the object was saved successfully to the database or not.
|
76
|
+
#
|
77
|
+
# ==== Parameters
|
78
|
+
#
|
79
|
+
# * +id+ - This should be the id or an array of ids to be updated.
|
80
|
+
# * +attributes+ - This should be a hash of attributes or an array of hashes.
|
81
|
+
#
|
82
|
+
# ==== Examples
|
83
|
+
#
|
84
|
+
# # Updates one record
|
85
|
+
# Person.update(15, user_name: "Samuel", group: "expert")
|
86
|
+
#
|
87
|
+
# # Updates multiple records
|
88
|
+
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
|
89
|
+
# Person.update(people.keys, people.values)
|
90
|
+
#
|
91
|
+
# # Updates multiple records from the result of a relation
|
92
|
+
# people = Person.where(group: "expert")
|
93
|
+
# people.update(group: "masters")
|
94
|
+
#
|
95
|
+
# Note: Updating a large number of records will run an UPDATE
|
96
|
+
# query for each record, which may cause a performance issue.
|
97
|
+
# When running callbacks is not needed for each record update,
|
98
|
+
# it is preferred to use {update_all}[rdoc-ref:Relation#update_all]
|
99
|
+
# for updating all records in a single query.
|
100
|
+
def update(id = :all, attributes)
|
101
|
+
if id.is_a?(Array)
|
102
|
+
id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
|
103
|
+
object.update(attributes[idx])
|
104
|
+
}
|
105
|
+
elsif id == :all
|
106
|
+
all.each { |record| record.update(attributes) }
|
107
|
+
else
|
108
|
+
if ActiveRecord::Base === id
|
109
|
+
raise ArgumentError,
|
110
|
+
"You are passing an instance of ActiveRecord::Base to `update`. " \
|
111
|
+
"Please pass the id of the object by calling `.id`."
|
112
|
+
end
|
113
|
+
object = find(id)
|
114
|
+
object.update(attributes)
|
115
|
+
object
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
# Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
|
120
|
+
# therefore all callbacks and filters are fired off before the object is deleted. This method is
|
121
|
+
# less efficient than #delete but allows cleanup methods and other actions to be run.
|
122
|
+
#
|
123
|
+
# This essentially finds the object (or multiple objects) with the given id, creates a new object
|
124
|
+
# from the attributes, and then calls destroy on it.
|
125
|
+
#
|
126
|
+
# ==== Parameters
|
127
|
+
#
|
128
|
+
# * +id+ - This should be the id or an array of ids to be destroyed.
|
129
|
+
#
|
130
|
+
# ==== Examples
|
131
|
+
#
|
132
|
+
# # Destroy a single object
|
133
|
+
# Todo.destroy(1)
|
134
|
+
#
|
135
|
+
# # Destroy multiple objects
|
136
|
+
# todos = [1,2,3]
|
137
|
+
# Todo.destroy(todos)
|
138
|
+
def destroy(id)
|
139
|
+
if id.is_a?(Array)
|
140
|
+
find(id).each(&:destroy)
|
141
|
+
else
|
142
|
+
find(id).destroy
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Deletes the row with a primary key matching the +id+ argument, using a
|
147
|
+
# SQL +DELETE+ statement, and returns the number of rows deleted. Active
|
148
|
+
# Record objects are not instantiated, so the object's callbacks are not
|
149
|
+
# executed, including any <tt>:dependent</tt> association options.
|
150
|
+
#
|
151
|
+
# You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
|
152
|
+
#
|
153
|
+
# Note: Although it is often much faster than the alternative, #destroy,
|
154
|
+
# skipping callbacks might bypass business logic in your application
|
155
|
+
# that ensures referential integrity or performs other essential jobs.
|
156
|
+
#
|
157
|
+
# ==== Examples
|
158
|
+
#
|
159
|
+
# # Delete a single row
|
160
|
+
# Todo.delete(1)
|
161
|
+
#
|
162
|
+
# # Delete multiple rows
|
163
|
+
# Todo.delete([2,3,4])
|
164
|
+
def delete(id_or_array)
|
165
|
+
where(primary_key => id_or_array).delete_all
|
166
|
+
end
|
167
|
+
|
168
|
+
def _insert_record(values) # :nodoc:
|
169
|
+
primary_key_value = nil
|
170
|
+
|
171
|
+
if primary_key && Hash === values
|
172
|
+
primary_key_value = values[primary_key]
|
173
|
+
|
174
|
+
if !primary_key_value && prefetch_primary_key?
|
175
|
+
primary_key_value = next_sequence_value
|
176
|
+
values[primary_key] = primary_key_value
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
if values.empty?
|
181
|
+
im = arel_table.compile_insert(connection.empty_insert_statement_value)
|
182
|
+
im.into arel_table
|
183
|
+
else
|
184
|
+
im = arel_table.compile_insert(_substitute_values(values))
|
185
|
+
end
|
186
|
+
|
187
|
+
connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
|
188
|
+
end
|
189
|
+
|
190
|
+
def _update_record(values, constraints) # :nodoc:
|
191
|
+
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
192
|
+
|
193
|
+
um = arel_table.where(
|
194
|
+
constraints.reduce(&:and)
|
195
|
+
).compile_update(_substitute_values(values), primary_key)
|
196
|
+
|
197
|
+
connection.update(um, "#{self} Update")
|
198
|
+
end
|
199
|
+
|
200
|
+
def _delete_record(constraints) # :nodoc:
|
201
|
+
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
202
|
+
|
203
|
+
dm = Arel::DeleteManager.new
|
204
|
+
dm.from(arel_table)
|
205
|
+
dm.wheres = constraints
|
206
|
+
|
207
|
+
connection.delete(dm, "#{self} Destroy")
|
208
|
+
end
|
209
|
+
|
72
210
|
private
|
73
211
|
# Called by +instantiate+ to decide which class to use for a new
|
74
212
|
# record instance.
|
@@ -78,6 +216,14 @@ module ActiveRecord
|
|
78
216
|
def discriminate_class_for_record(record)
|
79
217
|
self
|
80
218
|
end
|
219
|
+
|
220
|
+
def _substitute_values(values)
|
221
|
+
values.map do |name, value|
|
222
|
+
attr = arel_attribute(name)
|
223
|
+
bind = predicate_builder.build_bind_attribute(name, value)
|
224
|
+
[attr, bind]
|
225
|
+
end
|
226
|
+
end
|
81
227
|
end
|
82
228
|
|
83
229
|
# Returns true if this object hasn't been saved yet -- that is, a record
|
@@ -175,7 +321,7 @@ module ActiveRecord
|
|
175
321
|
# callbacks or any <tt>:dependent</tt> association
|
176
322
|
# options, use <tt>#destroy</tt>.
|
177
323
|
def delete
|
178
|
-
|
324
|
+
_delete_row if persisted?
|
179
325
|
@destroyed = true
|
180
326
|
freeze
|
181
327
|
end
|
@@ -224,9 +370,10 @@ module ActiveRecord
|
|
224
370
|
# Any change to the attributes on either instance will affect both instances.
|
225
371
|
# If you want to change the sti column as well, use #becomes! instead.
|
226
372
|
def becomes(klass)
|
227
|
-
became = klass.
|
373
|
+
became = klass.allocate
|
374
|
+
became.send(:initialize)
|
228
375
|
became.instance_variable_set("@attributes", @attributes)
|
229
|
-
became.instance_variable_set("@
|
376
|
+
became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
|
230
377
|
became.instance_variable_set("@changed_attributes", attributes_changed_by_setter)
|
231
378
|
became.instance_variable_set("@new_record", new_record?)
|
232
379
|
became.instance_variable_set("@destroyed", destroyed?)
|
@@ -326,13 +473,17 @@ module ActiveRecord
|
|
326
473
|
verify_readonly_attribute(key.to_s)
|
327
474
|
end
|
328
475
|
|
329
|
-
|
330
|
-
|
476
|
+
id_in_database = self.id_in_database
|
331
477
|
attributes.each do |k, v|
|
332
|
-
|
478
|
+
write_attribute_without_type_cast(k, v)
|
333
479
|
end
|
334
480
|
|
335
|
-
|
481
|
+
affected_rows = self.class._update_record(
|
482
|
+
attributes,
|
483
|
+
self.class.primary_key => id_in_database
|
484
|
+
)
|
485
|
+
|
486
|
+
affected_rows == 1
|
336
487
|
end
|
337
488
|
|
338
489
|
# Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
|
@@ -347,7 +498,7 @@ module ActiveRecord
|
|
347
498
|
# Wrapper around #increment that writes the update to the database.
|
348
499
|
# Only +attribute+ is updated; the record itself is not saved.
|
349
500
|
# This means that any other modified attributes will still be dirty.
|
350
|
-
# Validations and callbacks are skipped. Supports the
|
501
|
+
# Validations and callbacks are skipped. Supports the +touch+ option from
|
351
502
|
# +update_counters+, see that for more.
|
352
503
|
# Returns +self+.
|
353
504
|
def increment!(attribute, by = 1, touch: nil)
|
@@ -368,7 +519,7 @@ module ActiveRecord
|
|
368
519
|
# Wrapper around #decrement that writes the update to the database.
|
369
520
|
# Only +attribute+ is updated; the record itself is not saved.
|
370
521
|
# This means that any other modified attributes will still be dirty.
|
371
|
-
# Validations and callbacks are skipped. Supports the
|
522
|
+
# Validations and callbacks are skipped. Supports the +touch+ option from
|
372
523
|
# +update_counters+, see that for more.
|
373
524
|
# Returns +self+.
|
374
525
|
def decrement!(attribute, by = 1, touch: nil)
|
@@ -505,36 +656,12 @@ module ActiveRecord
|
|
505
656
|
MSG
|
506
657
|
end
|
507
658
|
|
508
|
-
|
509
|
-
|
510
|
-
attributes.concat(names)
|
659
|
+
attribute_names = timestamp_attributes_for_update_in_model
|
660
|
+
attribute_names |= names.map(&:to_s)
|
511
661
|
|
512
|
-
unless
|
513
|
-
|
514
|
-
|
515
|
-
attributes.each do |column|
|
516
|
-
column = column.to_s
|
517
|
-
changes[column] = write_attribute(column, time)
|
518
|
-
end
|
519
|
-
|
520
|
-
primary_key = self.class.primary_key
|
521
|
-
scope = self.class.unscoped.where(primary_key => _read_attribute(primary_key))
|
522
|
-
|
523
|
-
if locking_enabled?
|
524
|
-
locking_column = self.class.locking_column
|
525
|
-
scope = scope.where(locking_column => _read_attribute(locking_column))
|
526
|
-
changes[locking_column] = increment_lock
|
527
|
-
end
|
528
|
-
|
529
|
-
clear_attribute_changes(changes.keys)
|
530
|
-
result = scope.update_all(changes) == 1
|
531
|
-
|
532
|
-
if !result && locking_enabled?
|
533
|
-
raise ActiveRecord::StaleObjectError.new(self, "touch")
|
534
|
-
end
|
535
|
-
|
536
|
-
@_trigger_update_callback = result
|
537
|
-
result
|
662
|
+
unless attribute_names.empty?
|
663
|
+
affected_rows = _touch_row(attribute_names, time)
|
664
|
+
@_trigger_update_callback = affected_rows == 1
|
538
665
|
else
|
539
666
|
true
|
540
667
|
end
|
@@ -547,15 +674,34 @@ module ActiveRecord
|
|
547
674
|
end
|
548
675
|
|
549
676
|
def destroy_row
|
550
|
-
|
677
|
+
_delete_row
|
551
678
|
end
|
552
679
|
|
553
|
-
def
|
554
|
-
self.class.
|
680
|
+
def _delete_row
|
681
|
+
self.class._delete_record(self.class.primary_key => id_in_database)
|
682
|
+
end
|
683
|
+
|
684
|
+
def _touch_row(attribute_names, time)
|
685
|
+
time ||= current_time_from_proper_timezone
|
686
|
+
|
687
|
+
attribute_names.each do |attr_name|
|
688
|
+
write_attribute(attr_name, time)
|
689
|
+
clear_attribute_change(attr_name)
|
690
|
+
end
|
691
|
+
|
692
|
+
_update_row(attribute_names, "touch")
|
693
|
+
end
|
694
|
+
|
695
|
+
def _update_row(attribute_names, attempted_action = "update")
|
696
|
+
self.class._update_record(
|
697
|
+
attributes_with_values(attribute_names),
|
698
|
+
self.class.primary_key => id_in_database
|
699
|
+
)
|
555
700
|
end
|
556
701
|
|
557
702
|
def create_or_update(*args, &block)
|
558
703
|
_raise_readonly_record_error if readonly?
|
704
|
+
return false if destroyed?
|
559
705
|
result = new_record? ? _create_record(&block) : _update_record(*args, &block)
|
560
706
|
result != false
|
561
707
|
end
|
@@ -563,26 +709,29 @@ module ActiveRecord
|
|
563
709
|
# Updates the associated record with values matching those of the instance attributes.
|
564
710
|
# Returns the number of affected rows.
|
565
711
|
def _update_record(attribute_names = self.attribute_names)
|
566
|
-
|
567
|
-
|
568
|
-
|
712
|
+
attribute_names &= self.class.column_names
|
713
|
+
attribute_names = attributes_for_update(attribute_names)
|
714
|
+
|
715
|
+
if attribute_names.empty?
|
716
|
+
affected_rows = 0
|
569
717
|
@_trigger_update_callback = true
|
570
718
|
else
|
571
|
-
|
572
|
-
@_trigger_update_callback =
|
719
|
+
affected_rows = _update_row(attribute_names)
|
720
|
+
@_trigger_update_callback = affected_rows == 1
|
573
721
|
end
|
574
722
|
|
575
723
|
yield(self) if block_given?
|
576
724
|
|
577
|
-
|
725
|
+
affected_rows
|
578
726
|
end
|
579
727
|
|
580
728
|
# Creates a record with values matching those of the instance attributes
|
581
729
|
# and returns its id.
|
582
730
|
def _create_record(attribute_names = self.attribute_names)
|
583
|
-
|
731
|
+
attribute_names &= self.class.column_names
|
732
|
+
attributes_values = attributes_with_values_for_create(attribute_names)
|
584
733
|
|
585
|
-
new_id = self.class.
|
734
|
+
new_id = self.class._insert_record(attributes_values)
|
586
735
|
self.id ||= new_id if self.class.primary_key
|
587
736
|
|
588
737
|
@new_record = false
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Query Cache
|
3
5
|
class QueryCache
|
@@ -5,35 +7,31 @@ module ActiveRecord
|
|
5
7
|
# Enable the query cache within the block if Active Record is configured.
|
6
8
|
# If it's not, it will execute the given block.
|
7
9
|
def cache(&block)
|
8
|
-
if configurations.empty?
|
9
|
-
yield
|
10
|
-
else
|
10
|
+
if connected? || !configurations.empty?
|
11
11
|
connection.cache(&block)
|
12
|
+
else
|
13
|
+
yield
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
17
|
# Disable the query cache within the block if Active Record is configured.
|
16
18
|
# If it's not, it will execute the given block.
|
17
19
|
def uncached(&block)
|
18
|
-
if configurations.empty?
|
19
|
-
yield
|
20
|
-
else
|
20
|
+
if connected? || !configurations.empty?
|
21
21
|
connection.uncached(&block)
|
22
|
+
else
|
23
|
+
yield
|
22
24
|
end
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
28
|
def self.run
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
caching_pool.enable_query_cache!
|
31
|
-
|
32
|
-
[caching_pool, caching_was_enabled]
|
29
|
+
ActiveRecord::Base.connection_handler.connection_pool_list.
|
30
|
+
reject { |p| p.query_cache_enabled }.each { |p| p.enable_query_cache! }
|
33
31
|
end
|
34
32
|
|
35
|
-
def self.complete(
|
36
|
-
|
33
|
+
def self.complete(pools)
|
34
|
+
pools.each { |pool| pool.disable_query_cache! }
|
37
35
|
|
38
36
|
ActiveRecord::Base.connection_handler.connection_pool_list.each do |pool|
|
39
37
|
pool.release_connection if pool.active_connection? && !pool.connection.transaction_open?
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module Querying
|
3
5
|
delegate :find, :take, :take!, :first, :first!, :last, :last!, :exists?, :any?, :many?, :none?, :one?, to: :all
|
@@ -5,7 +7,7 @@ module ActiveRecord
|
|
5
7
|
delegate :first_or_create, :first_or_create!, :first_or_initialize, to: :all
|
6
8
|
delegate :find_or_create_by, :find_or_create_by!, :find_or_initialize_by, to: :all
|
7
9
|
delegate :find_by, :find_by!, to: :all
|
8
|
-
delegate :
|
10
|
+
delegate :destroy_all, :delete_all, :update_all, to: :all
|
9
11
|
delegate :find_each, :find_in_batches, :in_batches, to: :all
|
10
12
|
delegate :select, :group, :order, :except, :reorder, :limit, :offset, :joins, :left_joins, :left_outer_joins, :or,
|
11
13
|
:where, :rewhere, :preload, :eager_load, :includes, :from, :lock, :readonly, :extending,
|
@@ -38,7 +40,7 @@ module ActiveRecord
|
|
38
40
|
def find_by_sql(sql, binds = [], preparable: nil, &block)
|
39
41
|
result_set = connection.select_all(sanitize_sql(sql), "#{name} Load", binds, preparable: preparable)
|
40
42
|
column_types = result_set.column_types.dup
|
41
|
-
|
43
|
+
attribute_types.each_key { |k| column_types.delete k }
|
42
44
|
message_bus = ActiveSupport::Notifications.instrumenter
|
43
45
|
|
44
46
|
payload = {
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "active_record"
|
2
4
|
require "rails"
|
3
5
|
require "active_model/railtie"
|
@@ -26,6 +28,9 @@ module ActiveRecord
|
|
26
28
|
config.active_record.use_schema_cache_dump = true
|
27
29
|
config.active_record.maintain_test_schema = true
|
28
30
|
|
31
|
+
config.active_record.sqlite3 = ActiveSupport::OrderedOptions.new
|
32
|
+
config.active_record.sqlite3.represent_boolean_as_integer = nil
|
33
|
+
|
29
34
|
config.eager_load_namespaces << ActiveRecord
|
30
35
|
|
31
36
|
rake_tasks do
|
@@ -54,6 +59,7 @@ module ActiveRecord
|
|
54
59
|
console = ActiveSupport::Logger.new(STDERR)
|
55
60
|
Rails.logger.extend ActiveSupport::Logger.broadcast console
|
56
61
|
end
|
62
|
+
ActiveRecord::Base.verbose_query_logs = false
|
57
63
|
end
|
58
64
|
|
59
65
|
runner do
|
@@ -85,12 +91,16 @@ module ActiveRecord
|
|
85
91
|
filename = File.join(app.config.paths["db"].first, "schema_cache.yml")
|
86
92
|
|
87
93
|
if File.file?(filename)
|
94
|
+
current_version = ActiveRecord::Migrator.current_version
|
95
|
+
|
96
|
+
next if current_version.nil?
|
97
|
+
|
88
98
|
cache = YAML.load(File.read(filename))
|
89
|
-
if cache.version ==
|
99
|
+
if cache.version == current_version
|
90
100
|
connection.schema_cache = cache
|
91
101
|
connection_pool.schema_cache = cache.dup
|
92
102
|
else
|
93
|
-
warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{
|
103
|
+
warn "Ignoring db/schema_cache.yml because it has expired. The current schema version is #{current_version}, but the one in the cache is #{cache.version}."
|
94
104
|
end
|
95
105
|
end
|
96
106
|
end
|
@@ -108,7 +118,9 @@ module ActiveRecord
|
|
108
118
|
|
109
119
|
initializer "active_record.set_configs" do |app|
|
110
120
|
ActiveSupport.on_load(:active_record) do
|
111
|
-
app.config.active_record.
|
121
|
+
configs = app.config.active_record.dup
|
122
|
+
configs.delete(:sqlite3)
|
123
|
+
configs.each do |k, v|
|
112
124
|
send "#{k}=", v
|
113
125
|
end
|
114
126
|
end
|
@@ -157,14 +169,76 @@ end_warning
|
|
157
169
|
end
|
158
170
|
|
159
171
|
initializer "active_record.set_executor_hooks" do
|
160
|
-
|
161
|
-
ActiveRecord::QueryCache.install_executor_hooks
|
162
|
-
end
|
172
|
+
ActiveRecord::QueryCache.install_executor_hooks
|
163
173
|
end
|
164
174
|
|
165
175
|
initializer "active_record.add_watchable_files" do |app|
|
166
176
|
path = app.paths["db"].first
|
167
177
|
config.watchable_files.concat ["#{path}/schema.rb", "#{path}/structure.sql"]
|
168
178
|
end
|
179
|
+
|
180
|
+
initializer "active_record.clear_active_connections" do
|
181
|
+
config.after_initialize do
|
182
|
+
ActiveSupport.on_load(:active_record) do
|
183
|
+
# Ideally the application doesn't connect to the database during boot,
|
184
|
+
# but sometimes it does. In case it did, we want to empty out the
|
185
|
+
# connection pools so that a non-database-using process (e.g. a master
|
186
|
+
# process in a forking server model) doesn't retain a needless
|
187
|
+
# connection. If it was needed, the incremental cost of reestablishing
|
188
|
+
# this connection is trivial: the rest of the pool would need to be
|
189
|
+
# populated anyway.
|
190
|
+
|
191
|
+
clear_active_connections!
|
192
|
+
flush_idle_connections!
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
initializer "active_record.check_represent_sqlite3_boolean_as_integer" do
|
198
|
+
config.after_initialize do
|
199
|
+
ActiveSupport.on_load(:active_record_sqlite3adapter) do
|
200
|
+
represent_boolean_as_integer = Rails.application.config.active_record.sqlite3.delete(:represent_boolean_as_integer)
|
201
|
+
unless represent_boolean_as_integer.nil?
|
202
|
+
ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer = represent_boolean_as_integer
|
203
|
+
end
|
204
|
+
|
205
|
+
unless ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer
|
206
|
+
ActiveSupport::Deprecation.warn <<-MSG
|
207
|
+
Leaving `ActiveRecord::ConnectionAdapters::SQLite3Adapter.represent_boolean_as_integer`
|
208
|
+
set to false is deprecated. SQLite databases have used 't' and 'f' to serialize
|
209
|
+
boolean values and must have old data converted to 1 and 0 (its native boolean
|
210
|
+
serialization) before setting this flag to true. Conversion can be accomplished
|
211
|
+
by setting up a rake task which runs
|
212
|
+
|
213
|
+
ExampleModel.where("boolean_column = 't'").update_all(boolean_column: 1)
|
214
|
+
ExampleModel.where("boolean_column = 'f'").update_all(boolean_column: 0)
|
215
|
+
|
216
|
+
for all models and all boolean columns, after which the flag must be set to
|
217
|
+
true by adding the following to your application.rb file:
|
218
|
+
|
219
|
+
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
|
220
|
+
MSG
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
initializer "active_record.use_yaml_unsafe_load" do |app|
|
227
|
+
config.after_initialize do
|
228
|
+
unless app.config.active_record.use_yaml_unsafe_load.nil?
|
229
|
+
ActiveRecord::Base.use_yaml_unsafe_load =
|
230
|
+
app.config.active_record.use_yaml_unsafe_load
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
initializer "active_record.yaml_column_permitted_classes" do |app|
|
236
|
+
config.after_initialize do
|
237
|
+
unless app.config.active_record.yaml_column_permitted_classes.nil?
|
238
|
+
ActiveRecord::Base.yaml_column_permitted_classes =
|
239
|
+
app.config.active_record.yaml_column_permitted_classes
|
240
|
+
end
|
241
|
+
end
|
242
|
+
end
|
169
243
|
end
|
170
244
|
end
|