activerecord 4.2.9 → 6.1.4.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +5 -5
- data/CHANGELOG.md +964 -1382
- data/MIT-LICENSE +4 -2
- data/README.rdoc +15 -14
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record/aggregations.rb +266 -251
- data/lib/active_record/association_relation.rb +40 -15
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +162 -69
- data/lib/active_record/associations/association_scope.rb +105 -130
- data/lib/active_record/associations/belongs_to_association.rb +83 -65
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +13 -12
- data/lib/active_record/associations/builder/association.rb +57 -43
- data/lib/active_record/associations/builder/belongs_to.rb +74 -57
- data/lib/active_record/associations/builder/collection_association.rb +15 -37
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +49 -66
- data/lib/active_record/associations/builder/has_many.rb +13 -5
- data/lib/active_record/associations/builder/has_one.rb +44 -6
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +148 -287
- data/lib/active_record/associations/collection_proxy.rb +252 -150
- data/lib/active_record/associations/foreign_association.rb +23 -1
- data/lib/active_record/associations/has_many_association.rb +56 -98
- data/lib/active_record/associations/has_many_through_association.rb +68 -89
- data/lib/active_record/associations/has_one_association.rb +73 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -81
- data/lib/active_record/associations/join_dependency/join_base.rb +10 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +14 -14
- data/lib/active_record/associations/join_dependency.rb +174 -169
- data/lib/active_record/associations/preloader/association.rb +108 -115
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +97 -94
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +39 -19
- data/lib/active_record/associations.rb +1845 -1598
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +18 -10
- data/lib/active_record/attribute_methods/dirty.rb +168 -148
- data/lib/active_record/attribute_methods/primary_key.rb +93 -83
- data/lib/active_record/attribute_methods/query.rb +8 -10
- data/lib/active_record/attribute_methods/read.rb +19 -79
- data/lib/active_record/attribute_methods/serialization.rb +49 -24
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +55 -36
- data/lib/active_record/attribute_methods/write.rb +24 -55
- data/lib/active_record/attribute_methods.rb +149 -154
- data/lib/active_record/attributes.rb +234 -78
- data/lib/active_record/autosave_association.rb +133 -60
- data/lib/active_record/base.rb +46 -46
- data/lib/active_record/callbacks.rb +234 -79
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +34 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -323
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +292 -124
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +177 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +8 -6
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +473 -255
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +869 -286
- data/lib/active_record/connection_adapters/abstract/transaction.rb +257 -91
- data/lib/active_record/connection_adapters/abstract_adapter.rb +483 -230
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +557 -640
- data/lib/active_record/connection_adapters/column.rb +67 -40
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +194 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +71 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +96 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +97 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +103 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +91 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +268 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +80 -192
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +44 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +75 -160
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -58
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +9 -8
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +4 -2
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +8 -6
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +14 -19
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -4
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -20
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{infinity.rb → oid.rb} +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +32 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +70 -34
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +4 -5
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +58 -54
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +18 -4
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid.rb +25 -25
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +145 -48
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +80 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +496 -298
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +11 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +588 -375
- data/lib/active_record/connection_adapters/schema_cache.rb +167 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +144 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +102 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +170 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +322 -373
- data/lib/active_record/connection_adapters/statement_pool.rb +33 -13
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +314 -41
- data/lib/active_record/core.rb +458 -241
- data/lib/active_record/counter_cache.rb +70 -49
- data/lib/active_record/database_configurations/connection_url_resolver.rb +98 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +272 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +87 -106
- data/lib/active_record/enum.rb +211 -92
- data/lib/active_record/errors.rb +224 -54
- data/lib/active_record/explain.rb +27 -11
- data/lib/active_record/explain_registry.rb +4 -2
- data/lib/active_record/explain_subscriber.rb +10 -5
- data/lib/active_record/fixture_set/file.rb +33 -14
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +275 -500
- data/lib/active_record/gem_version.rb +6 -4
- data/lib/active_record/inheritance.rb +175 -110
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +121 -29
- data/lib/active_record/internal_metadata.rb +62 -0
- data/lib/active_record/legacy_yaml_adapter.rb +27 -5
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +98 -92
- data/lib/active_record/locking/pessimistic.rb +22 -6
- data/lib/active_record/log_subscriber.rb +93 -31
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +185 -90
- data/lib/active_record/migration/compatibility.rb +295 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +673 -325
- data/lib/active_record/model_schema.rb +418 -113
- data/lib/active_record/nested_attributes.rb +263 -224
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +572 -136
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +170 -51
- data/lib/active_record/railties/console_sandbox.rb +3 -3
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +523 -199
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +454 -291
- data/lib/active_record/relation/batches/batch_enumerator.rb +85 -0
- data/lib/active_record/relation/batches.rb +217 -59
- data/lib/active_record/relation/calculations.rb +324 -249
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +316 -242
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +95 -103
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +42 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +57 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +7 -1
- data/lib/active_record/relation/predicate_builder.rb +136 -122
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -413
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +18 -20
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -343
- data/lib/active_record/result.rb +91 -47
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +134 -122
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +141 -92
- data/lib/active_record/schema_migration.rb +24 -23
- data/lib/active_record/scoping/default.rb +96 -83
- data/lib/active_record/scoping/named.rb +78 -36
- data/lib/active_record/scoping.rb +45 -27
- data/lib/active_record/secure_token.rb +48 -0
- data/lib/active_record/serialization.rb +8 -6
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +89 -36
- data/lib/active_record/store.rb +128 -43
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +81 -0
- data/lib/active_record/tasks/database_tasks.rb +364 -130
- data/lib/active_record/tasks/mysql_database_tasks.rb +67 -113
- data/lib/active_record/tasks/postgresql_database_tasks.rb +86 -49
- data/lib/active_record/tasks/sqlite_database_tasks.rb +44 -19
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +182 -163
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +126 -0
- data/lib/active_record/type/date.rb +4 -45
- data/lib/active_record/type/date_time.rb +4 -49
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +5 -4
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +27 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +21 -16
- data/lib/active_record/type/type_map.rb +16 -19
- data/lib/active_record/type/unsigned_integer.rb +9 -8
- data/lib/active_record/type.rb +84 -23
- data/lib/active_record/type_caster/connection.rb +33 -0
- data/lib/active_record/type_caster/map.rb +23 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +12 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +63 -56
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +42 -29
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +26 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +43 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +26 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +13 -4
- data/lib/rails/generators/active_record/migration.rb +35 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +55 -22
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
- data/lib/rails/generators/active_record.rb +7 -5
- metadata +172 -65
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -19
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute.rb +0 -163
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -106
- data/lib/active_record/attribute_set.rb +0 -81
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -275
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -491
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +0 -35
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -110
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -19
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
@@ -1,140 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module DynamicMatchers #:nodoc:
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
private
|
6
|
+
def respond_to_missing?(name, _)
|
7
|
+
if self == Base
|
8
|
+
super
|
9
|
+
else
|
10
|
+
match = Method.match(self, name)
|
11
|
+
match && match.valid? || super
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(name, *arguments, &block)
|
12
16
|
match = Method.match(self, name)
|
13
|
-
|
17
|
+
|
18
|
+
if match && match.valid?
|
19
|
+
match.define
|
20
|
+
send(name, *arguments, &block)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
14
24
|
end
|
15
|
-
end
|
16
25
|
|
17
|
-
|
26
|
+
class Method
|
27
|
+
@matchers = []
|
18
28
|
|
19
|
-
|
20
|
-
|
29
|
+
class << self
|
30
|
+
attr_reader :matchers
|
21
31
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
super
|
27
|
-
end
|
28
|
-
end
|
32
|
+
def match(model, name)
|
33
|
+
klass = matchers.find { |k| k.pattern.match?(name) }
|
34
|
+
klass.new(model, name) if klass
|
35
|
+
end
|
29
36
|
|
30
|
-
|
31
|
-
|
37
|
+
def pattern
|
38
|
+
@pattern ||= /\A#{prefix}_([_a-zA-Z]\w*)#{suffix}\Z/
|
39
|
+
end
|
32
40
|
|
33
|
-
|
34
|
-
|
41
|
+
def prefix
|
42
|
+
raise NotImplementedError
|
43
|
+
end
|
35
44
|
|
36
|
-
|
37
|
-
|
38
|
-
|
45
|
+
def suffix
|
46
|
+
""
|
47
|
+
end
|
39
48
|
end
|
40
49
|
|
41
|
-
|
42
|
-
@pattern ||= /\A#{prefix}_([_a-zA-Z]\w*)#{suffix}\Z/
|
43
|
-
end
|
50
|
+
attr_reader :model, :name, :attribute_names
|
44
51
|
|
45
|
-
def
|
46
|
-
|
52
|
+
def initialize(model, method_name)
|
53
|
+
@model = model
|
54
|
+
@name = method_name.to_s
|
55
|
+
@attribute_names = @name.match(self.class.pattern)[1].split("_and_")
|
56
|
+
@attribute_names.map! { |name| @model.attribute_aliases[name] || name }
|
47
57
|
end
|
48
58
|
|
49
|
-
def
|
50
|
-
|
59
|
+
def valid?
|
60
|
+
attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) }
|
51
61
|
end
|
52
|
-
end
|
53
62
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
62
|
-
|
63
|
-
def valid?
|
64
|
-
attribute_names.all? { |name| model.columns_hash[name] || model.reflect_on_aggregation(name.to_sym) }
|
65
|
-
end
|
63
|
+
def define
|
64
|
+
model.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
65
|
+
def self.#{name}(#{signature})
|
66
|
+
#{body}
|
67
|
+
end
|
68
|
+
CODE
|
69
|
+
end
|
66
70
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
#{body}
|
71
|
+
private
|
72
|
+
def body
|
73
|
+
"#{finder}(#{attributes_hash})"
|
71
74
|
end
|
72
|
-
CODE
|
73
|
-
end
|
74
|
-
|
75
|
-
def body
|
76
|
-
raise NotImplementedError
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
module Finder
|
81
|
-
# Extended in activerecord-deprecated_finders
|
82
|
-
def body
|
83
|
-
result
|
84
|
-
end
|
85
75
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
# The parameters in the signature may have reserved Ruby words, in order
|
92
|
-
# to prevent errors, we start each param name with `_`.
|
93
|
-
#
|
94
|
-
# Extended in activerecord-deprecated_finders
|
95
|
-
def signature
|
96
|
-
attribute_names.map { |name| "_#{name}" }.join(', ')
|
97
|
-
end
|
76
|
+
# The parameters in the signature may have reserved Ruby words, in order
|
77
|
+
# to prevent errors, we start each param name with `_`.
|
78
|
+
def signature
|
79
|
+
attribute_names.map { |name| "_#{name}" }.join(", ")
|
80
|
+
end
|
98
81
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
82
|
+
# Given that the parameters starts with `_`, the finder needs to use the
|
83
|
+
# same parameter name.
|
84
|
+
def attributes_hash
|
85
|
+
"{" + attribute_names.map { |name| ":#{name} => _#{name}" }.join(",") + "}"
|
86
|
+
end
|
104
87
|
|
105
|
-
|
106
|
-
|
88
|
+
def finder
|
89
|
+
raise NotImplementedError
|
90
|
+
end
|
107
91
|
end
|
108
|
-
end
|
109
92
|
|
110
|
-
|
111
|
-
|
112
|
-
include Finder
|
93
|
+
class FindBy < Method
|
94
|
+
Method.matchers << self
|
113
95
|
|
114
|
-
|
115
|
-
|
116
|
-
|
96
|
+
def self.prefix
|
97
|
+
"find_by"
|
98
|
+
end
|
117
99
|
|
118
|
-
|
119
|
-
|
100
|
+
def finder
|
101
|
+
"find_by"
|
102
|
+
end
|
120
103
|
end
|
121
|
-
end
|
122
104
|
|
123
|
-
|
124
|
-
|
125
|
-
include Finder
|
105
|
+
class FindByBang < Method
|
106
|
+
Method.matchers << self
|
126
107
|
|
127
|
-
|
128
|
-
|
129
|
-
|
108
|
+
def self.prefix
|
109
|
+
"find_by"
|
110
|
+
end
|
130
111
|
|
131
|
-
|
132
|
-
|
133
|
-
|
112
|
+
def self.suffix
|
113
|
+
"!"
|
114
|
+
end
|
134
115
|
|
135
|
-
|
136
|
-
|
116
|
+
def finder
|
117
|
+
"find_by!"
|
118
|
+
end
|
137
119
|
end
|
138
|
-
end
|
139
120
|
end
|
140
121
|
end
|
data/lib/active_record/enum.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/object/deep_dup"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
# Declare an enum attribute where the values map to integers in the database,
|
@@ -29,24 +31,39 @@ module ActiveRecord
|
|
29
31
|
# as well. With the above example:
|
30
32
|
#
|
31
33
|
# Conversation.active
|
34
|
+
# Conversation.not_active
|
32
35
|
# Conversation.archived
|
36
|
+
# Conversation.not_archived
|
37
|
+
#
|
38
|
+
# Of course, you can also query them directly if the scopes don't fit your
|
39
|
+
# needs:
|
40
|
+
#
|
41
|
+
# Conversation.where(status: [:active, :archived])
|
42
|
+
# Conversation.where.not(status: :active)
|
33
43
|
#
|
34
|
-
#
|
44
|
+
# Defining scopes can be disabled by setting +:_scopes+ to +false+.
|
35
45
|
#
|
36
|
-
#
|
37
|
-
#
|
46
|
+
# class Conversation < ActiveRecord::Base
|
47
|
+
# enum status: [ :active, :archived ], _scopes: false
|
38
48
|
# end
|
39
49
|
#
|
40
|
-
#
|
50
|
+
# You can set the default enum value by setting +:_default+, like:
|
51
|
+
#
|
52
|
+
# class Conversation < ActiveRecord::Base
|
53
|
+
# enum status: [ :active, :archived ], _default: "active"
|
54
|
+
# end
|
55
|
+
#
|
56
|
+
# conversation = Conversation.new
|
57
|
+
# conversation.status # => "active"
|
41
58
|
#
|
42
59
|
# Finally, it's also possible to explicitly map the relation between attribute and
|
43
|
-
# database integer with a
|
60
|
+
# database integer with a hash:
|
44
61
|
#
|
45
62
|
# class Conversation < ActiveRecord::Base
|
46
63
|
# enum status: { active: 0, archived: 1 }
|
47
64
|
# end
|
48
65
|
#
|
49
|
-
# Note that when an
|
66
|
+
# Note that when an array is used, the implicit mapping from the values to database
|
50
67
|
# integers is derived from the order the values appear in the array. In the example,
|
51
68
|
# <tt>:active</tt> is mapped to +0+ as it's the first element, and <tt>:archived</tt>
|
52
69
|
# is mapped to +1+. In general, the +i+-th element is mapped to <tt>i-1</tt> in the
|
@@ -54,23 +71,42 @@ module ActiveRecord
|
|
54
71
|
#
|
55
72
|
# Therefore, once a value is added to the enum array, its position in the array must
|
56
73
|
# be maintained, and new values should only be added to the end of the array. To
|
57
|
-
# remove unused values, the explicit
|
74
|
+
# remove unused values, the explicit hash syntax should be used.
|
58
75
|
#
|
59
76
|
# In rare circumstances you might need to access the mapping directly.
|
60
77
|
# The mappings are exposed through a class method with the pluralized attribute
|
61
|
-
# name
|
78
|
+
# name, which return the mapping in a +HashWithIndifferentAccess+:
|
62
79
|
#
|
63
|
-
# Conversation.statuses
|
80
|
+
# Conversation.statuses[:active] # => 0
|
81
|
+
# Conversation.statuses["archived"] # => 1
|
64
82
|
#
|
65
|
-
# Use that class method when you need to know the ordinal value of an enum
|
83
|
+
# Use that class method when you need to know the ordinal value of an enum.
|
84
|
+
# For example, you can use that when manually building SQL strings:
|
66
85
|
#
|
67
86
|
# Conversation.where("status <> ?", Conversation.statuses[:archived])
|
68
87
|
#
|
69
|
-
#
|
88
|
+
# You can use the +:_prefix+ or +:_suffix+ options when you need to define
|
89
|
+
# multiple enums with same values. If the passed value is +true+, the methods
|
90
|
+
# are prefixed/suffixed with the name of the enum. It is also possible to
|
91
|
+
# supply a custom value:
|
92
|
+
#
|
93
|
+
# class Conversation < ActiveRecord::Base
|
94
|
+
# enum status: [:active, :archived], _suffix: true
|
95
|
+
# enum comments_status: [:active, :inactive], _prefix: :comments
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# With the above example, the bang and predicate methods along with the
|
99
|
+
# associated scopes are now prefixed and/or suffixed accordingly:
|
100
|
+
#
|
101
|
+
# conversation.active_status!
|
102
|
+
# conversation.archived_status? # => false
|
103
|
+
#
|
104
|
+
# conversation.comments_inactive!
|
105
|
+
# conversation.comments_active? # => false
|
106
|
+
|
70
107
|
module Enum
|
71
108
|
def self.extended(base) # :nodoc:
|
72
|
-
base.class_attribute(:defined_enums, instance_writer: false)
|
73
|
-
base.defined_enums = {}
|
109
|
+
base.class_attribute(:defined_enums, instance_writer: false, default: {})
|
74
110
|
end
|
75
111
|
|
76
112
|
def inherited(base) # :nodoc:
|
@@ -78,119 +114,202 @@ module ActiveRecord
|
|
78
114
|
super
|
79
115
|
end
|
80
116
|
|
117
|
+
class EnumType < Type::Value # :nodoc:
|
118
|
+
delegate :type, to: :subtype
|
119
|
+
|
120
|
+
def initialize(name, mapping, subtype)
|
121
|
+
@name = name
|
122
|
+
@mapping = mapping
|
123
|
+
@subtype = subtype
|
124
|
+
end
|
125
|
+
|
126
|
+
def cast(value)
|
127
|
+
if mapping.has_key?(value)
|
128
|
+
value.to_s
|
129
|
+
elsif mapping.has_value?(value)
|
130
|
+
mapping.key(value)
|
131
|
+
elsif value.blank?
|
132
|
+
nil
|
133
|
+
else
|
134
|
+
assert_valid_value(value)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def deserialize(value)
|
139
|
+
mapping.key(subtype.deserialize(value))
|
140
|
+
end
|
141
|
+
|
142
|
+
def serialize(value)
|
143
|
+
mapping.fetch(value, value)
|
144
|
+
end
|
145
|
+
|
146
|
+
def assert_valid_value(value)
|
147
|
+
unless value.blank? || mapping.has_key?(value) || mapping.has_value?(value)
|
148
|
+
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
attr_reader :subtype
|
153
|
+
|
154
|
+
private
|
155
|
+
attr_reader :name, :mapping
|
156
|
+
end
|
157
|
+
|
81
158
|
def enum(definitions)
|
82
|
-
|
159
|
+
enum_prefix = definitions.delete(:_prefix)
|
160
|
+
enum_suffix = definitions.delete(:_suffix)
|
161
|
+
enum_scopes = definitions.delete(:_scopes)
|
162
|
+
|
163
|
+
default = {}
|
164
|
+
default[:default] = definitions.delete(:_default) if definitions.key?(:_default)
|
165
|
+
|
83
166
|
definitions.each do |name, values|
|
167
|
+
assert_valid_enum_definition_values(values)
|
84
168
|
# statuses = { }
|
85
169
|
enum_values = ActiveSupport::HashWithIndifferentAccess.new
|
86
|
-
name
|
170
|
+
name = name.to_s
|
87
171
|
|
88
|
-
# def self.statuses statuses end
|
89
|
-
detect_enum_conflict!(name, name.
|
90
|
-
|
172
|
+
# def self.statuses() statuses end
|
173
|
+
detect_enum_conflict!(name, name.pluralize, true)
|
174
|
+
singleton_class.define_method(name.pluralize) { enum_values }
|
175
|
+
defined_enums[name] = enum_values
|
91
176
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
# This is used internally to make building objects from the generated scopes work
|
101
|
-
# as expected, i.e. +Conversation.archived.build.archived?+ should be true.
|
102
|
-
self[name] = value
|
103
|
-
else
|
104
|
-
raise ArgumentError, "'#{value}' is not a valid #{name}"
|
105
|
-
end
|
106
|
-
}
|
177
|
+
detect_enum_conflict!(name, name)
|
178
|
+
detect_enum_conflict!(name, "#{name}=")
|
179
|
+
|
180
|
+
attr = attribute_alias?(name) ? attribute_alias(name) : name
|
181
|
+
|
182
|
+
decorate_attribute_type(attr, **default) do |subtype|
|
183
|
+
EnumType.new(attr, enum_values, subtype)
|
184
|
+
end
|
107
185
|
|
108
|
-
|
109
|
-
|
110
|
-
|
186
|
+
value_method_names = []
|
187
|
+
_enum_methods_module.module_eval do
|
188
|
+
prefix = if enum_prefix == true
|
189
|
+
"#{name}_"
|
190
|
+
elsif enum_prefix
|
191
|
+
"#{enum_prefix}_"
|
192
|
+
end
|
111
193
|
|
112
|
-
|
113
|
-
|
114
|
-
|
194
|
+
suffix = if enum_suffix == true
|
195
|
+
"_#{name}"
|
196
|
+
elsif enum_suffix
|
197
|
+
"_#{enum_suffix}"
|
198
|
+
end
|
115
199
|
|
116
200
|
pairs = values.respond_to?(:each_pair) ? values.each_pair : values.each_with_index
|
117
|
-
pairs.each do |
|
118
|
-
enum_values[
|
201
|
+
pairs.each do |label, value|
|
202
|
+
enum_values[label] = value
|
203
|
+
label = label.to_s
|
119
204
|
|
120
|
-
|
121
|
-
|
122
|
-
|
205
|
+
value_method_name = "#{prefix}#{label}#{suffix}"
|
206
|
+
value_method_names << value_method_name
|
207
|
+
define_enum_methods(name, value_method_name, value, enum_scopes)
|
123
208
|
|
124
|
-
|
125
|
-
|
126
|
-
define_method("#{value}!") { update! name => value }
|
209
|
+
method_friendly_label = label.gsub(/[\W&&[:ascii:]]+/, "_")
|
210
|
+
value_method_alias = "#{prefix}#{method_friendly_label}#{suffix}"
|
127
211
|
|
128
|
-
|
129
|
-
|
130
|
-
|
212
|
+
if value_method_alias != value_method_name && !value_method_names.include?(value_method_alias)
|
213
|
+
value_method_names << value_method_alias
|
214
|
+
define_enum_methods(name, value_method_alias, value, enum_scopes)
|
215
|
+
end
|
131
216
|
end
|
132
217
|
end
|
133
|
-
|
218
|
+
detect_negative_enum_conditions!(value_method_names) if enum_scopes != false
|
219
|
+
enum_values.freeze
|
134
220
|
end
|
135
221
|
end
|
136
222
|
|
137
223
|
private
|
224
|
+
class EnumMethods < Module # :nodoc:
|
225
|
+
def initialize(klass)
|
226
|
+
@klass = klass
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
attr_reader :klass
|
231
|
+
|
232
|
+
def define_enum_methods(name, value_method_name, value, enum_scopes)
|
233
|
+
# def active?() status_for_database == 0 end
|
234
|
+
klass.send(:detect_enum_conflict!, name, "#{value_method_name}?")
|
235
|
+
define_method("#{value_method_name}?") { public_send(:"#{name}_for_database") == value }
|
236
|
+
|
237
|
+
# def active!() update!(status: 0) end
|
238
|
+
klass.send(:detect_enum_conflict!, name, "#{value_method_name}!")
|
239
|
+
define_method("#{value_method_name}!") { update!(name => value) }
|
240
|
+
|
241
|
+
# scope :active, -> { where(status: 0) }
|
242
|
+
# scope :not_active, -> { where.not(status: 0) }
|
243
|
+
if enum_scopes != false
|
244
|
+
klass.send(:detect_enum_conflict!, name, value_method_name, true)
|
245
|
+
klass.scope value_method_name, -> { where(name => value) }
|
246
|
+
|
247
|
+
klass.send(:detect_enum_conflict!, name, "not_#{value_method_name}", true)
|
248
|
+
klass.scope "not_#{value_method_name}", -> { where.not(name => value) }
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
private_constant :EnumMethods
|
253
|
+
|
138
254
|
def _enum_methods_module
|
139
255
|
@_enum_methods_module ||= begin
|
140
|
-
mod =
|
141
|
-
private
|
142
|
-
def save_changed_attribute(attr_name, old)
|
143
|
-
if (mapping = self.class.defined_enums[attr_name.to_s])
|
144
|
-
value = _read_attribute(attr_name)
|
145
|
-
if attribute_changed?(attr_name)
|
146
|
-
if mapping[old] == value
|
147
|
-
clear_attribute_changes([attr_name])
|
148
|
-
end
|
149
|
-
else
|
150
|
-
if old != value
|
151
|
-
set_attribute_was(attr_name, mapping.key(old))
|
152
|
-
end
|
153
|
-
end
|
154
|
-
else
|
155
|
-
super
|
156
|
-
end
|
157
|
-
end
|
158
|
-
end
|
256
|
+
mod = EnumMethods.new(self)
|
159
257
|
include mod
|
160
258
|
mod
|
161
259
|
end
|
162
260
|
end
|
163
261
|
|
262
|
+
def assert_valid_enum_definition_values(values)
|
263
|
+
unless values.is_a?(Hash) || values.all? { |v| v.is_a?(Symbol) } || values.all? { |v| v.is_a?(String) }
|
264
|
+
error_message = <<~MSG
|
265
|
+
Enum values #{values} must be either a hash, an array of symbols, or an array of strings.
|
266
|
+
MSG
|
267
|
+
raise ArgumentError, error_message
|
268
|
+
end
|
269
|
+
|
270
|
+
if values.is_a?(Hash) && values.keys.any?(&:blank?) || values.is_a?(Array) && values.any?(&:blank?)
|
271
|
+
raise ArgumentError, "Enum label name must not be blank."
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
164
275
|
ENUM_CONFLICT_MESSAGE = \
|
165
276
|
"You tried to define an enum named \"%{enum}\" on the model \"%{klass}\", but " \
|
166
277
|
"this will generate a %{type} method \"%{method}\", which is already defined " \
|
167
278
|
"by %{source}."
|
279
|
+
private_constant :ENUM_CONFLICT_MESSAGE
|
168
280
|
|
169
281
|
def detect_enum_conflict!(enum_name, method_name, klass_method = false)
|
170
282
|
if klass_method && dangerous_class_method?(method_name)
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
type: 'class',
|
175
|
-
method: method_name,
|
176
|
-
source: 'Active Record'
|
177
|
-
}
|
283
|
+
raise_conflict_error(enum_name, method_name, type: "class")
|
284
|
+
elsif klass_method && method_defined_within?(method_name, Relation)
|
285
|
+
raise_conflict_error(enum_name, method_name, type: "class", source: Relation.name)
|
178
286
|
elsif !klass_method && dangerous_attribute_method?(method_name)
|
179
|
-
|
180
|
-
enum: enum_name,
|
181
|
-
klass: self.name,
|
182
|
-
type: 'instance',
|
183
|
-
method: method_name,
|
184
|
-
source: 'Active Record'
|
185
|
-
}
|
287
|
+
raise_conflict_error(enum_name, method_name)
|
186
288
|
elsif !klass_method && method_defined_within?(method_name, _enum_methods_module, Module)
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
289
|
+
raise_conflict_error(enum_name, method_name, source: "another enum")
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
def raise_conflict_error(enum_name, method_name, type: "instance", source: "Active Record")
|
294
|
+
raise ArgumentError, ENUM_CONFLICT_MESSAGE % {
|
295
|
+
enum: enum_name,
|
296
|
+
klass: name,
|
297
|
+
type: type,
|
298
|
+
method: method_name,
|
299
|
+
source: source
|
300
|
+
}
|
301
|
+
end
|
302
|
+
|
303
|
+
def detect_negative_enum_conditions!(method_names)
|
304
|
+
return unless logger
|
305
|
+
|
306
|
+
method_names.select { |m| m.start_with?("not_") }.each do |potential_not|
|
307
|
+
inverted_form = potential_not.sub("not_", "")
|
308
|
+
if method_names.include?(inverted_form)
|
309
|
+
logger.warn "Enum element '#{potential_not}' in #{self.name} uses the prefix 'not_'." \
|
310
|
+
" This has caused a conflict with auto generated negative scopes." \
|
311
|
+
" Avoid using enum elements starting with 'not' where the positive form is also an element."
|
312
|
+
end
|
194
313
|
end
|
195
314
|
end
|
196
315
|
end
|