activerecord 7.0.10 → 7.1.0.beta1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1348 -1672
- data/MIT-LICENSE +1 -1
- data/README.rdoc +15 -17
- data/lib/active_record/aggregations.rb +16 -13
- data/lib/active_record/association_relation.rb +1 -1
- data/lib/active_record/associations/association.rb +18 -3
- data/lib/active_record/associations/association_scope.rb +16 -9
- data/lib/active_record/associations/belongs_to_association.rb +14 -6
- data/lib/active_record/associations/builder/association.rb +3 -3
- data/lib/active_record/associations/builder/belongs_to.rb +21 -8
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- data/lib/active_record/associations/builder/singular_association.rb +4 -0
- data/lib/active_record/associations/collection_association.rb +17 -9
- data/lib/active_record/associations/collection_proxy.rb +16 -11
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +20 -13
- data/lib/active_record/associations/has_many_through_association.rb +10 -6
- data/lib/active_record/associations/has_one_association.rb +10 -3
- data/lib/active_record/associations/join_dependency.rb +10 -8
- data/lib/active_record/associations/preloader/association.rb +27 -6
- data/lib/active_record/associations/preloader.rb +12 -9
- data/lib/active_record/associations/singular_association.rb +1 -1
- data/lib/active_record/associations/through_association.rb +22 -11
- data/lib/active_record/associations.rb +313 -217
- data/lib/active_record/attribute_assignment.rb +0 -2
- data/lib/active_record/attribute_methods/before_type_cast.rb +17 -0
- data/lib/active_record/attribute_methods/dirty.rb +48 -38
- data/lib/active_record/attribute_methods/primary_key.rb +76 -24
- data/lib/active_record/attribute_methods/query.rb +28 -16
- data/lib/active_record/attribute_methods/read.rb +18 -5
- data/lib/active_record/attribute_methods/serialization.rb +150 -31
- data/lib/active_record/attribute_methods/write.rb +3 -3
- data/lib/active_record/attribute_methods.rb +105 -21
- data/lib/active_record/attributes.rb +3 -3
- data/lib/active_record/autosave_association.rb +55 -9
- data/lib/active_record/base.rb +7 -2
- data/lib/active_record/callbacks.rb +10 -24
- data/lib/active_record/coders/column_serializer.rb +61 -0
- data/lib/active_record/coders/json.rb +1 -1
- data/lib/active_record/coders/yaml_column.rb +70 -42
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +163 -88
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +2 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +3 -1
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +65 -49
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +109 -32
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +60 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +41 -6
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +18 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +137 -11
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +291 -122
- data/lib/active_record/connection_adapters/abstract/transaction.rb +280 -58
- data/lib/active_record/connection_adapters/abstract_adapter.rb +502 -91
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +200 -115
- data/lib/active_record/connection_adapters/column.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +22 -143
- data/lib/active_record/connection_adapters/mysql/quoting.rb +16 -12
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +6 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +18 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +98 -53
- data/lib/active_record/connection_adapters/pool_config.rb +14 -5
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +76 -29
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +2 -3
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +9 -6
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +3 -9
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -6
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +131 -2
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +42 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +352 -55
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +336 -168
- data/lib/active_record/connection_adapters/schema_cache.rb +287 -59
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +42 -36
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +4 -3
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +1 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +26 -7
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +162 -77
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +98 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +254 -0
- data/lib/active_record/connection_adapters.rb +3 -1
- data/lib/active_record/connection_handling.rb +72 -95
- data/lib/active_record/core.rb +131 -142
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/database_config.rb +9 -3
- data/lib/active_record/database_configurations/hash_config.rb +22 -12
- data/lib/active_record/database_configurations/url_config.rb +17 -11
- data/lib/active_record/database_configurations.rb +86 -33
- data/lib/active_record/delegated_type.rb +11 -6
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +2 -0
- data/lib/active_record/encryption/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +4 -1
- data/lib/active_record/encryption/config.rb +25 -1
- data/lib/active_record/encryption/configurable.rb +12 -19
- data/lib/active_record/encryption/context.rb +10 -3
- data/lib/active_record/encryption/contexts.rb +5 -1
- data/lib/active_record/encryption/derived_secret_key_provider.rb +8 -2
- data/lib/active_record/encryption/encryptable_record.rb +36 -18
- data/lib/active_record/encryption/encrypted_attribute_type.rb +17 -6
- data/lib/active_record/encryption/extended_deterministic_queries.rb +52 -12
- data/lib/active_record/encryption/extended_deterministic_uniqueness_validator.rb +2 -2
- data/lib/active_record/encryption/key_generator.rb +12 -1
- data/lib/active_record/encryption/message_serializer.rb +2 -0
- data/lib/active_record/encryption/properties.rb +3 -3
- data/lib/active_record/encryption/scheme.rb +19 -22
- data/lib/active_record/encryption.rb +1 -0
- data/lib/active_record/enum.rb +113 -26
- data/lib/active_record/errors.rb +89 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/fixture_set/model_metadata.rb +14 -4
- data/lib/active_record/fixture_set/render_context.rb +2 -0
- data/lib/active_record/fixture_set/table_row.rb +29 -8
- data/lib/active_record/fixtures.rb +119 -83
- data/lib/active_record/future_result.rb +30 -5
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +30 -16
- data/lib/active_record/insert_all.rb +58 -11
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/internal_metadata.rb +118 -30
- data/lib/active_record/locking/pessimistic.rb +5 -2
- data/lib/active_record/log_subscriber.rb +29 -12
- data/lib/active_record/marshalling.rb +56 -0
- data/lib/active_record/message_pack.rb +124 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +4 -0
- data/lib/active_record/middleware/database_selector.rb +6 -8
- data/lib/active_record/middleware/shard_selector.rb +3 -1
- data/lib/active_record/migration/command_recorder.rb +100 -4
- data/lib/active_record/migration/compatibility.rb +131 -5
- data/lib/active_record/migration/default_strategy.rb +23 -0
- data/lib/active_record/migration/execution_strategy.rb +19 -0
- data/lib/active_record/migration.rb +215 -112
- data/lib/active_record/model_schema.rb +50 -32
- data/lib/active_record/nested_attributes.rb +31 -6
- data/lib/active_record/normalization.rb +158 -0
- data/lib/active_record/persistence.rb +183 -33
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +77 -52
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +15 -2
- data/lib/active_record/railtie.rb +108 -46
- data/lib/active_record/railties/controller_runtime.rb +10 -5
- data/lib/active_record/railties/databases.rake +139 -145
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +32 -5
- data/lib/active_record/reflection.rb +169 -45
- data/lib/active_record/relation/batches/batch_enumerator.rb +5 -3
- data/lib/active_record/relation/batches.rb +190 -61
- data/lib/active_record/relation/calculations.rb +152 -63
- data/lib/active_record/relation/delegation.rb +23 -9
- data/lib/active_record/relation/finder_methods.rb +85 -15
- data/lib/active_record/relation/merger.rb +2 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +11 -2
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +26 -14
- data/lib/active_record/relation/query_attribute.rb +2 -1
- data/lib/active_record/relation/query_methods.rb +351 -62
- data/lib/active_record/relation/spawn_methods.rb +18 -1
- data/lib/active_record/relation.rb +75 -34
- data/lib/active_record/result.rb +19 -5
- data/lib/active_record/runtime_registry.rb +10 -1
- data/lib/active_record/sanitization.rb +51 -11
- data/lib/active_record/schema.rb +2 -3
- data/lib/active_record/schema_dumper.rb +41 -7
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +15 -5
- data/lib/active_record/scoping/named.rb +2 -2
- data/lib/active_record/scoping.rb +2 -1
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/signed_id.rb +7 -5
- data/lib/active_record/store.rb +8 -8
- data/lib/active_record/suppressor.rb +3 -1
- data/lib/active_record/table_metadata.rb +10 -1
- data/lib/active_record/tasks/database_tasks.rb +127 -105
- data/lib/active_record/tasks/mysql_database_tasks.rb +15 -6
- data/lib/active_record/tasks/postgresql_database_tasks.rb +16 -13
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -7
- data/lib/active_record/test_fixtures.rb +113 -96
- data/lib/active_record/timestamp.rb +27 -15
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +36 -10
- data/lib/active_record/type/adapter_specific_registry.rb +1 -8
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/numericality.rb +5 -4
- data/lib/active_record/validations/presence.rb +5 -28
- data/lib/active_record/validations/uniqueness.rb +47 -2
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +121 -16
- data/lib/arel/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/nodes/binary.rb +6 -1
- data/lib/arel/nodes/bound_sql_literal.rb +61 -0
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/homogeneous_in.rb +1 -9
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes.rb +4 -0
- data/lib/arel/predications.rb +2 -0
- data/lib/arel/table.rb +9 -5
- data/lib/arel/visitors/mysql.rb +8 -1
- data/lib/arel/visitors/to_sql.rb +81 -17
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +16 -2
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/migration.rb +3 -1
- data/lib/rails/generators/active_record/model/USAGE +113 -0
- data/lib/rails/generators/active_record/model/model_generator.rb +15 -6
- metadata +52 -14
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -63
|
@@ -6,20 +6,23 @@ require "zlib"
|
|
|
6
6
|
require "set"
|
|
7
7
|
require "active_support/dependencies"
|
|
8
8
|
require "active_support/core_ext/digest/uuid"
|
|
9
|
-
require "active_record/fixture_set/file"
|
|
10
|
-
require "active_record/fixture_set/render_context"
|
|
11
|
-
require "active_record/fixture_set/table_rows"
|
|
12
9
|
require "active_record/test_fixtures"
|
|
13
10
|
|
|
14
11
|
module ActiveRecord
|
|
15
12
|
class FixtureClassNotFound < ActiveRecord::ActiveRecordError # :nodoc:
|
|
16
13
|
end
|
|
17
14
|
|
|
15
|
+
# = Active Record \Fixtures
|
|
16
|
+
#
|
|
18
17
|
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
|
|
19
18
|
#
|
|
20
|
-
# They are stored in YAML files, one file per model, which are placed in
|
|
21
|
-
#
|
|
22
|
-
#
|
|
19
|
+
# They are stored in YAML files, one file per model, which are by default placed in either
|
|
20
|
+
# <tt><your-rails-app>/test/fixtures/</tt> or in the <tt>test/fixtures</tt>
|
|
21
|
+
# folder under any of your application's engines.
|
|
22
|
+
#
|
|
23
|
+
# The location can also be changed with ActiveSupport::TestCase.fixture_paths=,
|
|
24
|
+
# once you have <tt>require "rails/test_help"</tt> in your +test_helper.rb+.
|
|
25
|
+
#
|
|
23
26
|
# The fixture file ends with the +.yml+ file extension, for example:
|
|
24
27
|
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
|
|
25
28
|
#
|
|
@@ -39,10 +42,17 @@ module ActiveRecord
|
|
|
39
42
|
# is followed by an indented list of key/value pairs in the "key: value" format. Records are
|
|
40
43
|
# separated by a blank line for your viewing pleasure.
|
|
41
44
|
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
45
|
+
# == Ordering
|
|
46
|
+
#
|
|
47
|
+
# Fixtures by default are unordered. This is because the maps in YAML are unordered.
|
|
48
|
+
#
|
|
49
|
+
# If you want ordered fixtures, use the omap YAML type.
|
|
50
|
+
# See https://yaml.org/type/omap.html for the specification.
|
|
51
|
+
#
|
|
52
|
+
# You will need ordered fixtures when you have foreign key constraints
|
|
53
|
+
# on keys in the same table. This is commonly needed for tree structures.
|
|
54
|
+
#
|
|
55
|
+
# For example:
|
|
46
56
|
#
|
|
47
57
|
# --- !omap
|
|
48
58
|
# - parent:
|
|
@@ -54,7 +64,7 @@ module ActiveRecord
|
|
|
54
64
|
# parent_id: 1
|
|
55
65
|
# title: Child
|
|
56
66
|
#
|
|
57
|
-
#
|
|
67
|
+
# == Using Fixtures in Test Cases
|
|
58
68
|
#
|
|
59
69
|
# Since fixtures are a testing construct, we use them in our unit and functional tests. There
|
|
60
70
|
# are two ways to use the fixtures, but first let's take a look at a sample unit test:
|
|
@@ -124,7 +134,7 @@ module ActiveRecord
|
|
|
124
134
|
# traversed in the database to create the fixture hash and/or instance variables. This is expensive for
|
|
125
135
|
# large sets of fixtured data.
|
|
126
136
|
#
|
|
127
|
-
#
|
|
137
|
+
# == Dynamic fixtures with \ERB
|
|
128
138
|
#
|
|
129
139
|
# Sometimes you don't care about the content of the fixtures as much as you care about the volume.
|
|
130
140
|
# In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
|
|
@@ -162,7 +172,7 @@ module ActiveRecord
|
|
|
162
172
|
# name: kitten.png
|
|
163
173
|
# sha: <%= file_sha 'files/kitten.png' %>
|
|
164
174
|
#
|
|
165
|
-
#
|
|
175
|
+
# == Transactional Tests
|
|
166
176
|
#
|
|
167
177
|
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
|
|
168
178
|
# delete+insert for every test case.
|
|
@@ -198,7 +208,7 @@ module ActiveRecord
|
|
|
198
208
|
# 2. Your database does not support transactions. Every Active Record database supports transactions except MySQL MyISAM.
|
|
199
209
|
# Use InnoDB, MaxDB, or NDB instead.
|
|
200
210
|
#
|
|
201
|
-
#
|
|
211
|
+
# == Advanced Fixtures
|
|
202
212
|
#
|
|
203
213
|
# Fixtures that don't specify an ID get some extra features:
|
|
204
214
|
#
|
|
@@ -212,7 +222,7 @@ module ActiveRecord
|
|
|
212
222
|
# * Fixture label interpolation
|
|
213
223
|
# * Support for YAML defaults
|
|
214
224
|
#
|
|
215
|
-
#
|
|
225
|
+
# === Stable, Autogenerated IDs
|
|
216
226
|
#
|
|
217
227
|
# Here, have a monkey fixture:
|
|
218
228
|
#
|
|
@@ -241,13 +251,13 @@ module ActiveRecord
|
|
|
241
251
|
# The generated ID for a given label is constant, so we can discover
|
|
242
252
|
# any fixture's ID without loading anything, as long as we know the label.
|
|
243
253
|
#
|
|
244
|
-
#
|
|
254
|
+
# === Label references for associations (+belongs_to+, +has_one+, +has_many+)
|
|
245
255
|
#
|
|
246
256
|
# Specifying foreign keys in fixtures can be very fragile, not to
|
|
247
257
|
# mention difficult to read. Since Active Record can figure out the ID of
|
|
248
258
|
# any fixture from its label, you can specify FK's by label instead of ID.
|
|
249
259
|
#
|
|
250
|
-
#
|
|
260
|
+
# ==== +belongs_to+
|
|
251
261
|
#
|
|
252
262
|
# Let's break out some more monkeys and pirates.
|
|
253
263
|
#
|
|
@@ -258,8 +268,6 @@ module ActiveRecord
|
|
|
258
268
|
# name: Reginald the Pirate
|
|
259
269
|
# monkey_id: 1
|
|
260
270
|
#
|
|
261
|
-
# <code></code>
|
|
262
|
-
#
|
|
263
271
|
# ### in monkeys.yml
|
|
264
272
|
#
|
|
265
273
|
# george:
|
|
@@ -277,8 +285,6 @@ module ActiveRecord
|
|
|
277
285
|
# name: Reginald the Pirate
|
|
278
286
|
# monkey: george
|
|
279
287
|
#
|
|
280
|
-
# <code></code>
|
|
281
|
-
#
|
|
282
288
|
# ### in monkeys.yml
|
|
283
289
|
#
|
|
284
290
|
# george:
|
|
@@ -300,8 +306,6 @@ module ActiveRecord
|
|
|
300
306
|
#
|
|
301
307
|
# belongs_to :eater, polymorphic: true
|
|
302
308
|
#
|
|
303
|
-
# <code></code>
|
|
304
|
-
#
|
|
305
309
|
# ### in fruits.yml
|
|
306
310
|
#
|
|
307
311
|
# apple:
|
|
@@ -317,9 +321,9 @@ module ActiveRecord
|
|
|
317
321
|
#
|
|
318
322
|
# Just provide the polymorphic target type and Active Record will take care of the rest.
|
|
319
323
|
#
|
|
320
|
-
#
|
|
324
|
+
# ==== +has_and_belongs_to_many+ or <tt>has_many :through</tt>
|
|
321
325
|
#
|
|
322
|
-
# Time to give our monkey some fruit.
|
|
326
|
+
# \Time to give our monkey some fruit.
|
|
323
327
|
#
|
|
324
328
|
# ### in monkeys.yml
|
|
325
329
|
#
|
|
@@ -327,8 +331,6 @@ module ActiveRecord
|
|
|
327
331
|
# id: 1
|
|
328
332
|
# name: George the Monkey
|
|
329
333
|
#
|
|
330
|
-
# <code></code>
|
|
331
|
-
#
|
|
332
334
|
# ### in fruits.yml
|
|
333
335
|
#
|
|
334
336
|
# apple:
|
|
@@ -343,8 +345,6 @@ module ActiveRecord
|
|
|
343
345
|
# id: 3
|
|
344
346
|
# name: grape
|
|
345
347
|
#
|
|
346
|
-
# <code></code>
|
|
347
|
-
#
|
|
348
348
|
# ### in fruits_monkeys.yml
|
|
349
349
|
#
|
|
350
350
|
# apple_george:
|
|
@@ -368,8 +368,6 @@ module ActiveRecord
|
|
|
368
368
|
# name: George the Monkey
|
|
369
369
|
# fruits: apple, orange, grape
|
|
370
370
|
#
|
|
371
|
-
# <code></code>
|
|
372
|
-
#
|
|
373
371
|
# ### in fruits.yml
|
|
374
372
|
#
|
|
375
373
|
# apple:
|
|
@@ -387,7 +385,7 @@ module ActiveRecord
|
|
|
387
385
|
# the fixture's model class and discovers the +has_and_belongs_to_many+
|
|
388
386
|
# associations.
|
|
389
387
|
#
|
|
390
|
-
#
|
|
388
|
+
# === Autofilled \Timestamp Columns
|
|
391
389
|
#
|
|
392
390
|
# If your table/model specifies any of Active Record's
|
|
393
391
|
# standard timestamp columns (+created_at+, +created_on+, +updated_at+, +updated_on+),
|
|
@@ -395,7 +393,7 @@ module ActiveRecord
|
|
|
395
393
|
#
|
|
396
394
|
# If you've set specific values, they'll be left alone.
|
|
397
395
|
#
|
|
398
|
-
#
|
|
396
|
+
# === Fixture label interpolation
|
|
399
397
|
#
|
|
400
398
|
# The label of the current fixture is always available as a column value:
|
|
401
399
|
#
|
|
@@ -412,7 +410,11 @@ module ActiveRecord
|
|
|
412
410
|
# monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
|
|
413
411
|
# pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
|
|
414
412
|
#
|
|
415
|
-
#
|
|
413
|
+
# If the model uses UUID values for identifiers, add the +:uuid+ argument:
|
|
414
|
+
#
|
|
415
|
+
# ActiveRecord::FixtureSet.identify(:boaty_mcboatface, :uuid)
|
|
416
|
+
#
|
|
417
|
+
# === Support for YAML defaults
|
|
416
418
|
#
|
|
417
419
|
# You can set and reuse defaults in your fixtures YAML file.
|
|
418
420
|
# This is the same technique used in the +database.yml+ file to specify
|
|
@@ -454,6 +456,41 @@ module ActiveRecord
|
|
|
454
456
|
# In the above example, 'base' will be ignored when creating fixtures.
|
|
455
457
|
# This can be used for common attributes inheriting.
|
|
456
458
|
#
|
|
459
|
+
# == Composite Primary Key Fixtures
|
|
460
|
+
#
|
|
461
|
+
# Fixtures for composite primary key tables are fairly similar to normal tables.
|
|
462
|
+
# When using an id column, the column may be omitted as usual:
|
|
463
|
+
#
|
|
464
|
+
# # app/models/book.rb
|
|
465
|
+
# class Book < ApplicationRecord
|
|
466
|
+
# self.primary_key = [:author_id, :id]
|
|
467
|
+
# belongs_to :author
|
|
468
|
+
# end
|
|
469
|
+
#
|
|
470
|
+
# # books.yml
|
|
471
|
+
# alices_adventure_in_wonderland:
|
|
472
|
+
# author_id: <%= ActiveRecord::FixtureSet.identify(:lewis_carroll) %>
|
|
473
|
+
# title: "Alice's Adventures in Wonderland"
|
|
474
|
+
#
|
|
475
|
+
# However, in order to support composite primary key relationships,
|
|
476
|
+
# you must use the `composite_identify` method:
|
|
477
|
+
#
|
|
478
|
+
# # app/models/book_orders.rb
|
|
479
|
+
# class BookOrder < ApplicationRecord
|
|
480
|
+
# self.primary_key = [:shop_id, :id]
|
|
481
|
+
# belongs_to :order, query_constraints: [:shop_id, :order_id]
|
|
482
|
+
# belongs_to :book, query_constraints: [:author_id, :book_id]
|
|
483
|
+
# end
|
|
484
|
+
#
|
|
485
|
+
# # book_orders.yml
|
|
486
|
+
# alices_adventure_in_wonderland_in_books:
|
|
487
|
+
# author: lewis_carroll
|
|
488
|
+
# book_id: <%= ActiveRecord::FixtureSet.composite_identify(
|
|
489
|
+
# :alices_adventure_in_wonderland, Book.primary_key)[:id] %>
|
|
490
|
+
# shop: book_store
|
|
491
|
+
# order_id: <%= ActiveRecord::FixtureSet.composite_identify(
|
|
492
|
+
# :books, Order.primary_key)[:id] %>
|
|
493
|
+
#
|
|
457
494
|
# == Configure the fixture model class
|
|
458
495
|
#
|
|
459
496
|
# It's possible to set the fixture's model class directly in the YAML file.
|
|
@@ -468,6 +505,10 @@ module ActiveRecord
|
|
|
468
505
|
#
|
|
469
506
|
# Any fixtures labeled "_fixture" are safely ignored.
|
|
470
507
|
class FixtureSet
|
|
508
|
+
require "active_record/fixture_set/file"
|
|
509
|
+
require "active_record/fixture_set/render_context"
|
|
510
|
+
require "active_record/fixture_set/table_rows"
|
|
511
|
+
|
|
471
512
|
#--
|
|
472
513
|
# An instance of FixtureSet is normally stored in a single YAML file and
|
|
473
514
|
# possibly in a folder with the same name.
|
|
@@ -479,39 +520,6 @@ module ActiveRecord
|
|
|
479
520
|
|
|
480
521
|
cattr_accessor :all_loaded_fixtures, default: {}
|
|
481
522
|
|
|
482
|
-
class ClassCache
|
|
483
|
-
def initialize(class_names, config)
|
|
484
|
-
@class_names = class_names.stringify_keys
|
|
485
|
-
@config = config
|
|
486
|
-
|
|
487
|
-
# Remove string values that aren't constants or subclasses of AR
|
|
488
|
-
@class_names.delete_if do |klass_name, klass|
|
|
489
|
-
!insert_class(@class_names, klass_name, klass)
|
|
490
|
-
end
|
|
491
|
-
end
|
|
492
|
-
|
|
493
|
-
def [](fs_name)
|
|
494
|
-
@class_names.fetch(fs_name) do
|
|
495
|
-
klass = default_fixture_model(fs_name, @config).safe_constantize
|
|
496
|
-
insert_class(@class_names, fs_name, klass)
|
|
497
|
-
end
|
|
498
|
-
end
|
|
499
|
-
|
|
500
|
-
private
|
|
501
|
-
def insert_class(class_names, name, klass)
|
|
502
|
-
# We only want to deal with AR objects.
|
|
503
|
-
if klass && klass < ActiveRecord::Base
|
|
504
|
-
class_names[name] = klass
|
|
505
|
-
else
|
|
506
|
-
class_names[name] = nil
|
|
507
|
-
end
|
|
508
|
-
end
|
|
509
|
-
|
|
510
|
-
def default_fixture_model(fs_name, config)
|
|
511
|
-
ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
|
|
512
|
-
end
|
|
513
|
-
end
|
|
514
|
-
|
|
515
523
|
class << self
|
|
516
524
|
def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
|
517
525
|
config.pluralize_table_names ?
|
|
@@ -564,9 +572,9 @@ module ActiveRecord
|
|
|
564
572
|
end
|
|
565
573
|
end
|
|
566
574
|
|
|
567
|
-
def create_fixtures(
|
|
575
|
+
def create_fixtures(fixtures_directories, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
|
|
568
576
|
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
|
569
|
-
class_names
|
|
577
|
+
class_names.stringify_keys!
|
|
570
578
|
|
|
571
579
|
# FIXME: Apparently JK uses this.
|
|
572
580
|
connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
|
|
@@ -577,7 +585,7 @@ module ActiveRecord
|
|
|
577
585
|
|
|
578
586
|
if fixture_files_to_read.any?
|
|
579
587
|
fixtures_map = read_and_insert(
|
|
580
|
-
|
|
588
|
+
Array(fixtures_directories),
|
|
581
589
|
fixture_files_to_read,
|
|
582
590
|
class_names,
|
|
583
591
|
connection,
|
|
@@ -588,7 +596,8 @@ module ActiveRecord
|
|
|
588
596
|
end
|
|
589
597
|
|
|
590
598
|
# Returns a consistent, platform-independent identifier for +label+.
|
|
591
|
-
#
|
|
599
|
+
#
|
|
600
|
+
# \Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
|
|
592
601
|
def identify(label, column_type = :integer)
|
|
593
602
|
if column_type == :uuid
|
|
594
603
|
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
|
|
@@ -597,21 +606,35 @@ module ActiveRecord
|
|
|
597
606
|
end
|
|
598
607
|
end
|
|
599
608
|
|
|
600
|
-
#
|
|
609
|
+
# Returns a consistent, platform-independent hash representing a mapping
|
|
610
|
+
# between the label and the subcomponents of the provided composite key.
|
|
611
|
+
#
|
|
612
|
+
# Example:
|
|
613
|
+
#
|
|
614
|
+
# composite_identify("label", [:a, :b, :c]) # => { a: hash_1, b: hash_2, c: hash_3 }
|
|
615
|
+
def composite_identify(label, key)
|
|
616
|
+
key
|
|
617
|
+
.index_with
|
|
618
|
+
.with_index { |sub_key, index| (identify(label) << index) % MAX_ID }
|
|
619
|
+
.with_indifferent_access
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
# Superclass for the evaluation contexts used by \ERB fixtures.
|
|
601
623
|
def context_class
|
|
602
624
|
@context_class ||= Class.new
|
|
603
625
|
end
|
|
604
626
|
|
|
605
627
|
private
|
|
606
|
-
def read_and_insert(
|
|
628
|
+
def read_and_insert(fixtures_directories, fixture_files, class_names, connection) # :nodoc:
|
|
607
629
|
fixtures_map = {}
|
|
630
|
+
directory_glob = "{#{fixtures_directories.join(",")}}"
|
|
608
631
|
fixture_sets = fixture_files.map do |fixture_set_name|
|
|
609
632
|
klass = class_names[fixture_set_name]
|
|
610
633
|
fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
|
|
611
634
|
nil,
|
|
612
635
|
fixture_set_name,
|
|
613
636
|
klass,
|
|
614
|
-
::File.join(
|
|
637
|
+
::File.join(directory_glob, fixture_set_name)
|
|
615
638
|
)
|
|
616
639
|
end
|
|
617
640
|
update_all_loaded_fixtures(fixtures_map)
|
|
@@ -641,9 +664,7 @@ module ActiveRecord
|
|
|
641
664
|
|
|
642
665
|
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
|
643
666
|
|
|
644
|
-
|
|
645
|
-
raise "Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations."
|
|
646
|
-
end
|
|
667
|
+
check_all_foreign_keys_valid!(conn)
|
|
647
668
|
|
|
648
669
|
# Cap primary key sequences to max(pk).
|
|
649
670
|
if conn.respond_to?(:reset_pk_sequence!)
|
|
@@ -652,6 +673,16 @@ module ActiveRecord
|
|
|
652
673
|
end
|
|
653
674
|
end
|
|
654
675
|
|
|
676
|
+
def check_all_foreign_keys_valid!(conn)
|
|
677
|
+
return unless ActiveRecord.verify_foreign_keys_for_fixtures
|
|
678
|
+
|
|
679
|
+
begin
|
|
680
|
+
conn.check_all_foreign_keys_valid!
|
|
681
|
+
rescue ActiveRecord::StatementInvalid => e
|
|
682
|
+
raise "Foreign key violations found in your fixture data. Ensure you aren't referring to labels that don't exist on associations. Error from database:\n\n#{e.message}"
|
|
683
|
+
end
|
|
684
|
+
end
|
|
685
|
+
|
|
655
686
|
def update_all_loaded_fixtures(fixtures_map) # :nodoc:
|
|
656
687
|
all_loaded_fixtures.update(fixtures_map)
|
|
657
688
|
end
|
|
@@ -665,7 +696,6 @@ module ActiveRecord
|
|
|
665
696
|
@config = config
|
|
666
697
|
|
|
667
698
|
self.model_class = class_name
|
|
668
|
-
|
|
669
699
|
@fixtures = read_fixture_files(path)
|
|
670
700
|
|
|
671
701
|
@table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
|
|
@@ -727,14 +757,18 @@ module ActiveRecord
|
|
|
727
757
|
# Loads the fixtures from the YAML file at +path+.
|
|
728
758
|
# If the file sets the +model_class+ and current instance value is not set,
|
|
729
759
|
# it uses the file value.
|
|
760
|
+
|
|
730
761
|
def read_fixture_files(path)
|
|
731
|
-
yaml_files = Dir["#{path}
|
|
762
|
+
yaml_files = Dir["#{path}{.yml,/{**,*}/*.yml}"].select { |f|
|
|
732
763
|
::File.file?(f)
|
|
733
|
-
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
raise ArgumentError, "No fixture files found for #{@name}" if yaml_files.empty?
|
|
734
767
|
|
|
735
768
|
yaml_files.each_with_object({}) do |file, fixtures|
|
|
736
769
|
FixtureSet::File.open(file) do |fh|
|
|
737
770
|
self.model_class ||= fh.model_class if fh.model_class
|
|
771
|
+
self.model_class ||= default_fixture_model_class
|
|
738
772
|
self.ignored_fixtures ||= fh.ignored_fixtures
|
|
739
773
|
fh.each do |fixture_name, row|
|
|
740
774
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
|
@@ -743,8 +777,9 @@ module ActiveRecord
|
|
|
743
777
|
end
|
|
744
778
|
end
|
|
745
779
|
|
|
746
|
-
def
|
|
747
|
-
|
|
780
|
+
def default_fixture_model_class
|
|
781
|
+
klass = ActiveRecord::FixtureSet.default_fixture_model_name(@name, @config).safe_constantize
|
|
782
|
+
klass if klass && klass < ActiveRecord::Base
|
|
748
783
|
end
|
|
749
784
|
end
|
|
750
785
|
|
|
@@ -781,7 +816,8 @@ module ActiveRecord
|
|
|
781
816
|
def find
|
|
782
817
|
raise FixtureClassNotFound, "No class attached to find." unless model_class
|
|
783
818
|
object = model_class.unscoped do
|
|
784
|
-
|
|
819
|
+
pk_clauses = fixture.slice(*Array(model_class.primary_key))
|
|
820
|
+
model_class.find_by!(pk_clauses)
|
|
785
821
|
end
|
|
786
822
|
# Fixtures can't be eagerly loaded
|
|
787
823
|
object.instance_variable_set(:@strict_loading, false)
|
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
4
|
class FutureResult # :nodoc:
|
|
5
|
+
class Complete
|
|
6
|
+
attr_reader :result
|
|
7
|
+
delegate :empty?, :to_a, to: :result
|
|
8
|
+
|
|
9
|
+
def initialize(result)
|
|
10
|
+
@result = result
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pending?
|
|
14
|
+
false
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def canceled?
|
|
18
|
+
false
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def then(&block)
|
|
22
|
+
Promise::Complete.new(@result.then(&block))
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
5
26
|
class EventBuffer
|
|
6
27
|
def initialize(future_result, instrumenter)
|
|
7
28
|
@future_result = future_result
|
|
@@ -45,6 +66,10 @@ module ActiveRecord
|
|
|
45
66
|
@event_buffer = nil
|
|
46
67
|
end
|
|
47
68
|
|
|
69
|
+
def then(&block)
|
|
70
|
+
Promise.new(self, block)
|
|
71
|
+
end
|
|
72
|
+
|
|
48
73
|
def schedule!(session)
|
|
49
74
|
@session = session
|
|
50
75
|
@pool.schedule_query(self)
|
|
@@ -95,11 +120,11 @@ module ActiveRecord
|
|
|
95
120
|
@pending && (!@session || @session.active?)
|
|
96
121
|
end
|
|
97
122
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
end
|
|
123
|
+
def canceled?
|
|
124
|
+
@session && !@session.active?
|
|
125
|
+
end
|
|
102
126
|
|
|
127
|
+
private
|
|
103
128
|
def execute_or_wait
|
|
104
129
|
if pending?
|
|
105
130
|
start = Process.clock_gettime(Process::CLOCK_MONOTONIC, :float_millisecond)
|
|
@@ -124,7 +149,7 @@ module ActiveRecord
|
|
|
124
149
|
end
|
|
125
150
|
|
|
126
151
|
def exec_query(connection, *args, **kwargs)
|
|
127
|
-
connection.
|
|
152
|
+
connection.internal_exec_query(*args, **kwargs)
|
|
128
153
|
end
|
|
129
154
|
|
|
130
155
|
class SelectAll < FutureResult # :nodoc:
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
module ActiveRecord
|
|
4
|
-
# Returns the currently loaded version of Active Record as a
|
|
4
|
+
# Returns the currently loaded version of Active Record as a +Gem::Version+.
|
|
5
5
|
def self.gem_version
|
|
6
6
|
Gem::Version.new VERSION::STRING
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
module VERSION
|
|
10
10
|
MAJOR = 7
|
|
11
|
-
MINOR =
|
|
12
|
-
TINY =
|
|
13
|
-
PRE =
|
|
11
|
+
MINOR = 1
|
|
12
|
+
TINY = 0
|
|
13
|
+
PRE = "beta1"
|
|
14
14
|
|
|
15
15
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|
|
16
16
|
end
|
|
@@ -4,7 +4,7 @@ require "active_support/inflector"
|
|
|
4
4
|
require "active_support/core_ext/hash/indifferent_access"
|
|
5
5
|
|
|
6
6
|
module ActiveRecord
|
|
7
|
-
#
|
|
7
|
+
# = Single table inheritance
|
|
8
8
|
#
|
|
9
9
|
# Active Record allows inheritance by storing the name of the class in a column that by
|
|
10
10
|
# default is named "type" (can be changed by overwriting <tt>Base.inheritance_column</tt>).
|
|
@@ -32,8 +32,9 @@ module ActiveRecord
|
|
|
32
32
|
# be triggered. In that case, it'll work just like normal subclasses with no special magic
|
|
33
33
|
# for differentiating between them or reloading the right type with find.
|
|
34
34
|
#
|
|
35
|
-
# Note, all the attributes for all the cases are kept in the same table.
|
|
36
|
-
#
|
|
35
|
+
# Note, all the attributes for all the cases are kept in the same table.
|
|
36
|
+
# Read more:
|
|
37
|
+
# * https://www.martinfowler.com/eaaCatalog/singleTableInheritance.html
|
|
37
38
|
#
|
|
38
39
|
module Inheritance
|
|
39
40
|
extend ActiveSupport::Concern
|
|
@@ -93,14 +94,24 @@ module ActiveRecord
|
|
|
93
94
|
:true == (@finder_needs_type_condition ||= descends_from_active_record? ? :false : :true)
|
|
94
95
|
end
|
|
95
96
|
|
|
96
|
-
# Returns the class
|
|
97
|
-
#
|
|
97
|
+
# Returns the first class in the inheritance hierarchy that descends from either an
|
|
98
|
+
# abstract class or from <tt>ActiveRecord::Base</tt>.
|
|
98
99
|
#
|
|
99
|
-
#
|
|
100
|
-
# through some arbitrarily deep hierarchy, B.base_class will return A.
|
|
100
|
+
# Consider the following behaviour:
|
|
101
101
|
#
|
|
102
|
-
#
|
|
103
|
-
#
|
|
102
|
+
# class ApplicationRecord < ActiveRecord::Base
|
|
103
|
+
# self.abstract_class = true
|
|
104
|
+
# end
|
|
105
|
+
# class Shape < ApplicationRecord
|
|
106
|
+
# self.abstract_class = true
|
|
107
|
+
# end
|
|
108
|
+
# Polygon = Class.new(Shape)
|
|
109
|
+
# Square = Class.new(Polygon)
|
|
110
|
+
#
|
|
111
|
+
# ApplicationRecord.base_class # => ApplicationRecord
|
|
112
|
+
# Shape.base_class # => Shape
|
|
113
|
+
# Polygon.base_class # => Polygon
|
|
114
|
+
# Square.base_class # => Polygon
|
|
104
115
|
attr_reader :base_class
|
|
105
116
|
|
|
106
117
|
# Returns whether the class is a base class.
|
|
@@ -116,7 +127,7 @@ module ActiveRecord
|
|
|
116
127
|
# true.
|
|
117
128
|
# +ApplicationRecord+, for example, is generated as an abstract class.
|
|
118
129
|
#
|
|
119
|
-
# Consider the following default
|
|
130
|
+
# Consider the following default behavior:
|
|
120
131
|
#
|
|
121
132
|
# Shape = Class.new(ActiveRecord::Base)
|
|
122
133
|
# Polygon = Class.new(Shape)
|
|
@@ -210,12 +221,6 @@ module ActiveRecord
|
|
|
210
221
|
end
|
|
211
222
|
end
|
|
212
223
|
|
|
213
|
-
def inherited(subclass)
|
|
214
|
-
subclass.set_base_class
|
|
215
|
-
subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
|
|
216
|
-
super
|
|
217
|
-
end
|
|
218
|
-
|
|
219
224
|
def dup # :nodoc:
|
|
220
225
|
# `initialize_dup` / `initialize_copy` don't work when defined
|
|
221
226
|
# in the `singleton_class`.
|
|
@@ -277,6 +282,15 @@ module ActiveRecord
|
|
|
277
282
|
end
|
|
278
283
|
|
|
279
284
|
private
|
|
285
|
+
def inherited(subclass)
|
|
286
|
+
super
|
|
287
|
+
subclass.set_base_class
|
|
288
|
+
subclass.instance_variable_set(:@_type_candidates_cache, Concurrent::Map.new)
|
|
289
|
+
subclass.class_eval do
|
|
290
|
+
@finder_needs_type_condition = nil
|
|
291
|
+
end
|
|
292
|
+
end
|
|
293
|
+
|
|
280
294
|
# Called by +instantiate+ to decide which class to use for a new
|
|
281
295
|
# record instance. For single-table inheritance, we check the record
|
|
282
296
|
# for a +type+ column and return the corresponding class.
|