activerecord 6.1.6 → 7.0.4
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 +1314 -975
- data/README.rdoc +1 -1
- data/lib/active_record/aggregations.rb +1 -1
- data/lib/active_record/association_relation.rb +0 -10
- data/lib/active_record/associations/association.rb +33 -17
- data/lib/active_record/associations/association_scope.rb +1 -3
- data/lib/active_record/associations/belongs_to_association.rb +15 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +8 -2
- data/lib/active_record/associations/builder/belongs_to.rb +19 -6
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_many.rb +3 -2
- data/lib/active_record/associations/builder/has_one.rb +2 -1
- data/lib/active_record/associations/builder/singular_association.rb +2 -2
- data/lib/active_record/associations/collection_association.rb +19 -21
- data/lib/active_record/associations/collection_proxy.rb +10 -5
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/has_many_association.rb +8 -5
- data/lib/active_record/associations/has_many_through_association.rb +2 -1
- data/lib/active_record/associations/has_one_association.rb +10 -7
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +23 -15
- data/lib/active_record/associations/preloader/association.rb +186 -52
- data/lib/active_record/associations/preloader/batch.rb +48 -0
- data/lib/active_record/associations/preloader/branch.rb +147 -0
- data/lib/active_record/associations/preloader/through_association.rb +49 -13
- data/lib/active_record/associations/preloader.rb +39 -113
- data/lib/active_record/associations/singular_association.rb +8 -2
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +124 -95
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -1
- data/lib/active_record/attribute_methods/before_type_cast.rb +7 -2
- data/lib/active_record/attribute_methods/dirty.rb +49 -16
- 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 +7 -5
- data/lib/active_record/attribute_methods/serialization.rb +57 -19
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +7 -10
- data/lib/active_record/attribute_methods.rb +14 -15
- data/lib/active_record/attributes.rb +24 -35
- data/lib/active_record/autosave_association.rb +8 -23
- data/lib/active_record/base.rb +19 -1
- data/lib/active_record/callbacks.rb +2 -2
- data/lib/active_record/coders/yaml_column.rb +10 -2
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +292 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +209 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +76 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +47 -561
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +0 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +46 -22
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/quoting.rb +42 -72
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +4 -17
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +38 -13
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +80 -24
- data/lib/active_record/connection_adapters/abstract/transaction.rb +15 -22
- data/lib/active_record/connection_adapters/abstract_adapter.rb +149 -74
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +105 -81
- data/lib/active_record/connection_adapters/column.rb +4 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +36 -24
- data/lib/active_record/connection_adapters/mysql/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +7 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +20 -1
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +12 -6
- data/lib/active_record/connection_adapters/pool_config.rb +7 -7
- data/lib/active_record/connection_adapters/postgresql/column.rb +17 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +19 -12
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +8 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +5 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +53 -14
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/timestamp_with_time_zone.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +18 -6
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +51 -51
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +21 -1
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +22 -1
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +37 -19
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +208 -107
- data/lib/active_record/connection_adapters/schema_cache.rb +39 -38
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +25 -19
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +28 -16
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +17 -15
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +96 -32
- data/lib/active_record/connection_adapters.rb +6 -5
- data/lib/active_record/connection_handling.rb +49 -55
- data/lib/active_record/core.rb +124 -134
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +12 -9
- data/lib/active_record/database_configurations/hash_config.rb +63 -5
- data/lib/active_record/database_configurations/url_config.rb +2 -2
- data/lib/active_record/database_configurations.rb +15 -32
- data/lib/active_record/delegated_type.rb +53 -12
- data/lib/active_record/destroy_association_async_job.rb +1 -1
- data/lib/active_record/disable_joins_association_relation.rb +39 -0
- data/lib/active_record/dynamic_matchers.rb +1 -1
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +98 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +44 -0
- data/lib/active_record/encryption/configurable.rb +67 -0
- data/lib/active_record/encryption/context.rb +35 -0
- data/lib/active_record/encryption/contexts.rb +72 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +12 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +206 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +140 -0
- data/lib/active_record/encryption/encrypted_fixtures.rb +38 -0
- data/lib/active_record/encryption/encrypting_only_encryptor.rb +12 -0
- data/lib/active_record/encryption/encryptor.rb +155 -0
- data/lib/active_record/encryption/envelope_encryption_key_provider.rb +55 -0
- data/lib/active_record/encryption/errors.rb +15 -0
- data/lib/active_record/encryption/extended_deterministic_queries.rb +160 -0
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +28 -0
- data/lib/active_record/encryption/key.rb +28 -0
- data/lib/active_record/encryption/key_generator.rb +42 -0
- data/lib/active_record/encryption/key_provider.rb +46 -0
- data/lib/active_record/encryption/message.rb +33 -0
- data/lib/active_record/encryption/message_serializer.rb +90 -0
- data/lib/active_record/encryption/null_encryptor.rb +21 -0
- data/lib/active_record/encryption/properties.rb +76 -0
- data/lib/active_record/encryption/read_only_null_encryptor.rb +24 -0
- data/lib/active_record/encryption/scheme.rb +99 -0
- data/lib/active_record/encryption.rb +55 -0
- data/lib/active_record/enum.rb +50 -43
- data/lib/active_record/errors.rb +67 -4
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/fixture_set/file.rb +15 -1
- data/lib/active_record/fixture_set/table_row.rb +41 -6
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +20 -23
- data/lib/active_record/future_result.rb +139 -0
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +55 -17
- data/lib/active_record/insert_all.rb +80 -14
- data/lib/active_record/integration.rb +4 -3
- data/lib/active_record/internal_metadata.rb +1 -5
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +10 -9
- data/lib/active_record/locking/pessimistic.rb +10 -4
- data/lib/active_record/log_subscriber.rb +23 -7
- data/lib/active_record/middleware/database_selector/resolver.rb +6 -10
- data/lib/active_record/middleware/database_selector.rb +18 -6
- data/lib/active_record/middleware/shard_selector.rb +60 -0
- data/lib/active_record/migration/command_recorder.rb +7 -7
- data/lib/active_record/migration/compatibility.rb +84 -2
- data/lib/active_record/migration/join_table.rb +1 -1
- data/lib/active_record/migration.rb +114 -83
- data/lib/active_record/model_schema.rb +58 -59
- data/lib/active_record/nested_attributes.rb +13 -12
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/null_relation.rb +2 -6
- data/lib/active_record/persistence.rb +228 -60
- data/lib/active_record/query_cache.rb +2 -2
- data/lib/active_record/query_logs.rb +138 -0
- data/lib/active_record/querying.rb +16 -6
- data/lib/active_record/railtie.rb +136 -22
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +78 -136
- data/lib/active_record/readonly_attributes.rb +11 -0
- data/lib/active_record/reflection.rb +73 -50
- data/lib/active_record/relation/batches/batch_enumerator.rb +19 -5
- data/lib/active_record/relation/batches.rb +6 -6
- data/lib/active_record/relation/calculations.rb +43 -38
- data/lib/active_record/relation/delegation.rb +7 -7
- data/lib/active_record/relation/finder_methods.rb +31 -35
- data/lib/active_record/relation/merger.rb +20 -13
- data/lib/active_record/relation/predicate_builder.rb +1 -6
- data/lib/active_record/relation/query_attribute.rb +5 -11
- data/lib/active_record/relation/query_methods.rb +276 -67
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +2 -2
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +189 -88
- data/lib/active_record/result.rb +17 -7
- data/lib/active_record/runtime_registry.rb +9 -13
- data/lib/active_record/sanitization.rb +17 -12
- data/lib/active_record/schema.rb +38 -23
- data/lib/active_record/schema_dumper.rb +25 -19
- data/lib/active_record/schema_migration.rb +4 -4
- data/lib/active_record/scoping/default.rb +60 -13
- data/lib/active_record/scoping/named.rb +3 -11
- data/lib/active_record/scoping.rb +64 -34
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +3 -3
- data/lib/active_record/store.rb +7 -2
- data/lib/active_record/suppressor.rb +11 -15
- data/lib/active_record/tasks/database_tasks.rb +127 -60
- data/lib/active_record/tasks/mysql_database_tasks.rb +1 -1
- data/lib/active_record/tasks/postgresql_database_tasks.rb +19 -13
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +16 -9
- data/lib/active_record/timestamp.rb +3 -4
- data/lib/active_record/transactions.rb +9 -14
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -7
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +2 -2
- data/lib/active_record/type/serialized.rb +1 -1
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/associated.rb +4 -4
- data/lib/active_record/validations/presence.rb +2 -2
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +217 -27
- data/lib/arel/attributes/attribute.rb +0 -8
- data/lib/arel/crud.rb +28 -22
- data/lib/arel/delete_manager.rb +18 -4
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/casted.rb +1 -1
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +1 -0
- data/lib/arel/predications.rb +11 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +0 -1
- data/lib/arel/tree_manager.rb +0 -12
- data/lib/arel/update_manager.rb +18 -4
- data/lib/arel/visitors/dot.rb +80 -90
- data/lib/arel/visitors/mysql.rb +8 -2
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +58 -2
- data/lib/arel.rb +2 -1
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +1 -1
- data/lib/rails/generators/active_record/model/templates/module.rb.tt +2 -2
- data/lib/rails/generators/active_record/multi_db/multi_db_generator.rb +16 -0
- data/lib/rails/generators/active_record/multi_db/templates/multi_db.rb.tt +44 -0
- metadata +55 -11
@@ -54,7 +54,7 @@ module ActiveRecord
|
|
54
54
|
# Accepts an array, or string of SQL conditions and sanitizes
|
55
55
|
# them into a valid SQL fragment for an ORDER clause.
|
56
56
|
#
|
57
|
-
# sanitize_sql_for_order(["field(id, ?)", [1,3,2]])
|
57
|
+
# sanitize_sql_for_order([Arel.sql("field(id, ?)"), [1,3,2]])
|
58
58
|
# # => "field(id, 1,3,2)"
|
59
59
|
#
|
60
60
|
# sanitize_sql_for_order("id ASC")
|
@@ -92,16 +92,17 @@ module ActiveRecord
|
|
92
92
|
end
|
93
93
|
|
94
94
|
# Sanitizes a +string+ so that it is safe to use within an SQL
|
95
|
-
# LIKE statement. This method uses +escape_character+ to escape all
|
95
|
+
# LIKE statement. This method uses +escape_character+ to escape all
|
96
|
+
# occurrences of itself, "_" and "%".
|
96
97
|
#
|
97
|
-
# sanitize_sql_like("100%")
|
98
|
-
# # => "100\\%"
|
98
|
+
# sanitize_sql_like("100% true!")
|
99
|
+
# # => "100\\% true!"
|
99
100
|
#
|
100
101
|
# sanitize_sql_like("snake_cased_string")
|
101
102
|
# # => "snake\\_cased\\_string"
|
102
103
|
#
|
103
|
-
# sanitize_sql_like("100%", "!")
|
104
|
-
# # => "100!%"
|
104
|
+
# sanitize_sql_like("100% true!", "!")
|
105
|
+
# # => "100!% true!!"
|
105
106
|
#
|
106
107
|
# sanitize_sql_like("snake_cased_string", "!")
|
107
108
|
# # => "snake!_cased!_string"
|
@@ -137,14 +138,18 @@ module ActiveRecord
|
|
137
138
|
def disallow_raw_sql!(args, permit: connection.column_name_matcher) # :nodoc:
|
138
139
|
unexpected = nil
|
139
140
|
args.each do |arg|
|
140
|
-
next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s)
|
141
|
+
next if arg.is_a?(Symbol) || Arel.arel_node?(arg) || permit.match?(arg.to_s.strip)
|
141
142
|
(unexpected ||= []) << arg
|
142
143
|
end
|
143
144
|
|
144
145
|
if unexpected
|
145
146
|
raise(ActiveRecord::UnknownAttributeReference,
|
146
|
-
"
|
147
|
-
|
147
|
+
"Dangerous query method (method whose arguments are used as raw " \
|
148
|
+
"SQL) called with non-attribute argument(s): " \
|
149
|
+
"#{unexpected.map(&:inspect).join(", ")}." \
|
150
|
+
"This method should not be called with user-provided values, such as request " \
|
151
|
+
"parameters or model attributes. Known-safe values can be passed " \
|
152
|
+
"by wrapping them in Arel.sql()."
|
148
153
|
)
|
149
154
|
end
|
150
155
|
end
|
@@ -183,13 +188,13 @@ module ActiveRecord
|
|
183
188
|
if value.respond_to?(:map) && !value.acts_like?(:string)
|
184
189
|
values = value.map { |v| v.respond_to?(:id_for_database) ? v.id_for_database : v }
|
185
190
|
if values.empty?
|
186
|
-
c.
|
191
|
+
c.quote_bound_value(nil)
|
187
192
|
else
|
188
|
-
values.map! { |v| c.
|
193
|
+
values.map! { |v| c.quote_bound_value(v) }.join(",")
|
189
194
|
end
|
190
195
|
else
|
191
196
|
value = value.id_for_database if value.respond_to?(:id_for_database)
|
192
|
-
c.
|
197
|
+
c.quote_bound_value(value)
|
193
198
|
end
|
194
199
|
end
|
195
200
|
|
data/lib/active_record/schema.rb
CHANGED
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
#
|
11
11
|
# Usage:
|
12
12
|
#
|
13
|
-
# ActiveRecord::Schema.define do
|
13
|
+
# ActiveRecord::Schema[7.0].define do
|
14
14
|
# create_table :authors do |t|
|
15
15
|
# t.string :name, null: false
|
16
16
|
# end
|
@@ -30,32 +30,47 @@ module ActiveRecord
|
|
30
30
|
# ActiveRecord::Schema is only supported by database adapters that also
|
31
31
|
# support migrations, the two features being very similar.
|
32
32
|
class Schema < Migration::Current
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
33
|
+
module Definition
|
34
|
+
extend ActiveSupport::Concern
|
35
|
+
|
36
|
+
module ClassMethods
|
37
|
+
# Eval the given block. All methods available to the current connection
|
38
|
+
# adapter are available within the block, so you can easily use the
|
39
|
+
# database definition DSL to build up your schema (
|
40
|
+
# {create_table}[rdoc-ref:ConnectionAdapters::SchemaStatements#create_table],
|
41
|
+
# {add_index}[rdoc-ref:ConnectionAdapters::SchemaStatements#add_index], etc.).
|
42
|
+
#
|
43
|
+
# The +info+ hash is optional, and if given is used to define metadata
|
44
|
+
# about the current schema (currently, only the schema's version):
|
45
|
+
#
|
46
|
+
# ActiveRecord::Schema[7.0].define(version: 2038_01_19_000001) do
|
47
|
+
# ...
|
48
|
+
# end
|
49
|
+
def define(info = {}, &block)
|
50
|
+
new.define(info, &block)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def define(info, &block) # :nodoc:
|
55
|
+
instance_eval(&block)
|
48
56
|
|
49
|
-
|
50
|
-
|
57
|
+
if info[:version].present?
|
58
|
+
connection.schema_migration.create_table
|
59
|
+
connection.assume_migrated_upto_version(info[:version])
|
60
|
+
end
|
51
61
|
|
52
|
-
|
53
|
-
connection.
|
54
|
-
connection.assume_migrated_upto_version(info[:version])
|
62
|
+
ActiveRecord::InternalMetadata.create_table
|
63
|
+
ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
|
55
64
|
end
|
65
|
+
end
|
66
|
+
|
67
|
+
include Definition
|
56
68
|
|
57
|
-
|
58
|
-
|
69
|
+
def self.[](version)
|
70
|
+
@class_for_version ||= {}
|
71
|
+
@class_for_version[version] ||= Class.new(Migration::Compatibility.find(version)) do
|
72
|
+
include Definition
|
73
|
+
end
|
59
74
|
end
|
60
75
|
end
|
61
76
|
end
|
@@ -7,14 +7,14 @@ module ActiveRecord
|
|
7
7
|
#
|
8
8
|
# This class is used to dump the database schema for some connection to some
|
9
9
|
# output format (i.e., ActiveRecord::Schema).
|
10
|
-
class SchemaDumper
|
10
|
+
class SchemaDumper # :nodoc:
|
11
11
|
private_class_method :new
|
12
12
|
|
13
13
|
##
|
14
14
|
# :singleton-method:
|
15
15
|
# A list of tables which should not be dumped to the schema.
|
16
|
-
# Acceptable values are strings as well as regexp if ActiveRecord
|
17
|
-
# Only strings are accepted if ActiveRecord
|
16
|
+
# Acceptable values are strings as well as regexp if ActiveRecord.schema_format == :ruby.
|
17
|
+
# Only strings are accepted if ActiveRecord.schema_format == :sql.
|
18
18
|
cattr_accessor :ignore_tables, default: []
|
19
19
|
|
20
20
|
##
|
@@ -47,6 +47,7 @@ module ActiveRecord
|
|
47
47
|
def dump(stream)
|
48
48
|
header(stream)
|
49
49
|
extensions(stream)
|
50
|
+
types(stream)
|
50
51
|
tables(stream)
|
51
52
|
trailer(stream)
|
52
53
|
stream
|
@@ -73,22 +74,21 @@ module ActiveRecord
|
|
73
74
|
end
|
74
75
|
|
75
76
|
def header(stream)
|
76
|
-
stream.puts
|
77
|
-
# This file is auto-generated from the current state of the database. Instead
|
78
|
-
# of editing this file, please use the migrations feature of Active Record to
|
79
|
-
# incrementally modify your database, and then regenerate this schema definition.
|
80
|
-
#
|
81
|
-
# This file is the source Rails uses to define your schema when running `bin/rails
|
82
|
-
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
83
|
-
# be faster and is potentially less error prone than running all of your
|
84
|
-
# migrations from scratch. Old migrations may fail to apply correctly if those
|
85
|
-
# migrations use external dependencies or application code.
|
86
|
-
#
|
87
|
-
# It's strongly recommended that you check this file into your version control system.
|
88
|
-
|
89
|
-
ActiveRecord::Schema.define(#{define_params}) do
|
90
|
-
|
91
|
-
HEADER
|
77
|
+
stream.puts <<~HEADER
|
78
|
+
# This file is auto-generated from the current state of the database. Instead
|
79
|
+
# of editing this file, please use the migrations feature of Active Record to
|
80
|
+
# incrementally modify your database, and then regenerate this schema definition.
|
81
|
+
#
|
82
|
+
# This file is the source Rails uses to define your schema when running `bin/rails
|
83
|
+
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
|
84
|
+
# be faster and is potentially less error prone than running all of your
|
85
|
+
# migrations from scratch. Old migrations may fail to apply correctly if those
|
86
|
+
# migrations use external dependencies or application code.
|
87
|
+
#
|
88
|
+
# It's strongly recommended that you check this file into your version control system.
|
89
|
+
|
90
|
+
ActiveRecord::Schema[#{ActiveRecord::Migration.current_version}].define(#{define_params}) do
|
91
|
+
HEADER
|
92
92
|
end
|
93
93
|
|
94
94
|
def trailer(stream)
|
@@ -99,6 +99,10 @@ HEADER
|
|
99
99
|
def extensions(stream)
|
100
100
|
end
|
101
101
|
|
102
|
+
# (enum) types are only supported by PostgreSQL
|
103
|
+
def types(stream)
|
104
|
+
end
|
105
|
+
|
102
106
|
def tables(stream)
|
103
107
|
sorted_tables = @connection.tables.sort
|
104
108
|
|
@@ -154,6 +158,7 @@ HEADER
|
|
154
158
|
columns.each do |column|
|
155
159
|
raise StandardError, "Unknown type '#{column.sql_type}' for column '#{column.name}'" unless @connection.valid_type?(column.type)
|
156
160
|
next if column.name == pk
|
161
|
+
|
157
162
|
type, colspec = column_spec(column)
|
158
163
|
if type.is_a?(Symbol)
|
159
164
|
tbl.print " t.#{type} #{column.name.inspect}"
|
@@ -259,6 +264,7 @@ HEADER
|
|
259
264
|
|
260
265
|
parts << "on_update: #{foreign_key.on_update.inspect}" if foreign_key.on_update
|
261
266
|
parts << "on_delete: #{foreign_key.on_delete.inspect}" if foreign_key.on_delete
|
267
|
+
parts << "deferrable: #{foreign_key.deferrable.inspect}" if foreign_key.deferrable
|
262
268
|
|
263
269
|
" #{parts.join(', ')}"
|
264
270
|
end
|
@@ -10,10 +10,6 @@ module ActiveRecord
|
|
10
10
|
# to be executed the next time.
|
11
11
|
class SchemaMigration < ActiveRecord::Base # :nodoc:
|
12
12
|
class << self
|
13
|
-
def _internal?
|
14
|
-
true
|
15
|
-
end
|
16
|
-
|
17
13
|
def primary_key
|
18
14
|
"version"
|
19
15
|
end
|
@@ -45,6 +41,10 @@ module ActiveRecord
|
|
45
41
|
def all_versions
|
46
42
|
order(:version).pluck(:version)
|
47
43
|
end
|
44
|
+
|
45
|
+
def table_exists?
|
46
|
+
connection.data_source_exists?(table_name)
|
47
|
+
end
|
48
48
|
end
|
49
49
|
|
50
50
|
def version
|
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module Scoping
|
5
|
+
class DefaultScope # :nodoc:
|
6
|
+
attr_reader :scope, :all_queries
|
7
|
+
|
8
|
+
def initialize(scope, all_queries = nil)
|
9
|
+
@scope = scope
|
10
|
+
@all_queries = all_queries
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
5
14
|
module Default
|
6
15
|
extend ActiveSupport::Concern
|
7
16
|
|
@@ -30,8 +39,8 @@ module ActiveRecord
|
|
30
39
|
# Post.unscoped {
|
31
40
|
# Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10"
|
32
41
|
# }
|
33
|
-
def unscoped
|
34
|
-
block_given? ? relation.scoping
|
42
|
+
def unscoped(&block)
|
43
|
+
block_given? ? relation.scoping(&block) : relation
|
35
44
|
end
|
36
45
|
|
37
46
|
# Are there attributes associated with this scope?
|
@@ -39,8 +48,15 @@ module ActiveRecord
|
|
39
48
|
super || default_scopes.any? || respond_to?(:default_scope)
|
40
49
|
end
|
41
50
|
|
42
|
-
|
43
|
-
|
51
|
+
# Checks if the model has any default scopes. If all_queries
|
52
|
+
# is set to true, the method will check if there are any
|
53
|
+
# default_scopes for the model where +all_queries+ is true.
|
54
|
+
def default_scopes?(all_queries: false)
|
55
|
+
if all_queries
|
56
|
+
self.default_scopes.any?(&:all_queries)
|
57
|
+
else
|
58
|
+
self.default_scopes.any?
|
59
|
+
end
|
44
60
|
end
|
45
61
|
|
46
62
|
private
|
@@ -54,11 +70,26 @@ module ActiveRecord
|
|
54
70
|
# Article.all # => SELECT * FROM articles WHERE published = true
|
55
71
|
#
|
56
72
|
# The #default_scope is also applied while creating/building a record.
|
57
|
-
# It is not applied while updating a record.
|
73
|
+
# It is not applied while updating or deleting a record.
|
58
74
|
#
|
59
75
|
# Article.new.published # => true
|
60
76
|
# Article.create.published # => true
|
61
77
|
#
|
78
|
+
# To apply a #default_scope when updating or deleting a record, add
|
79
|
+
# <tt>all_queries: true</tt>:
|
80
|
+
#
|
81
|
+
# class Article < ActiveRecord::Base
|
82
|
+
# default_scope -> { where(blog_id: 1) }, all_queries: true
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# Applying a default scope to all queries will ensure that records
|
86
|
+
# are always queried by the additional conditions. Note that only
|
87
|
+
# where clauses apply, as it does not make sense to add order to
|
88
|
+
# queries that return a single object by primary key.
|
89
|
+
#
|
90
|
+
# Article.find(1).destroy
|
91
|
+
# => DELETE ... FROM `articles` where ID = 1 AND blog_id = 1;
|
92
|
+
#
|
62
93
|
# (You can also pass any object which responds to +call+ to the
|
63
94
|
# +default_scope+ macro, and it will be called when building the
|
64
95
|
# default scope.)
|
@@ -85,7 +116,7 @@ module ActiveRecord
|
|
85
116
|
# # Should return a scope, you can call 'super' here etc.
|
86
117
|
# end
|
87
118
|
# end
|
88
|
-
def default_scope(scope = nil, &block) # :doc:
|
119
|
+
def default_scope(scope = nil, all_queries: nil, &block) # :doc:
|
89
120
|
scope = block if block_given?
|
90
121
|
|
91
122
|
if scope.is_a?(Relation) || !scope.respond_to?(:call)
|
@@ -96,10 +127,12 @@ module ActiveRecord
|
|
96
127
|
"self.default_scope.)"
|
97
128
|
end
|
98
129
|
|
99
|
-
|
130
|
+
default_scope = DefaultScope.new(scope, all_queries)
|
131
|
+
|
132
|
+
self.default_scopes += [default_scope]
|
100
133
|
end
|
101
134
|
|
102
|
-
def build_default_scope(relation = relation())
|
135
|
+
def build_default_scope(relation = relation(), all_queries: nil)
|
103
136
|
return if abstract_class?
|
104
137
|
|
105
138
|
if default_scope_override.nil?
|
@@ -113,20 +146,34 @@ module ActiveRecord
|
|
113
146
|
end
|
114
147
|
elsif default_scopes.any?
|
115
148
|
evaluate_default_scope do
|
116
|
-
default_scopes.inject(relation) do |
|
117
|
-
|
118
|
-
|
149
|
+
default_scopes.inject(relation) do |combined_scope, scope_obj|
|
150
|
+
if execute_scope?(all_queries, scope_obj)
|
151
|
+
scope = scope_obj.scope.respond_to?(:to_proc) ? scope_obj.scope : scope_obj.scope.method(:call)
|
152
|
+
|
153
|
+
combined_scope.instance_exec(&scope) || combined_scope
|
154
|
+
else
|
155
|
+
combined_scope
|
156
|
+
end
|
119
157
|
end
|
120
158
|
end
|
121
159
|
end
|
122
160
|
end
|
123
161
|
|
162
|
+
# If all_queries is nil, only execute on select and insert queries.
|
163
|
+
#
|
164
|
+
# If all_queries is true, check if the default_scope object has
|
165
|
+
# all_queries set, then execute on all queries; select, insert, update
|
166
|
+
# and delete.
|
167
|
+
def execute_scope?(all_queries, default_scope_obj)
|
168
|
+
all_queries.nil? || all_queries && default_scope_obj.all_queries
|
169
|
+
end
|
170
|
+
|
124
171
|
def ignore_default_scope?
|
125
|
-
ScopeRegistry.
|
172
|
+
ScopeRegistry.ignore_default_scope(base_class)
|
126
173
|
end
|
127
174
|
|
128
175
|
def ignore_default_scope=(ignore)
|
129
|
-
ScopeRegistry.
|
176
|
+
ScopeRegistry.set_ignore_default_scope(base_class, ignore)
|
130
177
|
end
|
131
178
|
|
132
179
|
# The ignore_default_scope flag is used to prevent an infinite recursion
|
@@ -42,8 +42,8 @@ module ActiveRecord
|
|
42
42
|
end
|
43
43
|
|
44
44
|
# Returns a scope for the model with default scopes.
|
45
|
-
def default_scoped(scope = relation)
|
46
|
-
build_default_scope(scope) || scope
|
45
|
+
def default_scoped(scope = relation, all_queries: nil)
|
46
|
+
build_default_scope(scope, all_queries: all_queries) || scope
|
47
47
|
end
|
48
48
|
|
49
49
|
def default_extensions # :nodoc:
|
@@ -168,7 +168,6 @@ module ActiveRecord
|
|
168
168
|
"an instance method with the same name."
|
169
169
|
end
|
170
170
|
|
171
|
-
valid_scope_name?(name)
|
172
171
|
extension = Module.new(&block) if block
|
173
172
|
|
174
173
|
if body.respond_to?(:to_proc)
|
@@ -184,7 +183,7 @@ module ActiveRecord
|
|
184
183
|
scope
|
185
184
|
end
|
186
185
|
end
|
187
|
-
singleton_class.send(:ruby2_keywords, name)
|
186
|
+
singleton_class.send(:ruby2_keywords, name)
|
188
187
|
|
189
188
|
generate_relation_method(name)
|
190
189
|
end
|
@@ -193,13 +192,6 @@ module ActiveRecord
|
|
193
192
|
def singleton_method_added(name)
|
194
193
|
generate_relation_method(name) if Kernel.respond_to?(name) && !ActiveRecord::Relation.method_defined?(name)
|
195
194
|
end
|
196
|
-
|
197
|
-
def valid_scope_name?(name)
|
198
|
-
if respond_to?(name, true) && logger
|
199
|
-
logger.warn "Creating scope :#{name}. " \
|
200
|
-
"Overwriting existing method #{self.name}.#{name}."
|
201
|
-
end
|
202
|
-
end
|
203
195
|
end
|
204
196
|
end
|
205
197
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/
|
3
|
+
require "active_support/core_ext/module/delegation"
|
4
4
|
|
5
5
|
module ActiveRecord
|
6
6
|
module Scoping
|
@@ -24,11 +24,23 @@ module ActiveRecord
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def current_scope(skip_inherited_scope = false)
|
27
|
-
ScopeRegistry.
|
27
|
+
ScopeRegistry.current_scope(self, skip_inherited_scope)
|
28
28
|
end
|
29
29
|
|
30
30
|
def current_scope=(scope)
|
31
|
-
ScopeRegistry.
|
31
|
+
ScopeRegistry.set_current_scope(self, scope)
|
32
|
+
end
|
33
|
+
|
34
|
+
def global_current_scope(skip_inherited_scope = false)
|
35
|
+
ScopeRegistry.global_current_scope(self, skip_inherited_scope)
|
36
|
+
end
|
37
|
+
|
38
|
+
def global_current_scope=(scope)
|
39
|
+
ScopeRegistry.set_global_current_scope(self, scope)
|
40
|
+
end
|
41
|
+
|
42
|
+
def scope_registry
|
43
|
+
ScopeRegistry.instance
|
32
44
|
end
|
33
45
|
end
|
34
46
|
|
@@ -45,8 +57,8 @@ module ActiveRecord
|
|
45
57
|
end
|
46
58
|
|
47
59
|
# This class stores the +:current_scope+ and +:ignore_default_scope+ values
|
48
|
-
# for different classes. The registry is stored as a thread
|
49
|
-
#
|
60
|
+
# for different classes. The registry is stored as either a thread or fiber
|
61
|
+
# local depending on the application configuration.
|
50
62
|
#
|
51
63
|
# This class allows you to store and get the scope values on different
|
52
64
|
# classes and different types of scopes. For example, if you are attempting
|
@@ -54,52 +66,70 @@ module ActiveRecord
|
|
54
66
|
# following code:
|
55
67
|
#
|
56
68
|
# registry = ActiveRecord::Scoping::ScopeRegistry
|
57
|
-
# registry.
|
69
|
+
# registry.set_current_scope(Board, some_new_scope)
|
58
70
|
#
|
59
71
|
# Now when you run:
|
60
72
|
#
|
61
|
-
# registry.
|
62
|
-
#
|
63
|
-
# You will obtain whatever was defined in +some_new_scope+. The #value_for
|
64
|
-
# and #set_value_for methods are delegated to the current ScopeRegistry
|
65
|
-
# object, so the above example code can also be called as:
|
73
|
+
# registry.current_scope(Board)
|
66
74
|
#
|
67
|
-
#
|
68
|
-
# Board, some_new_scope)
|
75
|
+
# You will obtain whatever was defined in +some_new_scope+.
|
69
76
|
class ScopeRegistry # :nodoc:
|
70
|
-
|
77
|
+
class << self
|
78
|
+
delegate :current_scope, :set_current_scope, :ignore_default_scope, :set_ignore_default_scope,
|
79
|
+
:global_current_scope, :set_global_current_scope, to: :instance
|
71
80
|
|
72
|
-
|
81
|
+
def instance
|
82
|
+
ActiveSupport::IsolatedExecutionState[:active_record_scope_registry] ||= new
|
83
|
+
end
|
84
|
+
end
|
73
85
|
|
74
86
|
def initialize
|
75
|
-
@
|
87
|
+
@current_scope = {}
|
88
|
+
@ignore_default_scope = {}
|
89
|
+
@global_current_scope = {}
|
76
90
|
end
|
77
91
|
|
78
|
-
|
79
|
-
|
80
|
-
raise_invalid_scope_type!(scope_type)
|
81
|
-
return @registry[scope_type][model.name] if skip_inherited_scope
|
82
|
-
klass = model
|
83
|
-
base = model.base_class
|
84
|
-
while klass <= base
|
85
|
-
value = @registry[scope_type][klass.name]
|
86
|
-
return value if value
|
87
|
-
klass = klass.superclass
|
88
|
-
end
|
92
|
+
def current_scope(model, skip_inherited_scope = false)
|
93
|
+
value_for(@current_scope, model, skip_inherited_scope)
|
89
94
|
end
|
90
95
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
96
|
+
def set_current_scope(model, value)
|
97
|
+
set_value_for(@current_scope, model, value)
|
98
|
+
end
|
99
|
+
|
100
|
+
def ignore_default_scope(model, skip_inherited_scope = false)
|
101
|
+
value_for(@ignore_default_scope, model, skip_inherited_scope)
|
102
|
+
end
|
103
|
+
|
104
|
+
def set_ignore_default_scope(model, value)
|
105
|
+
set_value_for(@ignore_default_scope, model, value)
|
106
|
+
end
|
107
|
+
|
108
|
+
def global_current_scope(model, skip_inherited_scope = false)
|
109
|
+
value_for(@global_current_scope, model, skip_inherited_scope)
|
110
|
+
end
|
111
|
+
|
112
|
+
def set_global_current_scope(model, value)
|
113
|
+
set_value_for(@global_current_scope, model, value)
|
95
114
|
end
|
96
115
|
|
97
116
|
private
|
98
|
-
|
99
|
-
|
100
|
-
|
117
|
+
# Obtains the value for a given +scope_type+ and +model+.
|
118
|
+
def value_for(scope_type, model, skip_inherited_scope = false)
|
119
|
+
return scope_type[model.name] if skip_inherited_scope
|
120
|
+
klass = model
|
121
|
+
base = model.base_class
|
122
|
+
while klass <= base
|
123
|
+
value = scope_type[klass.name]
|
124
|
+
return value if value
|
125
|
+
klass = klass.superclass
|
101
126
|
end
|
102
127
|
end
|
128
|
+
|
129
|
+
# Sets the +value+ for a given +scope_type+ and +model+.
|
130
|
+
def set_value_for(scope_type, model, value)
|
131
|
+
scope_type[model.name] = value
|
132
|
+
end
|
103
133
|
end
|
104
134
|
end
|
105
135
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
module ActiveRecord
|
3
|
+
module ActiveRecord # :nodoc:
|
4
4
|
# = Active Record \Serialization
|
5
5
|
module Serialization
|
6
6
|
extend ActiveSupport::Concern
|
@@ -20,5 +20,10 @@ module ActiveRecord #:nodoc:
|
|
20
20
|
|
21
21
|
super(options)
|
22
22
|
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def attribute_names_for_serialization
|
26
|
+
attribute_names
|
27
|
+
end
|
23
28
|
end
|
24
29
|
end
|
@@ -10,7 +10,7 @@ module ActiveRecord
|
|
10
10
|
# :singleton-method:
|
11
11
|
# Set the secret used for the signed id verifier instance when using Active Record outside of Rails.
|
12
12
|
# Within Rails, this is automatically set using the Rails application key generator.
|
13
|
-
|
13
|
+
class_attribute :signed_id_verifier_secret, instance_writer: false
|
14
14
|
end
|
15
15
|
|
16
16
|
module ClassMethods
|
@@ -47,7 +47,7 @@ module ActiveRecord
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
-
# Works like
|
50
|
+
# Works like find_signed, but will raise an +ActiveSupport::MessageVerifier::InvalidSignature+
|
51
51
|
# exception if the +signed_id+ has either expired, has a purpose mismatch, is for another record,
|
52
52
|
# or has been tampered with. It will also raise an +ActiveRecord::RecordNotFound+ exception if
|
53
53
|
# the valid signed id can't find a record.
|
@@ -97,7 +97,7 @@ module ActiveRecord
|
|
97
97
|
|
98
98
|
# Returns a signed id that's generated using a preconfigured +ActiveSupport::MessageVerifier+ instance.
|
99
99
|
# This signed id is tamper proof, so it's safe to send in an email or otherwise share with the outside world.
|
100
|
-
# It can
|
100
|
+
# It can furthermore be set to expire (the default is not to expire), and scoped down with a specific purpose.
|
101
101
|
# If the expiration date has been exceeded before +find_signed+ is called, the id won't find the designated
|
102
102
|
# record. If a purpose is set, this too must match.
|
103
103
|
#
|
data/lib/active_record/store.rb
CHANGED
@@ -59,7 +59,7 @@ module ActiveRecord
|
|
59
59
|
# u.color = 'green'
|
60
60
|
# u.color_changed? # => true
|
61
61
|
# u.color_was # => 'black'
|
62
|
-
# u.color_change # => ['black', '
|
62
|
+
# u.color_change # => ['black', 'green']
|
63
63
|
#
|
64
64
|
# # Add additional accessors to an existing store through store_accessor
|
65
65
|
# class SuperUser < User
|
@@ -268,7 +268,7 @@ module ActiveRecord
|
|
268
268
|
end
|
269
269
|
|
270
270
|
def dump(obj)
|
271
|
-
@coder.dump
|
271
|
+
@coder.dump as_regular_hash(obj)
|
272
272
|
end
|
273
273
|
|
274
274
|
def load(yaml)
|
@@ -285,6 +285,11 @@ module ActiveRecord
|
|
285
285
|
ActiveSupport::HashWithIndifferentAccess.new
|
286
286
|
end
|
287
287
|
end
|
288
|
+
|
289
|
+
private
|
290
|
+
def as_regular_hash(obj)
|
291
|
+
obj.respond_to?(:to_hash) ? obj.to_hash : {}
|
292
|
+
end
|
288
293
|
end
|
289
294
|
end
|
290
295
|
end
|