activerecord 6.1.7 → 7.1.5
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 +2030 -1020
- data/MIT-LICENSE +1 -1
- data/README.rdoc +18 -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 +51 -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 +39 -35
- 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/join_association.rb +3 -2
- data/lib/active_record/associations/join_dependency.rb +28 -20
- data/lib/active_record/associations/preloader/association.rb +210 -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 +446 -306
- 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 +73 -22
- 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 +27 -12
- data/lib/active_record/attribute_methods/serialization.rb +194 -37
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +8 -3
- data/lib/active_record/attribute_methods/write.rb +12 -15
- data/lib/active_record/attribute_methods.rb +161 -40
- data/lib/active_record/attributes.rb +27 -38
- data/lib/active_record/autosave_association.rb +65 -31
- 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 +113 -597
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +5 -17
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +172 -50
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -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 +367 -141
- data/lib/active_record/connection_adapters/abstract/transaction.rb +281 -59
- data/lib/active_record/connection_adapters/abstract_adapter.rb +631 -150
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +317 -164
- 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 +39 -14
- data/lib/active_record/connection_adapters/mysql2/database_statements.rb +151 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +112 -55
- 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 +30 -1
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +89 -52
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +6 -0
- 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/money.rb +3 -2
- 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 +397 -75
- data/lib/active_record/connection_adapters/postgresql/utils.rb +9 -10
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +508 -246
- 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 +72 -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 +296 -104
- data/lib/active_record/connection_adapters/statement_pool.rb +7 -0
- data/lib/active_record/connection_adapters/trilogy/database_statements.rb +99 -0
- data/lib/active_record/connection_adapters/trilogy_adapter.rb +258 -0
- data/lib/active_record/connection_adapters.rb +9 -6
- data/lib/active_record/connection_handling.rb +108 -137
- data/lib/active_record/core.rb +242 -233
- data/lib/active_record/counter_cache.rb +52 -27
- data/lib/active_record/database_configurations/connection_url_resolver.rb +3 -2
- data/lib/active_record/database_configurations/database_config.rb +21 -12
- data/lib/active_record/database_configurations/hash_config.rb +88 -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 +66 -20
- data/lib/active_record/deprecator.rb +7 -0
- data/lib/active_record/destroy_association_async_job.rb +4 -2
- 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 +230 -0
- data/lib/active_record/encryption/encrypted_attribute_type.rb +155 -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 +157 -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 +100 -0
- data/lib/active_record/encryption.rb +58 -0
- data/lib/active_record/enum.rb +154 -63
- data/lib/active_record/errors.rb +172 -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 +147 -86
- data/lib/active_record/future_result.rb +174 -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 +135 -22
- data/lib/active_record/integration.rb +11 -10
- data/lib/active_record/internal_metadata.rb +119 -33
- data/lib/active_record/legacy_yaml_adapter.rb +2 -39
- data/lib/active_record/locking/optimistic.rb +37 -22
- data/lib/active_record/locking/pessimistic.rb +15 -6
- data/lib/active_record/log_subscriber.rb +52 -19
- data/lib/active_record/marshalling.rb +59 -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 +112 -14
- data/lib/active_record/migration/compatibility.rb +233 -46
- 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/pending_migration_connection.rb +21 -0
- data/lib/active_record/migration.rb +361 -173
- data/lib/active_record/model_schema.rb +125 -101
- data/lib/active_record/nested_attributes.rb +50 -20
- data/lib/active_record/no_touching.rb +3 -3
- data/lib/active_record/normalization.rb +167 -0
- data/lib/active_record/persistence.rb +409 -88
- data/lib/active_record/promise.rb +84 -0
- data/lib/active_record/query_cache.rb +4 -22
- 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 +220 -44
- data/lib/active_record/railties/controller_runtime.rb +15 -10
- data/lib/active_record/railties/databases.rake +188 -252
- 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 +248 -81
- 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 +246 -90
- data/lib/active_record/relation/delegation.rb +28 -14
- 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 +10 -7
- 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 +670 -129
- 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 +287 -120
- data/lib/active_record/result.rb +37 -11
- data/lib/active_record/runtime_registry.rb +32 -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 +251 -140
- 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 +117 -96
- data/lib/active_record/timestamp.rb +32 -19
- 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 +1 -9
- 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 +5 -13
- 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 +141 -20
- 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 +96 -16
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +0 -35
- data/lib/active_record/null_relation.rb +0 -67
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Encryption
|
5
|
+
# This is a wrapper for a hash of encryption properties. It is used by
|
6
|
+
# +Key+ (public tags) and +Message+ (headers).
|
7
|
+
#
|
8
|
+
# Since properties are serialized in messages, it is important for storage
|
9
|
+
# efficiency to keep their keys as short as possible. It defines accessors
|
10
|
+
# for common properties that will keep these keys very short while exposing
|
11
|
+
# a readable name.
|
12
|
+
#
|
13
|
+
# message.headers.encrypted_data_key # instead of message.headers[:k]
|
14
|
+
#
|
15
|
+
# See +Properties::DEFAULT_PROPERTIES+, Key, Message
|
16
|
+
class Properties
|
17
|
+
ALLOWED_VALUE_CLASSES = [String, ActiveRecord::Encryption::Message, Numeric, Integer, Float, BigDecimal, TrueClass, FalseClass, Symbol, NilClass]
|
18
|
+
|
19
|
+
delegate_missing_to :data
|
20
|
+
delegate :==, :[], :each, :key?, to: :data
|
21
|
+
|
22
|
+
# For each entry it generates an accessor exposing the full name
|
23
|
+
DEFAULT_PROPERTIES = {
|
24
|
+
encrypted_data_key: "k",
|
25
|
+
encrypted_data_key_id: "i",
|
26
|
+
compressed: "c",
|
27
|
+
iv: "iv",
|
28
|
+
auth_tag: "at",
|
29
|
+
encoding: "e"
|
30
|
+
}
|
31
|
+
|
32
|
+
DEFAULT_PROPERTIES.each do |name, key|
|
33
|
+
define_method name do
|
34
|
+
self[key.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
define_method "#{name}=" do |value|
|
38
|
+
self[key.to_sym] = value
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def initialize(initial_properties = {})
|
43
|
+
@data = {}
|
44
|
+
add(initial_properties)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Set a value for a given key
|
48
|
+
#
|
49
|
+
# It will raise an +EncryptedContentIntegrity+ if the value exists
|
50
|
+
def []=(key, value)
|
51
|
+
raise Errors::EncryptedContentIntegrity, "Properties can't be overridden: #{key}" if key?(key)
|
52
|
+
validate_value_type(value)
|
53
|
+
data[key] = value
|
54
|
+
end
|
55
|
+
|
56
|
+
def validate_value_type(value)
|
57
|
+
unless ALLOWED_VALUE_CLASSES.include?(value.class) || ALLOWED_VALUE_CLASSES.any? { |klass| value.is_a?(klass) }
|
58
|
+
raise ActiveRecord::Encryption::Errors::ForbiddenClass, "Can't store a #{value.class}, only properties of type #{ALLOWED_VALUE_CLASSES.inspect} are allowed"
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def add(other_properties)
|
63
|
+
other_properties.each do |key, value|
|
64
|
+
self[key.to_sym] = value
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def to_h
|
69
|
+
data
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
attr_reader :data
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Encryption
|
5
|
+
# A +NullEncryptor+ that will raise an error when trying to encrypt data
|
6
|
+
#
|
7
|
+
# This is useful when you want to reveal ciphertexts for debugging purposes
|
8
|
+
# and you want to make sure you won't overwrite any encryptable attribute with
|
9
|
+
# the wrong content.
|
10
|
+
class ReadOnlyNullEncryptor
|
11
|
+
def encrypt(clean_text, key_provider: nil, cipher_options: {})
|
12
|
+
raise Errors::Encryption, "This encryptor is read-only"
|
13
|
+
end
|
14
|
+
|
15
|
+
def decrypt(encrypted_text, key_provider: nil, cipher_options: {})
|
16
|
+
encrypted_text
|
17
|
+
end
|
18
|
+
|
19
|
+
def encrypted?(text)
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module Encryption
|
5
|
+
# A container of attribute encryption options.
|
6
|
+
#
|
7
|
+
# It validates and serves attribute encryption options.
|
8
|
+
#
|
9
|
+
# See EncryptedAttributeType, Context
|
10
|
+
class Scheme
|
11
|
+
attr_accessor :previous_schemes
|
12
|
+
|
13
|
+
def initialize(key_provider: nil, key: nil, deterministic: nil, support_unencrypted_data: nil, downcase: nil, ignore_case: nil,
|
14
|
+
previous_schemes: nil, **context_properties)
|
15
|
+
# Initializing all attributes to +nil+ as we want to allow a "not set" semantics so that we
|
16
|
+
# can merge schemes without overriding values with defaults. See +#merge+
|
17
|
+
|
18
|
+
@key_provider_param = key_provider
|
19
|
+
@key = key
|
20
|
+
@deterministic = deterministic
|
21
|
+
@support_unencrypted_data = support_unencrypted_data
|
22
|
+
@downcase = downcase || ignore_case
|
23
|
+
@ignore_case = ignore_case
|
24
|
+
@previous_schemes_param = previous_schemes
|
25
|
+
@previous_schemes = Array.wrap(previous_schemes)
|
26
|
+
@context_properties = context_properties
|
27
|
+
|
28
|
+
validate_config!
|
29
|
+
end
|
30
|
+
|
31
|
+
def ignore_case?
|
32
|
+
@ignore_case
|
33
|
+
end
|
34
|
+
|
35
|
+
def downcase?
|
36
|
+
@downcase
|
37
|
+
end
|
38
|
+
|
39
|
+
def deterministic?
|
40
|
+
!!@deterministic
|
41
|
+
end
|
42
|
+
|
43
|
+
def support_unencrypted_data?
|
44
|
+
@support_unencrypted_data.nil? ? ActiveRecord::Encryption.config.support_unencrypted_data : @support_unencrypted_data
|
45
|
+
end
|
46
|
+
|
47
|
+
def fixed?
|
48
|
+
# by default deterministic encryption is fixed
|
49
|
+
@fixed ||= @deterministic && (!@deterministic.is_a?(Hash) || @deterministic[:fixed])
|
50
|
+
end
|
51
|
+
|
52
|
+
def key_provider
|
53
|
+
@key_provider_param || key_provider_from_key || deterministic_key_provider || default_key_provider
|
54
|
+
end
|
55
|
+
|
56
|
+
def merge(other_scheme)
|
57
|
+
self.class.new(**to_h.merge(other_scheme.to_h))
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_h
|
61
|
+
{ key_provider: @key_provider_param, deterministic: @deterministic, downcase: @downcase, ignore_case: @ignore_case,
|
62
|
+
previous_schemes: @previous_schemes_param, **@context_properties }.compact
|
63
|
+
end
|
64
|
+
|
65
|
+
def with_context(&block)
|
66
|
+
if @context_properties.present?
|
67
|
+
ActiveRecord::Encryption.with_encryption_context(**@context_properties, &block)
|
68
|
+
else
|
69
|
+
block.call
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def compatible_with?(other_scheme)
|
74
|
+
deterministic? == other_scheme.deterministic?
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
def validate_config!
|
79
|
+
raise Errors::Configuration, "ignore_case: can only be used with deterministic encryption" if @ignore_case && !@deterministic
|
80
|
+
raise Errors::Configuration, "key_provider: and key: can't be used simultaneously" if @key_provider_param && @key
|
81
|
+
end
|
82
|
+
|
83
|
+
def key_provider_from_key
|
84
|
+
@key_provider_from_key ||= if @key.present?
|
85
|
+
DerivedSecretKeyProvider.new(@key)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def deterministic_key_provider
|
90
|
+
@deterministic_key_provider ||= if @deterministic
|
91
|
+
DeterministicKeyProvider.new(ActiveRecord::Encryption.config.deterministic_key)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def default_key_provider
|
96
|
+
ActiveRecord::Encryption.key_provider
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/module"
|
4
|
+
require "active_support/core_ext/array"
|
5
|
+
|
6
|
+
module ActiveRecord
|
7
|
+
module Encryption
|
8
|
+
extend ActiveSupport::Autoload
|
9
|
+
|
10
|
+
eager_autoload do
|
11
|
+
autoload :AutoFilteredParameters
|
12
|
+
autoload :Cipher
|
13
|
+
autoload :Config
|
14
|
+
autoload :Configurable
|
15
|
+
autoload :Context
|
16
|
+
autoload :Contexts
|
17
|
+
autoload :DerivedSecretKeyProvider
|
18
|
+
autoload :EncryptableRecord
|
19
|
+
autoload :EncryptedAttributeType
|
20
|
+
autoload :EncryptedFixtures
|
21
|
+
autoload :EncryptingOnlyEncryptor
|
22
|
+
autoload :DeterministicKeyProvider
|
23
|
+
autoload :Encryptor
|
24
|
+
autoload :EnvelopeEncryptionKeyProvider
|
25
|
+
autoload :Errors
|
26
|
+
autoload :ExtendedDeterministicQueries
|
27
|
+
autoload :ExtendedDeterministicUniquenessValidator
|
28
|
+
autoload :Key
|
29
|
+
autoload :KeyGenerator
|
30
|
+
autoload :KeyProvider
|
31
|
+
autoload :Message
|
32
|
+
autoload :MessageSerializer
|
33
|
+
autoload :NullEncryptor
|
34
|
+
autoload :Properties
|
35
|
+
autoload :ReadOnlyNullEncryptor
|
36
|
+
autoload :Scheme
|
37
|
+
end
|
38
|
+
|
39
|
+
class Cipher
|
40
|
+
extend ActiveSupport::Autoload
|
41
|
+
|
42
|
+
eager_autoload do
|
43
|
+
autoload :Aes256Gcm
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
include Configurable
|
48
|
+
include Contexts
|
49
|
+
|
50
|
+
def self.eager_load!
|
51
|
+
super
|
52
|
+
|
53
|
+
Cipher.eager_load!
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
ActiveSupport.run_load_hooks :active_record_encryption, Encryption
|
58
|
+
end
|
data/lib/active_record/enum.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "active_support/core_ext/hash/slice"
|
3
4
|
require "active_support/core_ext/object/deep_dup"
|
4
5
|
|
5
6
|
module ActiveRecord
|
@@ -7,7 +8,7 @@ module ActiveRecord
|
|
7
8
|
# but can be queried by name. Example:
|
8
9
|
#
|
9
10
|
# class Conversation < ActiveRecord::Base
|
10
|
-
# enum status
|
11
|
+
# enum :status, [ :active, :archived ]
|
11
12
|
# end
|
12
13
|
#
|
13
14
|
# # conversation.update! status: 0
|
@@ -41,26 +42,33 @@ module ActiveRecord
|
|
41
42
|
# Conversation.where(status: [:active, :archived])
|
42
43
|
# Conversation.where.not(status: :active)
|
43
44
|
#
|
44
|
-
# Defining scopes can be disabled by setting +:
|
45
|
+
# Defining scopes can be disabled by setting +:scopes+ to +false+.
|
45
46
|
#
|
46
47
|
# class Conversation < ActiveRecord::Base
|
47
|
-
# enum status
|
48
|
+
# enum :status, [ :active, :archived ], scopes: false
|
48
49
|
# end
|
49
50
|
#
|
50
|
-
# You can set the default enum value by setting +:
|
51
|
+
# You can set the default enum value by setting +:default+, like:
|
51
52
|
#
|
52
53
|
# class Conversation < ActiveRecord::Base
|
53
|
-
# enum status
|
54
|
+
# enum :status, [ :active, :archived ], default: :active
|
54
55
|
# end
|
55
56
|
#
|
56
57
|
# conversation = Conversation.new
|
57
58
|
# conversation.status # => "active"
|
58
59
|
#
|
59
|
-
#
|
60
|
+
# It's possible to explicitly map the relation between attribute and
|
60
61
|
# database integer with a hash:
|
61
62
|
#
|
62
63
|
# class Conversation < ActiveRecord::Base
|
63
|
-
# enum status
|
64
|
+
# enum :status, active: 0, archived: 1
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# Finally it's also possible to use a string column to persist the enumerated value.
|
68
|
+
# Note that this will likely lead to slower database queries:
|
69
|
+
#
|
70
|
+
# class Conversation < ActiveRecord::Base
|
71
|
+
# enum :status, active: "active", archived: "archived"
|
64
72
|
# end
|
65
73
|
#
|
66
74
|
# Note that when an array is used, the implicit mapping from the values to database
|
@@ -75,7 +83,7 @@ module ActiveRecord
|
|
75
83
|
#
|
76
84
|
# In rare circumstances you might need to access the mapping directly.
|
77
85
|
# The mappings are exposed through a class method with the pluralized attribute
|
78
|
-
# name, which return the mapping in a
|
86
|
+
# name, which return the mapping in a ActiveSupport::HashWithIndifferentAccess :
|
79
87
|
#
|
80
88
|
# Conversation.statuses[:active] # => 0
|
81
89
|
# Conversation.statuses["archived"] # => 1
|
@@ -85,14 +93,14 @@ module ActiveRecord
|
|
85
93
|
#
|
86
94
|
# Conversation.where("status <> ?", Conversation.statuses[:archived])
|
87
95
|
#
|
88
|
-
# You can use the +:
|
96
|
+
# You can use the +:prefix+ or +:suffix+ options when you need to define
|
89
97
|
# multiple enums with same values. If the passed value is +true+, the methods
|
90
98
|
# are prefixed/suffixed with the name of the enum. It is also possible to
|
91
99
|
# supply a custom value:
|
92
100
|
#
|
93
101
|
# class Conversation < ActiveRecord::Base
|
94
|
-
# enum status
|
95
|
-
# enum comments_status
|
102
|
+
# enum :status, [ :active, :archived ], suffix: true
|
103
|
+
# enum :comments_status, [ :active, :inactive ], prefix: :comments
|
96
104
|
# end
|
97
105
|
#
|
98
106
|
# With the above example, the bang and predicate methods along with the
|
@@ -103,24 +111,70 @@ module ActiveRecord
|
|
103
111
|
#
|
104
112
|
# conversation.comments_inactive!
|
105
113
|
# conversation.comments_active? # => false
|
106
|
-
|
114
|
+
#
|
115
|
+
# If you want to disable the auto-generated methods on the model, you can do
|
116
|
+
# so by setting the +:instance_methods+ option to false:
|
117
|
+
#
|
118
|
+
# class Conversation < ActiveRecord::Base
|
119
|
+
# enum :status, [ :active, :archived ], instance_methods: false
|
120
|
+
# end
|
121
|
+
#
|
122
|
+
# If you want the enum value to be validated before saving, use the option +:validate+:
|
123
|
+
#
|
124
|
+
# class Conversation < ActiveRecord::Base
|
125
|
+
# enum :status, [ :active, :archived ], validate: true
|
126
|
+
# end
|
127
|
+
#
|
128
|
+
# conversation = Conversation.new
|
129
|
+
#
|
130
|
+
# conversation.status = :unknown
|
131
|
+
# conversation.valid? # => false
|
132
|
+
#
|
133
|
+
# conversation.status = nil
|
134
|
+
# conversation.valid? # => false
|
135
|
+
#
|
136
|
+
# conversation.status = :active
|
137
|
+
# conversation.valid? # => true
|
138
|
+
#
|
139
|
+
# It is also possible to pass additional validation options:
|
140
|
+
#
|
141
|
+
# class Conversation < ActiveRecord::Base
|
142
|
+
# enum :status, [ :active, :archived ], validate: { allow_nil: true }
|
143
|
+
# end
|
144
|
+
#
|
145
|
+
# conversation = Conversation.new
|
146
|
+
#
|
147
|
+
# conversation.status = :unknown
|
148
|
+
# conversation.valid? # => false
|
149
|
+
#
|
150
|
+
# conversation.status = nil
|
151
|
+
# conversation.valid? # => true
|
152
|
+
#
|
153
|
+
# conversation.status = :active
|
154
|
+
# conversation.valid? # => true
|
155
|
+
#
|
156
|
+
# Otherwise +ArgumentError+ will raise:
|
157
|
+
#
|
158
|
+
# class Conversation < ActiveRecord::Base
|
159
|
+
# enum :status, [ :active, :archived ]
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# conversation = Conversation.new
|
163
|
+
#
|
164
|
+
# conversation.status = :unknown # 'unknown' is not a valid status (ArgumentError)
|
107
165
|
module Enum
|
108
166
|
def self.extended(base) # :nodoc:
|
109
167
|
base.class_attribute(:defined_enums, instance_writer: false, default: {})
|
110
168
|
end
|
111
169
|
|
112
|
-
def inherited(base) # :nodoc:
|
113
|
-
base.defined_enums = defined_enums.deep_dup
|
114
|
-
super
|
115
|
-
end
|
116
|
-
|
117
170
|
class EnumType < Type::Value # :nodoc:
|
118
171
|
delegate :type, to: :subtype
|
119
172
|
|
120
|
-
def initialize(name, mapping, subtype)
|
173
|
+
def initialize(name, mapping, subtype, raise_on_invalid_values: true)
|
121
174
|
@name = name
|
122
175
|
@mapping = mapping
|
123
176
|
@subtype = subtype
|
177
|
+
@_raise_on_invalid_values = raise_on_invalid_values
|
124
178
|
end
|
125
179
|
|
126
180
|
def cast(value)
|
@@ -128,10 +182,8 @@ module ActiveRecord
|
|
128
182
|
value.to_s
|
129
183
|
elsif mapping.has_value?(value)
|
130
184
|
mapping.key(value)
|
131
|
-
elsif value.blank?
|
132
|
-
nil
|
133
185
|
else
|
134
|
-
|
186
|
+
value.presence
|
135
187
|
end
|
136
188
|
end
|
137
189
|
|
@@ -140,10 +192,16 @@ module ActiveRecord
|
|
140
192
|
end
|
141
193
|
|
142
194
|
def serialize(value)
|
143
|
-
mapping.fetch(value, value)
|
195
|
+
subtype.serialize(mapping.fetch(value, value))
|
196
|
+
end
|
197
|
+
|
198
|
+
def serializable?(value, &block)
|
199
|
+
subtype.serializable?(mapping.fetch(value, value), &block)
|
144
200
|
end
|
145
201
|
|
146
202
|
def assert_valid_value(value)
|
203
|
+
return unless @_raise_on_invalid_values
|
204
|
+
|
147
205
|
unless value.blank? || mapping.has_key?(value) || mapping.has_value?(value)
|
148
206
|
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
149
207
|
end
|
@@ -155,15 +213,25 @@ module ActiveRecord
|
|
155
213
|
attr_reader :name, :mapping
|
156
214
|
end
|
157
215
|
|
158
|
-
def enum(
|
159
|
-
|
160
|
-
|
161
|
-
|
216
|
+
def enum(name = nil, values = nil, **options)
|
217
|
+
if name
|
218
|
+
values, options = options, {} unless values
|
219
|
+
return _enum(name, values, **options)
|
220
|
+
end
|
221
|
+
|
222
|
+
definitions = options.slice!(:_prefix, :_suffix, :_scopes, :_default, :_instance_methods)
|
223
|
+
options.transform_keys! { |key| :"#{key[1..-1]}" }
|
224
|
+
|
225
|
+
definitions.each { |name, values| _enum(name, values, **options) }
|
226
|
+
end
|
162
227
|
|
163
|
-
|
164
|
-
|
228
|
+
private
|
229
|
+
def inherited(base)
|
230
|
+
base.defined_enums = defined_enums.deep_dup
|
231
|
+
super
|
232
|
+
end
|
165
233
|
|
166
|
-
|
234
|
+
def _enum(name, values, prefix: nil, suffix: nil, scopes: true, instance_methods: true, validate: false, **options)
|
167
235
|
assert_valid_enum_definition_values(values)
|
168
236
|
# statuses = { }
|
169
237
|
enum_values = ActiveSupport::HashWithIndifferentAccess.new
|
@@ -177,24 +245,25 @@ module ActiveRecord
|
|
177
245
|
detect_enum_conflict!(name, name)
|
178
246
|
detect_enum_conflict!(name, "#{name}=")
|
179
247
|
|
180
|
-
|
248
|
+
attribute(name, **options) do |subtype|
|
249
|
+
if subtype == ActiveModel::Type.default_value
|
250
|
+
raise "Undeclared attribute type for enum '#{name}' in #{self.name}. Enums must be" \
|
251
|
+
" backed by a database column or declared with an explicit type" \
|
252
|
+
" via `attribute`."
|
253
|
+
end
|
181
254
|
|
182
|
-
|
183
|
-
EnumType.new(
|
255
|
+
subtype = subtype.subtype if EnumType === subtype
|
256
|
+
EnumType.new(name, enum_values, subtype, raise_on_invalid_values: !validate)
|
184
257
|
end
|
185
258
|
|
186
259
|
value_method_names = []
|
187
260
|
_enum_methods_module.module_eval do
|
188
|
-
prefix = if
|
189
|
-
"#{name}_"
|
190
|
-
elsif enum_prefix
|
191
|
-
"#{enum_prefix}_"
|
261
|
+
prefix = if prefix
|
262
|
+
prefix == true ? "#{name}_" : "#{prefix}_"
|
192
263
|
end
|
193
264
|
|
194
|
-
suffix = if
|
195
|
-
"_#{name}"
|
196
|
-
elsif enum_suffix
|
197
|
-
"_#{enum_suffix}"
|
265
|
+
suffix = if suffix
|
266
|
+
suffix == true ? "_#{name}" : "_#{suffix}"
|
198
267
|
end
|
199
268
|
|
200
269
|
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
|
@@ -204,23 +273,27 @@ module ActiveRecord
|
|
204
273
|
|
205
274
|
value_method_name = "#{prefix}#{label}#{suffix}"
|
206
275
|
value_method_names << value_method_name
|
207
|
-
define_enum_methods(name, value_method_name, value,
|
276
|
+
define_enum_methods(name, value_method_name, value, scopes, instance_methods)
|
208
277
|
|
209
278
|
method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
|
210
279
|
value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
|
211
280
|
|
212
281
|
if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
|
213
282
|
value_method_names << value_method_alias
|
214
|
-
define_enum_methods(name, value_method_alias, value,
|
283
|
+
define_enum_methods(name, value_method_alias, value, scopes, instance_methods)
|
215
284
|
end
|
216
285
|
end
|
217
286
|
end
|
218
|
-
detect_negative_enum_conditions!(value_method_names) if
|
287
|
+
detect_negative_enum_conditions!(value_method_names) if scopes
|
288
|
+
|
289
|
+
if validate
|
290
|
+
validate = {} unless Hash === validate
|
291
|
+
validates_inclusion_of name, in: enum_values.keys, **validate
|
292
|
+
end
|
293
|
+
|
219
294
|
enum_values.freeze
|
220
295
|
end
|
221
|
-
end
|
222
296
|
|
223
|
-
private
|
224
297
|
class EnumMethods < Module # :nodoc:
|
225
298
|
def initialize(klass)
|
226
299
|
@klass = klass
|
@@ -229,21 +302,23 @@ module ActiveRecord
|
|
229
302
|
private
|
230
303
|
attr_reader :klass
|
231
304
|
|
232
|
-
def define_enum_methods(name, value_method_name, value,
|
233
|
-
|
234
|
-
|
235
|
-
|
305
|
+
def define_enum_methods(name, value_method_name, value, scopes, instance_methods)
|
306
|
+
if instance_methods
|
307
|
+
# def active?() status_for_database == 0 end
|
308
|
+
klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
|
309
|
+
define_method("#{value_method_name}?") { public_send(:"#{name}_for_database") == value }
|
236
310
|
|
237
|
-
|
238
|
-
|
239
|
-
|
311
|
+
# def active!() update!(status: 0) end
|
312
|
+
klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
|
313
|
+
define_method("#{value_method_name}!") { update!(name => value) }
|
314
|
+
end
|
240
315
|
|
241
|
-
|
242
|
-
|
243
|
-
if enum_scopes != false
|
316
|
+
if scopes
|
317
|
+
# scope :active, -> { where(status: 0) }
|
244
318
|
klass.send(:detect_enum_conflict!, name, value_method_name, true)
|
245
319
|
klass.scope value_method_name, -> { where(name => value) }
|
246
320
|
|
321
|
+
# scope :not_active, -> { where.not(status: 0) }
|
247
322
|
klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
|
248
323
|
klass.scope "not_#{value_method_name}", -> { where.not(name => value) }
|
249
324
|
end
|
@@ -260,15 +335,29 @@ module ActiveRecord
|
|
260
335
|
end
|
261
336
|
|
262
337
|
def assert_valid_enum_definition_values(values)
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
end
|
338
|
+
case values
|
339
|
+
when Hash
|
340
|
+
if values.empty?
|
341
|
+
raise ArgumentError, "Enum values #{values} must not be empty."
|
342
|
+
end
|
269
343
|
|
270
|
-
|
271
|
-
|
344
|
+
if values.keys.any?(&:blank?)
|
345
|
+
raise ArgumentError, "Enum values #{values} must not contain a blank name."
|
346
|
+
end
|
347
|
+
when Array
|
348
|
+
if values.empty?
|
349
|
+
raise ArgumentError, "Enum values #{values} must not be empty."
|
350
|
+
end
|
351
|
+
|
352
|
+
unless values.all?(Symbol) || values.all?(String)
|
353
|
+
raise ArgumentError, "Enum values #{values} must only contain symbols or strings."
|
354
|
+
end
|
355
|
+
|
356
|
+
if values.any?(&:blank?)
|
357
|
+
raise ArgumentError, "Enum values #{values} must not contain a blank name."
|
358
|
+
end
|
359
|
+
else
|
360
|
+
raise ArgumentError, "Enum values #{values} must be either a non-empty hash or an array."
|
272
361
|
end
|
273
362
|
end
|
274
363
|
|
@@ -283,6 +372,8 @@ module ActiveRecord
|
|
283
372
|
raise_conflict_error(enum_name, method_name, type: "class")
|
284
373
|
elsif klass_method && method_defined_within?(method_name, Relation)
|
285
374
|
raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
|
375
|
+
elsif klass_method && method_name.to_sym == :id
|
376
|
+
raise_conflict_error(enum_name, method_name)
|
286
377
|
elsif !klass_method && dangerous_attribute_method?(method_name)
|
287
378
|
raise_conflict_error(enum_name, method_name)
|
288
379
|
elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
|