activerecord 6.1.7 → 7.1.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1516 -1019
- data/MIT-LICENSE +1 -1
- data/README.rdoc +17 -18
- data/lib/active_record/aggregations.rb +17 -14
- data/lib/active_record/association_relation.rb +1 -11
- data/lib/active_record/associations/association.rb +50 -19
- data/lib/active_record/associations/association_scope.rb +17 -12
- data/lib/active_record/associations/belongs_to_association.rb +28 -9
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +10 -2
- data/lib/active_record/associations/builder/association.rb +11 -5
- data/lib/active_record/associations/builder/belongs_to.rb +40 -14
- data/lib/active_record/associations/builder/collection_association.rb +10 -3
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +1 -5
- 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 +6 -2
- data/lib/active_record/associations/collection_association.rb +35 -31
- data/lib/active_record/associations/collection_proxy.rb +30 -15
- data/lib/active_record/associations/disable_joins_association_scope.rb +59 -0
- data/lib/active_record/associations/foreign_association.rb +10 -3
- data/lib/active_record/associations/has_many_association.rb +28 -18
- data/lib/active_record/associations/has_many_through_association.rb +12 -7
- data/lib/active_record/associations/has_one_association.rb +20 -10
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency.rb +26 -16
- data/lib/active_record/associations/preloader/association.rb +207 -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 +50 -14
- data/lib/active_record/associations/preloader.rb +50 -121
- data/lib/active_record/associations/singular_association.rb +9 -3
- data/lib/active_record/associations/through_association.rb +25 -14
- data/lib/active_record/associations.rb +423 -289
- data/lib/active_record/asynchronous_queries_tracker.rb +60 -0
- data/lib/active_record/attribute_assignment.rb +1 -3
- data/lib/active_record/attribute_methods/before_type_cast.rb +24 -2
- data/lib/active_record/attribute_methods/dirty.rb +61 -14
- data/lib/active_record/attribute_methods/primary_key.rb +78 -26
- data/lib/active_record/attribute_methods/query.rb +31 -19
- data/lib/active_record/attribute_methods/read.rb +25 -10
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +4 -3
- data/lib/active_record/attribute_methods/write.rb +10 -13
- data/lib/active_record/attribute_methods.rb +121 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +61 -30
- data/lib/active_record/base.rb +25 -2
- data/lib/active_record/callbacks.rb +18 -34
- 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 -46
- data/lib/active_record/connection_adapters/abstract/connection_handler.rb +367 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/queue.rb +211 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool/reaper.rb +78 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +96 -590
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +171 -51
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +77 -27
- data/lib/active_record/connection_adapters/abstract/quoting.rb +87 -73
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +4 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +21 -20
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +186 -31
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +14 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +360 -136
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +622 -149
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +285 -156
- data/lib/active_record/connection_adapters/column.rb +13 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +25 -134
- data/lib/active_record/connection_adapters/mysql/quoting.rb +56 -25
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +9 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +10 -1
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +8 -2
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +38 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +148 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +104 -53
- data/lib/active_record/connection_adapters/pool_config.rb +20 -11
- data/lib/active_record/connection_adapters/pool_manager.rb +19 -9
- data/lib/active_record/connection_adapters/postgresql/column.rb +18 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +86 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- 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 +12 -3
- 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 +89 -56
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +92 -2
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +153 -3
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +78 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +381 -69
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +492 -230
- data/lib/active_record/connection_adapters/schema_cache.rb +319 -90
- data/lib/active_record/connection_adapters/sqlite3/column.rb +49 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +65 -53
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +37 -21
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +7 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +43 -22
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +294 -102
- 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 +9 -6
- data/lib/active_record/connection_handling.rb +107 -136
- data/lib/active_record/core.rb +194 -224
- data/lib/active_record/counter_cache.rb +46 -25
- data/lib/active_record/database_configurations/connection_url_resolver.rb +2 -1
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +84 -16
- data/lib/active_record/database_configurations/url_config.rb +18 -12
- data/lib/active_record/database_configurations.rb +95 -59
- data/lib/active_record/delegated_type.rb +61 -15
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +3 -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/auto_filtered_parameters.rb +66 -0
- data/lib/active_record/encryption/cipher/aes256_gcm.rb +101 -0
- data/lib/active_record/encryption/cipher.rb +53 -0
- data/lib/active_record/encryption/config.rb +68 -0
- data/lib/active_record/encryption/configurable.rb +60 -0
- data/lib/active_record/encryption/context.rb +42 -0
- data/lib/active_record/encryption/contexts.rb +76 -0
- data/lib/active_record/encryption/derived_secret_key_provider.rb +18 -0
- data/lib/active_record/encryption/deterministic_key_provider.rb +14 -0
- data/lib/active_record/encryption/encryptable_record.rb +224 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +151 -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 +172 -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 +53 -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 +92 -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 +96 -0
- data/lib/active_record/encryption.rb +56 -0
- data/lib/active_record/enum.rb +156 -62
- data/lib/active_record/errors.rb +171 -15
- data/lib/active_record/explain.rb +23 -3
- data/lib/active_record/explain_registry.rb +11 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +15 -1
- 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 +70 -14
- data/lib/active_record/fixture_set/table_rows.rb +4 -4
- data/lib/active_record/fixtures.rb +131 -86
- data/lib/active_record/future_result.rb +164 -0
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +81 -29
- data/lib/active_record/insert_all.rb +133 -20
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +117 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +36 -21
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- 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 +10 -10
- data/lib/active_record/middleware/database_selector.rb +23 -13
- data/lib/active_record/middleware/shard_selector.rb +62 -0
- data/lib/active_record/migration/command_recorder.rb +108 -13
- data/lib/active_record/migration/compatibility.rb +221 -48
- 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/join_table.rb +1 -1
- data/lib/active_record/migration.rb +355 -171
- data/lib/active_record/model_schema.rb +116 -97
- data/lib/active_record/nested_attributes.rb +36 -15
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +159 -0
- data/lib/active_record/persistence.rb +405 -85
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +3 -21
- data/lib/active_record/query_logs.rb +174 -0
- data/lib/active_record/query_logs_formatter.rb +41 -0
- data/lib/active_record/querying.rb +29 -6
- data/lib/active_record/railtie.rb +219 -43
- data/lib/active_record/railties/controller_runtime.rb +13 -9
- data/lib/active_record/railties/databases.rake +185 -249
- data/lib/active_record/railties/job_runtime.rb +23 -0
- data/lib/active_record/readonly_attributes.rb +41 -3
- data/lib/active_record/reflection.rb +229 -80
- data/lib/active_record/relation/batches/batch_enumerator.rb +23 -7
- data/lib/active_record/relation/batches.rb +192 -63
- data/lib/active_record/relation/calculations.rb +211 -90
- data/lib/active_record/relation/delegation.rb +27 -13
- data/lib/active_record/relation/finder_methods.rb +108 -51
- data/lib/active_record/relation/merger.rb +22 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +31 -3
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +4 -6
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +5 -1
- data/lib/active_record/relation/predicate_builder.rb +27 -20
- data/lib/active_record/relation/query_attribute.rb +30 -12
- data/lib/active_record/relation/query_methods.rb +654 -127
- data/lib/active_record/relation/record_fetch_warning.rb +7 -9
- data/lib/active_record/relation/spawn_methods.rb +20 -3
- data/lib/active_record/relation/where_clause.rb +10 -19
- data/lib/active_record/relation.rb +262 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +18 -13
- data/lib/active_record/sanitization.rb +65 -20
- data/lib/active_record/schema.rb +36 -22
- data/lib/active_record/schema_dumper.rb +73 -24
- data/lib/active_record/schema_migration.rb +68 -33
- data/lib/active_record/scoping/default.rb +72 -15
- data/lib/active_record/scoping/named.rb +5 -13
- data/lib/active_record/scoping.rb +65 -34
- data/lib/active_record/secure_password.rb +60 -0
- data/lib/active_record/secure_token.rb +21 -3
- data/lib/active_record/serialization.rb +6 -1
- data/lib/active_record/signed_id.rb +10 -8
- data/lib/active_record/store.rb +10 -10
- data/lib/active_record/suppressor.rb +13 -15
- data/lib/active_record/table_metadata.rb +16 -3
- data/lib/active_record/tasks/database_tasks.rb +225 -136
- data/lib/active_record/tasks/mysql_database_tasks.rb +16 -7
- data/lib/active_record/tasks/postgresql_database_tasks.rb +35 -26
- data/lib/active_record/tasks/sqlite_database_tasks.rb +15 -7
- data/lib/active_record/test_databases.rb +1 -1
- data/lib/active_record/test_fixtures.rb +116 -96
- data/lib/active_record/timestamp.rb +28 -17
- data/lib/active_record/token_for.rb +113 -0
- data/lib/active_record/touch_later.rb +11 -6
- data/lib/active_record/transactions.rb +48 -27
- data/lib/active_record/translation.rb +3 -3
- data/lib/active_record/type/adapter_specific_registry.rb +32 -14
- data/lib/active_record/type/hash_lookup_type_map.rb +34 -1
- data/lib/active_record/type/internal/timezone.rb +7 -2
- data/lib/active_record/type/serialized.rb +9 -5
- data/lib/active_record/type/time.rb +4 -0
- data/lib/active_record/type/type_map.rb +17 -20
- data/lib/active_record/type.rb +1 -2
- data/lib/active_record/validations/absence.rb +1 -1
- data/lib/active_record/validations/associated.rb +4 -4
- 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 +51 -6
- data/lib/active_record/validations.rb +8 -4
- data/lib/active_record/version.rb +1 -1
- data/lib/active_record.rb +335 -32
- 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/errors.rb +10 -0
- data/lib/arel/factory_methods.rb +4 -0
- data/lib/arel/filter_predications.rb +9 -0
- data/lib/arel/insert_manager.rb +2 -3
- data/lib/arel/nodes/and.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/casted.rb +1 -1
- data/lib/arel/nodes/cte.rb +36 -0
- data/lib/arel/nodes/delete_statement.rb +12 -13
- data/lib/arel/nodes/filter.rb +10 -0
- data/lib/arel/nodes/fragments.rb +35 -0
- data/lib/arel/nodes/function.rb +1 -0
- data/lib/arel/nodes/homogeneous_in.rb +0 -8
- data/lib/arel/nodes/insert_statement.rb +2 -2
- data/lib/arel/nodes/leading_join.rb +8 -0
- data/lib/arel/nodes/node.rb +111 -2
- data/lib/arel/nodes/select_core.rb +2 -2
- data/lib/arel/nodes/select_statement.rb +2 -2
- data/lib/arel/nodes/sql_literal.rb +6 -0
- data/lib/arel/nodes/table_alias.rb +4 -0
- data/lib/arel/nodes/update_statement.rb +8 -3
- data/lib/arel/nodes.rb +5 -0
- data/lib/arel/predications.rb +13 -3
- data/lib/arel/select_manager.rb +10 -4
- data/lib/arel/table.rb +9 -6
- 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 +16 -3
- data/lib/arel/visitors/postgresql.rb +0 -10
- data/lib/arel/visitors/to_sql.rb +139 -19
- data/lib/arel/visitors/visitor.rb +2 -2
- data/lib/arel.rb +18 -3
- data/lib/rails/generators/active_record/application_record/USAGE +8 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +1 -1
- 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
- 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 +92 -13
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
data/lib/arel/visitors/to_sql.rb
CHANGED
@@ -103,7 +103,7 @@ module Arel # :nodoc: all
|
|
103
103
|
row.each_with_index do |value, k|
|
104
104
|
collector << ", " unless k == 0
|
105
105
|
case value
|
106
|
-
when Nodes::SqlLiteral, Nodes::BindParam
|
106
|
+
when Nodes::SqlLiteral, Nodes::BindParam, ActiveModel::Attribute
|
107
107
|
collector = visit(value, collector)
|
108
108
|
else
|
109
109
|
collector << quote(value).to_s
|
@@ -135,6 +135,8 @@ module Arel # :nodoc: all
|
|
135
135
|
visit_Arel_Nodes_SelectOptions(o, collector)
|
136
136
|
end
|
137
137
|
|
138
|
+
# The Oracle enhanced adapter uses this private method,
|
139
|
+
# see https://github.com/rsim/oracle-enhanced/issues/2186
|
138
140
|
def visit_Arel_Nodes_SelectOptions(o, collector)
|
139
141
|
collector = maybe_visit o.limit, collector
|
140
142
|
collector = maybe_visit o.offset, collector
|
@@ -243,6 +245,13 @@ module Arel # :nodoc: all
|
|
243
245
|
collector << ")"
|
244
246
|
end
|
245
247
|
|
248
|
+
def visit_Arel_Nodes_Filter(o, collector)
|
249
|
+
visit o.left, collector
|
250
|
+
collector << " FILTER (WHERE "
|
251
|
+
visit o.right, collector
|
252
|
+
collector << ")"
|
253
|
+
end
|
254
|
+
|
246
255
|
def visit_Arel_Nodes_Rows(o, collector)
|
247
256
|
if o.expr
|
248
257
|
collector << "ROWS "
|
@@ -324,7 +333,7 @@ module Arel # :nodoc: all
|
|
324
333
|
def visit_Arel_Nodes_HomogeneousIn(o, collector)
|
325
334
|
collector.preparable = false
|
326
335
|
|
327
|
-
|
336
|
+
visit o.left, collector
|
328
337
|
|
329
338
|
if o.type == :in
|
330
339
|
collector << " IN ("
|
@@ -341,7 +350,6 @@ module Arel # :nodoc: all
|
|
341
350
|
end
|
342
351
|
|
343
352
|
collector << ")"
|
344
|
-
collector
|
345
353
|
end
|
346
354
|
|
347
355
|
def visit_Arel_SelectManager(o, collector)
|
@@ -357,6 +365,17 @@ module Arel # :nodoc: all
|
|
357
365
|
visit(o.expr, collector) << " DESC"
|
358
366
|
end
|
359
367
|
|
368
|
+
# NullsFirst is available on all but MySQL, where it is redefined.
|
369
|
+
def visit_Arel_Nodes_NullsFirst(o, collector)
|
370
|
+
visit o.expr, collector
|
371
|
+
collector << " NULLS FIRST"
|
372
|
+
end
|
373
|
+
|
374
|
+
def visit_Arel_Nodes_NullsLast(o, collector)
|
375
|
+
visit o.expr, collector
|
376
|
+
collector << " NULLS LAST"
|
377
|
+
end
|
378
|
+
|
360
379
|
def visit_Arel_Nodes_Group(o, collector)
|
361
380
|
visit o.expr, collector
|
362
381
|
end
|
@@ -412,24 +431,48 @@ module Arel # :nodoc: all
|
|
412
431
|
end
|
413
432
|
|
414
433
|
def visit_Arel_Nodes_GreaterThanOrEqual(o, collector)
|
434
|
+
case unboundable?(o.right)
|
435
|
+
when 1
|
436
|
+
return collector << "1=0"
|
437
|
+
when -1
|
438
|
+
return collector << "1=1"
|
439
|
+
end
|
415
440
|
collector = visit o.left, collector
|
416
441
|
collector << " >= "
|
417
442
|
visit o.right, collector
|
418
443
|
end
|
419
444
|
|
420
445
|
def visit_Arel_Nodes_GreaterThan(o, collector)
|
446
|
+
case unboundable?(o.right)
|
447
|
+
when 1
|
448
|
+
return collector << "1=0"
|
449
|
+
when -1
|
450
|
+
return collector << "1=1"
|
451
|
+
end
|
421
452
|
collector = visit o.left, collector
|
422
453
|
collector << " > "
|
423
454
|
visit o.right, collector
|
424
455
|
end
|
425
456
|
|
426
457
|
def visit_Arel_Nodes_LessThanOrEqual(o, collector)
|
458
|
+
case unboundable?(o.right)
|
459
|
+
when 1
|
460
|
+
return collector << "1=1"
|
461
|
+
when -1
|
462
|
+
return collector << "1=0"
|
463
|
+
end
|
427
464
|
collector = visit o.left, collector
|
428
465
|
collector << " <= "
|
429
466
|
visit o.right, collector
|
430
467
|
end
|
431
468
|
|
432
469
|
def visit_Arel_Nodes_LessThan(o, collector)
|
470
|
+
case unboundable?(o.right)
|
471
|
+
when 1
|
472
|
+
return collector << "1=1"
|
473
|
+
when -1
|
474
|
+
return collector << "1=0"
|
475
|
+
end
|
433
476
|
collector = visit o.left, collector
|
434
477
|
collector << " < "
|
435
478
|
visit o.right, collector
|
@@ -525,11 +568,17 @@ module Arel # :nodoc: all
|
|
525
568
|
end
|
526
569
|
|
527
570
|
def visit_Arel_Table(o, collector)
|
528
|
-
if o.
|
529
|
-
|
571
|
+
if Arel::Nodes::Node === o.name
|
572
|
+
visit o.name, collector
|
530
573
|
else
|
531
574
|
collector << quote_table_name(o.name)
|
532
575
|
end
|
576
|
+
|
577
|
+
if o.table_alias
|
578
|
+
collector << " " << quote_table_name(o.table_alias)
|
579
|
+
end
|
580
|
+
|
581
|
+
collector
|
533
582
|
end
|
534
583
|
|
535
584
|
def visit_Arel_Nodes_In(o, collector)
|
@@ -585,7 +634,7 @@ module Arel # :nodoc: all
|
|
585
634
|
|
586
635
|
def visit_Arel_Nodes_Assignment(o, collector)
|
587
636
|
case o.right
|
588
|
-
when Arel::Nodes::Node, Arel::Attributes::Attribute
|
637
|
+
when Arel::Nodes::Node, Arel::Attributes::Attribute, ActiveModel::Attribute
|
589
638
|
collector = visit o.left, collector
|
590
639
|
collector << " = "
|
591
640
|
visit o.right, collector
|
@@ -685,6 +734,20 @@ module Arel # :nodoc: all
|
|
685
734
|
collector << quote_column_name(o.name)
|
686
735
|
end
|
687
736
|
|
737
|
+
def visit_Arel_Nodes_Cte(o, collector)
|
738
|
+
collector << quote_table_name(o.name)
|
739
|
+
collector << " AS "
|
740
|
+
|
741
|
+
case o.materialized
|
742
|
+
when true
|
743
|
+
collector << "MATERIALIZED "
|
744
|
+
when false
|
745
|
+
collector << "NOT MATERIALIZED "
|
746
|
+
end
|
747
|
+
|
748
|
+
visit o.relation, collector
|
749
|
+
end
|
750
|
+
|
688
751
|
def visit_Arel_Attributes_Attribute(o, collector)
|
689
752
|
join_name = o.relation.table_alias || o.relation.name
|
690
753
|
collector << quote_table_name(join_name) << "." << quote_column_name(o.name)
|
@@ -695,6 +758,10 @@ module Arel # :nodoc: all
|
|
695
758
|
|
696
759
|
def bind_block; BIND_BLOCK; end
|
697
760
|
|
761
|
+
def visit_ActiveModel_Attribute(o, collector)
|
762
|
+
collector.add_bind(o, &bind_block)
|
763
|
+
end
|
764
|
+
|
698
765
|
def visit_Arel_Nodes_BindParam(o, collector)
|
699
766
|
collector.add_bind(o.value, &bind_block)
|
700
767
|
end
|
@@ -704,6 +771,59 @@ module Arel # :nodoc: all
|
|
704
771
|
collector << o.to_s
|
705
772
|
end
|
706
773
|
|
774
|
+
def visit_Arel_Nodes_BoundSqlLiteral(o, collector)
|
775
|
+
bind_index = 0
|
776
|
+
|
777
|
+
new_bind = lambda do |value|
|
778
|
+
if Arel.arel_node?(value)
|
779
|
+
visit value, collector
|
780
|
+
elsif value.is_a?(Array)
|
781
|
+
if value.empty?
|
782
|
+
collector << @connection.quote(nil)
|
783
|
+
else
|
784
|
+
if value.none? { |v| Arel.arel_node?(v) }
|
785
|
+
collector.add_binds(value.map { |v| @connection.cast_bound_value(v) }, &bind_block)
|
786
|
+
else
|
787
|
+
value.each_with_index do |v, i|
|
788
|
+
collector << ", " unless i == 0
|
789
|
+
if Arel.arel_node?(v)
|
790
|
+
visit v, collector
|
791
|
+
else
|
792
|
+
collector.add_bind(@connection.cast_bound_value(v), &bind_block)
|
793
|
+
end
|
794
|
+
end
|
795
|
+
end
|
796
|
+
end
|
797
|
+
else
|
798
|
+
collector.add_bind(@connection.cast_bound_value(value), &bind_block)
|
799
|
+
end
|
800
|
+
end
|
801
|
+
|
802
|
+
if o.positional_binds
|
803
|
+
o.sql_with_placeholders.scan(/\?|([^?]+)/) do
|
804
|
+
if $1
|
805
|
+
collector << $1
|
806
|
+
else
|
807
|
+
value = o.positional_binds[bind_index]
|
808
|
+
bind_index += 1
|
809
|
+
|
810
|
+
new_bind.call(value)
|
811
|
+
end
|
812
|
+
end
|
813
|
+
else
|
814
|
+
o.sql_with_placeholders.scan(/:(?<!::)([a-zA-Z]\w*)|([^:]+|.)/) do
|
815
|
+
if $2
|
816
|
+
collector << $2
|
817
|
+
else
|
818
|
+
value = o.named_binds[$1.to_sym]
|
819
|
+
new_bind.call(value)
|
820
|
+
end
|
821
|
+
end
|
822
|
+
end
|
823
|
+
|
824
|
+
collector
|
825
|
+
end
|
826
|
+
|
707
827
|
def visit_Integer(o, collector)
|
708
828
|
collector << o.to_s
|
709
829
|
end
|
@@ -743,6 +863,10 @@ module Arel # :nodoc: all
|
|
743
863
|
end
|
744
864
|
alias :visit_Set :visit_Array
|
745
865
|
|
866
|
+
def visit_Arel_Nodes_Fragments(o, collector)
|
867
|
+
inject_join o.values, collector, " "
|
868
|
+
end
|
869
|
+
|
746
870
|
def quote(value)
|
747
871
|
return value if Arel::Nodes::SqlLiteral === value
|
748
872
|
@connection.quote value
|
@@ -793,6 +917,10 @@ module Arel # :nodoc: all
|
|
793
917
|
o.limit || o.offset || !o.orders.empty?
|
794
918
|
end
|
795
919
|
|
920
|
+
def has_group_by_and_having?(o)
|
921
|
+
!o.groups.empty? && !o.havings.empty?
|
922
|
+
end
|
923
|
+
|
796
924
|
# The default strategy for an UPDATE with joins is to use a subquery. This doesn't work
|
797
925
|
# on MySQL (even when aliasing the tables), but MySQL allows using JOIN directly in
|
798
926
|
# an UPDATE statement, so in the MySQL visitor we redefine this to do that.
|
@@ -804,6 +932,8 @@ module Arel # :nodoc: all
|
|
804
932
|
stmt.orders = []
|
805
933
|
stmt.wheres = [Nodes::In.new(o.key, [build_subselect(o.key, o)])]
|
806
934
|
stmt.relation = o.relation.left if has_join_sources?(o)
|
935
|
+
stmt.groups = o.groups unless o.groups.empty?
|
936
|
+
stmt.havings = o.havings unless o.havings.empty?
|
807
937
|
stmt
|
808
938
|
else
|
809
939
|
o
|
@@ -818,6 +948,8 @@ module Arel # :nodoc: all
|
|
818
948
|
core.froms = o.relation
|
819
949
|
core.wheres = o.wheres
|
820
950
|
core.projections = [key]
|
951
|
+
core.groups = o.groups unless o.groups.empty?
|
952
|
+
core.havings = o.havings unless o.havings.empty?
|
821
953
|
stmt.limit = o.limit
|
822
954
|
stmt.offset = o.offset
|
823
955
|
stmt.orders = o.orders
|
@@ -877,19 +1009,7 @@ module Arel # :nodoc: all
|
|
877
1009
|
def collect_ctes(children, collector)
|
878
1010
|
children.each_with_index do |child, i|
|
879
1011
|
collector << ", " unless i == 0
|
880
|
-
|
881
|
-
case child
|
882
|
-
when Arel::Nodes::As
|
883
|
-
name = child.left.name
|
884
|
-
relation = child.right
|
885
|
-
when Arel::Nodes::TableAlias
|
886
|
-
name = child.name
|
887
|
-
relation = child.relation
|
888
|
-
end
|
889
|
-
|
890
|
-
collector << quote_table_name(name)
|
891
|
-
collector << " AS "
|
892
|
-
visit relation, collector
|
1012
|
+
visit child.to_cte, collector
|
893
1013
|
end
|
894
1014
|
|
895
1015
|
collector
|
@@ -16,8 +16,8 @@ module Arel # :nodoc: all
|
|
16
16
|
|
17
17
|
def self.dispatch_cache
|
18
18
|
@dispatch_cache ||= Hash.new do |hash, klass|
|
19
|
-
hash[klass] = "visit_#{(klass.name ||
|
20
|
-
end
|
19
|
+
hash[klass] = :"visit_#{(klass.name || "").gsub("::", "_")}"
|
20
|
+
end.compare_by_identity
|
21
21
|
end
|
22
22
|
|
23
23
|
def get_dispatch_cache
|
data/lib/arel.rb
CHANGED
@@ -7,6 +7,7 @@ require "arel/factory_methods"
|
|
7
7
|
|
8
8
|
require "arel/expressions"
|
9
9
|
require "arel/predications"
|
10
|
+
require "arel/filter_predications"
|
10
11
|
require "arel/window_predications"
|
11
12
|
require "arel/math"
|
12
13
|
require "arel/alias_predication"
|
@@ -29,13 +30,27 @@ module Arel
|
|
29
30
|
|
30
31
|
# Wrap a known-safe SQL string for passing to query methods, e.g.
|
31
32
|
#
|
32
|
-
# Post.order(Arel.sql("
|
33
|
+
# Post.order(Arel.sql("REPLACE(title, 'misc', 'zzzz') asc")).pluck(:id)
|
33
34
|
#
|
34
35
|
# Great caution should be taken to avoid SQL injection vulnerabilities.
|
35
36
|
# This method should not be used with unsafe values such as request
|
36
37
|
# parameters or model attributes.
|
37
|
-
|
38
|
-
|
38
|
+
#
|
39
|
+
# Take a look at the {security guide}[https://guides.rubyonrails.org/security.html#sql-injection]
|
40
|
+
# for more information.
|
41
|
+
#
|
42
|
+
# To construct a more complex query fragment, including the possible
|
43
|
+
# use of user-provided values, the +sql_string+ may contain <tt>?</tt> and
|
44
|
+
# +:key+ placeholders, corresponding to the additional arguments. Note
|
45
|
+
# that this behavior only applies when bind value parameters are
|
46
|
+
# supplied in the call; without them, the placeholder tokens have no
|
47
|
+
# special meaning, and will be passed through to the query as-is.
|
48
|
+
def self.sql(sql_string, *positional_binds, **named_binds)
|
49
|
+
if positional_binds.empty? && named_binds.empty?
|
50
|
+
Arel::Nodes::SqlLiteral.new sql_string
|
51
|
+
else
|
52
|
+
Arel::Nodes::BoundSqlLiteral.new sql_string, positional_binds, named_binds
|
53
|
+
end
|
39
54
|
end
|
40
55
|
|
41
56
|
def self.star # :nodoc:
|
@@ -0,0 +1,8 @@
|
|
1
|
+
Description:
|
2
|
+
Generates an `ApplicationRecord` base class for other models to inherit from.
|
3
|
+
|
4
|
+
Example:
|
5
|
+
`bin/rails generate application_record`
|
6
|
+
|
7
|
+
This generates the base class. A test is not generated because no
|
8
|
+
behaviour is included in `ApplicationRecord` by default.
|
@@ -41,11 +41,13 @@ module ActiveRecord
|
|
41
41
|
|
42
42
|
def configured_migrate_path
|
43
43
|
return unless database = options[:database]
|
44
|
+
|
44
45
|
config = ActiveRecord::Base.configurations.configs_for(
|
45
46
|
env_name: Rails.env,
|
46
47
|
name: database
|
47
48
|
)
|
48
|
-
|
49
|
+
|
50
|
+
Array(config&.migrations_paths).first
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
Description:
|
2
|
+
Generates a new model. Pass the model name, either CamelCased or
|
3
|
+
under_scored, and an optional list of attribute pairs as arguments.
|
4
|
+
|
5
|
+
Attribute pairs are field:type arguments specifying the
|
6
|
+
model's attributes. Timestamps are added by default, so you don't have to
|
7
|
+
specify them by hand as 'created_at:datetime updated_at:datetime'.
|
8
|
+
|
9
|
+
As a special case, specifying 'password:digest' will generate a
|
10
|
+
password_digest field of string type, and configure your generated model and
|
11
|
+
tests for use with Active Model has_secure_password (assuming the default ORM
|
12
|
+
and test framework are being used).
|
13
|
+
|
14
|
+
You don't have to think up every attribute up front, but it helps to
|
15
|
+
sketch out a few so you can start working with the model immediately.
|
16
|
+
|
17
|
+
This generator invokes your configured ORM and test framework, which
|
18
|
+
defaults to Active Record and TestUnit.
|
19
|
+
|
20
|
+
Finally, if --parent option is given, it's used as superclass of the
|
21
|
+
created model. This allows you create Single Table Inheritance models.
|
22
|
+
|
23
|
+
If you pass a namespaced model name (e.g. admin/account or Admin::Account)
|
24
|
+
then the generator will create a module with a table_name_prefix method
|
25
|
+
to prefix the model's table name with the module name (e.g. admin_accounts)
|
26
|
+
|
27
|
+
Available field types:
|
28
|
+
|
29
|
+
Just after the field name you can specify a type like text or boolean.
|
30
|
+
It will generate the column with the associated SQL type. For instance:
|
31
|
+
|
32
|
+
`bin/rails generate model post title:string body:text`
|
33
|
+
|
34
|
+
will generate a title column with a varchar type and a body column with a text
|
35
|
+
type. If no type is specified the string type will be used by default.
|
36
|
+
You can use the following types:
|
37
|
+
|
38
|
+
integer
|
39
|
+
primary_key
|
40
|
+
decimal
|
41
|
+
float
|
42
|
+
boolean
|
43
|
+
binary
|
44
|
+
string
|
45
|
+
text
|
46
|
+
date
|
47
|
+
time
|
48
|
+
datetime
|
49
|
+
|
50
|
+
You can also consider `references` as a kind of type. For instance, if you run:
|
51
|
+
|
52
|
+
`bin/rails generate model photo title:string album:references`
|
53
|
+
|
54
|
+
It will generate an `album_id` column. You should generate these kinds of fields when
|
55
|
+
you will use a `belongs_to` association, for instance. `references` also supports
|
56
|
+
polymorphism, you can enable polymorphism like this:
|
57
|
+
|
58
|
+
`bin/rails generate model product supplier:references{polymorphic}`
|
59
|
+
|
60
|
+
For integer, string, text and binary fields, an integer in curly braces will
|
61
|
+
be set as the limit:
|
62
|
+
|
63
|
+
`bin/rails generate model user pseudo:string{30}`
|
64
|
+
|
65
|
+
For decimal, two integers separated by a comma in curly braces will be used
|
66
|
+
for precision and scale:
|
67
|
+
|
68
|
+
`bin/rails generate model product 'price:decimal{10,2}'`
|
69
|
+
|
70
|
+
You can add a `:uniq` or `:index` suffix for unique or standard indexes
|
71
|
+
respectively:
|
72
|
+
|
73
|
+
`bin/rails generate model user pseudo:string:uniq`
|
74
|
+
`bin/rails generate model user pseudo:string:index`
|
75
|
+
|
76
|
+
You can combine any single curly brace option with the index options:
|
77
|
+
|
78
|
+
`bin/rails generate model user username:string{30}:uniq`
|
79
|
+
`bin/rails generate model product supplier:references{polymorphic}:index`
|
80
|
+
|
81
|
+
If you require a `password_digest` string column for use with
|
82
|
+
has_secure_password, you can specify `password:digest`:
|
83
|
+
|
84
|
+
`bin/rails generate model user password:digest`
|
85
|
+
|
86
|
+
If you require a `token` string column for use with
|
87
|
+
has_secure_token, you can specify `auth_token:token`:
|
88
|
+
|
89
|
+
`bin/rails generate model user auth_token:token`
|
90
|
+
|
91
|
+
Examples:
|
92
|
+
`bin/rails generate model account`
|
93
|
+
|
94
|
+
For Active Record and TestUnit it creates:
|
95
|
+
|
96
|
+
Model: app/models/account.rb
|
97
|
+
Test: test/models/account_test.rb
|
98
|
+
Fixtures: test/fixtures/accounts.yml
|
99
|
+
Migration: db/migrate/XXX_create_accounts.rb
|
100
|
+
|
101
|
+
`bin/rails generate model post title:string body:text published:boolean`
|
102
|
+
|
103
|
+
Creates a Post model with a string title, text body, and published flag.
|
104
|
+
|
105
|
+
`bin/rails generate model admin/account`
|
106
|
+
|
107
|
+
For Active Record and TestUnit it creates:
|
108
|
+
|
109
|
+
Module: app/models/admin.rb
|
110
|
+
Model: app/models/admin/account.rb
|
111
|
+
Test: test/models/admin/account_test.rb
|
112
|
+
Fixtures: test/fixtures/admin/accounts.yml
|
113
|
+
Migration: db/migrate/XXX_create_admin_accounts.rb
|
@@ -11,20 +11,25 @@ module ActiveRecord
|
|
11
11
|
|
12
12
|
class_option :migration, type: :boolean
|
13
13
|
class_option :timestamps, type: :boolean
|
14
|
-
class_option :parent, type: :string, desc: "The parent class for the generated model"
|
14
|
+
class_option :parent, type: :string, default: "ApplicationRecord", desc: "The parent class for the generated model"
|
15
15
|
class_option :indexes, type: :boolean, default: true, desc: "Add indexes for references and belongs_to columns"
|
16
16
|
class_option :primary_key_type, type: :string, desc: "The type for primary key"
|
17
17
|
class_option :database, type: :string, aliases: %i(--db), desc: "The database for your model's migration. By default, the current environment's primary database is used."
|
18
18
|
|
19
|
+
Rails::Generators.templates_path.each do |path|
|
20
|
+
source_paths << File.join(path, base_name, "migration")
|
21
|
+
end
|
22
|
+
source_paths << File.expand_path(File.join(base_name, "migration", "templates"), base_root)
|
23
|
+
|
19
24
|
# creates the migration file for the model.
|
20
25
|
def create_migration_file
|
21
26
|
return if skip_migration_creation?
|
22
27
|
attributes.each { |a| a.attr_options.delete(:index) if a.reference? && !a.has_index? } if options[:indexes] == false
|
23
|
-
migration_template "
|
28
|
+
migration_template "create_table_migration.rb", File.join(db_migrate_path, "create_#{table_name}.rb")
|
24
29
|
end
|
25
30
|
|
26
31
|
def create_model_file
|
27
|
-
generate_abstract_class if database && !
|
32
|
+
generate_abstract_class if database && !custom_parent?
|
28
33
|
template "model.rb", File.join("app/models", class_path, "#{file_name}.rb")
|
29
34
|
end
|
30
35
|
|
@@ -40,7 +45,7 @@ module ActiveRecord
|
|
40
45
|
# - options parent is present and database option is not present
|
41
46
|
# - migrations option is nil or false
|
42
47
|
def skip_migration_creation?
|
43
|
-
|
48
|
+
custom_parent? && !database || !migration
|
44
49
|
end
|
45
50
|
|
46
51
|
def attributes_with_index
|
@@ -49,12 +54,12 @@ module ActiveRecord
|
|
49
54
|
|
50
55
|
# Used by the migration template to determine the parent name of the model
|
51
56
|
def parent_class_name
|
52
|
-
if
|
57
|
+
if custom_parent?
|
53
58
|
parent
|
54
59
|
elsif database
|
55
60
|
abstract_class_name
|
56
61
|
else
|
57
|
-
|
62
|
+
parent
|
58
63
|
end
|
59
64
|
end
|
60
65
|
|
@@ -77,6 +82,10 @@ module ActiveRecord
|
|
77
82
|
options[:parent]
|
78
83
|
end
|
79
84
|
|
85
|
+
def custom_parent?
|
86
|
+
parent != self.class.class_options[:parent].default
|
87
|
+
end
|
88
|
+
|
80
89
|
def migration
|
81
90
|
options[:migration]
|
82
91
|
end
|
@@ -2,6 +2,6 @@
|
|
2
2
|
class <%= abstract_class_name %> < ApplicationRecord
|
3
3
|
self.abstract_class = true
|
4
4
|
|
5
|
-
connects_to database: { <%= ActiveRecord
|
5
|
+
connects_to database: { <%= ActiveRecord.writing_role %>: :<%= database -%> }
|
6
6
|
end
|
7
7
|
<% end -%>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
2
|
class <%= class_name %> < <%= parent_class_name.classify %>
|
3
3
|
<% attributes.select(&:reference?).each do |attribute| -%>
|
4
|
-
belongs_to :<%= attribute.name %><%=
|
4
|
+
belongs_to :<%= attribute.name %><%= ", polymorphic: true" if attribute.polymorphic? %>
|
5
5
|
<% end -%>
|
6
6
|
<% attributes.select(&:rich_text?).each do |attribute| -%>
|
7
7
|
has_rich_text :<%= attribute.name %>
|
@@ -1,7 +1,7 @@
|
|
1
1
|
<% module_namespacing do -%>
|
2
|
-
module <%= class_path.map(&:camelize).join(
|
2
|
+
module <%= class_path.map(&:camelize).join("::") %>
|
3
3
|
def self.table_name_prefix
|
4
|
-
|
4
|
+
"<%= namespaced? ? namespaced_class_path.join("_") : class_path.join("_") %>_"
|
5
5
|
end
|
6
6
|
end
|
7
7
|
<% end -%>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rails/generators/active_record"
|
4
|
+
|
5
|
+
module ActiveRecord
|
6
|
+
module Generators # :nodoc:
|
7
|
+
class MultiDbGenerator < ::Rails::Generators::Base # :nodoc:
|
8
|
+
source_root File.expand_path("templates", __dir__)
|
9
|
+
|
10
|
+
def create_multi_db
|
11
|
+
filename = "multi_db.rb"
|
12
|
+
template filename, "config/initializers/#{filename}"
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Multi-db Configuration
|
2
|
+
#
|
3
|
+
# This file is used for configuration settings related to multiple databases.
|
4
|
+
#
|
5
|
+
# Enable Database Selector
|
6
|
+
#
|
7
|
+
# Inserts middleware to perform automatic connection switching.
|
8
|
+
# The `database_selector` hash is used to pass options to the DatabaseSelector
|
9
|
+
# middleware. The `delay` is used to determine how long to wait after a write
|
10
|
+
# to send a subsequent read to the primary.
|
11
|
+
#
|
12
|
+
# The `database_resolver` class is used by the middleware to determine which
|
13
|
+
# database is appropriate to use based on the time delay.
|
14
|
+
#
|
15
|
+
# The `database_resolver_context` class is used by the middleware to set
|
16
|
+
# timestamps for the last write to the primary. The resolver uses the context
|
17
|
+
# class timestamps to determine how long to wait before reading from the
|
18
|
+
# replica.
|
19
|
+
#
|
20
|
+
# By default Rails will store a last write timestamp in the session. The
|
21
|
+
# DatabaseSelector middleware is designed as such you can define your own
|
22
|
+
# strategy for connection switching and pass that into the middleware through
|
23
|
+
# these configuration options.
|
24
|
+
#
|
25
|
+
# Rails.application.configure do
|
26
|
+
# config.active_record.database_selector = { delay: 2.seconds }
|
27
|
+
# config.active_record.database_resolver = ActiveRecord::Middleware::DatabaseSelector::Resolver
|
28
|
+
# config.active_record.database_resolver_context = ActiveRecord::Middleware::DatabaseSelector::Resolver::Session
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# Enable Shard Selector
|
32
|
+
#
|
33
|
+
# Inserts middleware to perform automatic shard swapping. The `shard_selector` hash
|
34
|
+
# can be used to pass options to the `ShardSelector` middleware. The `lock` option is
|
35
|
+
# used to determine whether shard swapping should be prohibited for the request.
|
36
|
+
#
|
37
|
+
# The `shard_resolver` option is used by the middleware to determine which shard
|
38
|
+
# to switch to. The application must provide a mechanism for finding the shard name
|
39
|
+
# in a proc. See guides for an example.
|
40
|
+
#
|
41
|
+
# Rails.application.configure do
|
42
|
+
# config.active_record.shard_selector = { lock: true }
|
43
|
+
# config.active_record.shard_resolver = ->(request) { Tenant.find_by!(host: request.host).shard }
|
44
|
+
# end
|