activerecord 4.2.8 → 6.0.0
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 +612 -1583
- data/MIT-LICENSE +4 -2
- data/README.rdoc +13 -12
- data/examples/performance.rb +33 -32
- data/examples/simple.rb +5 -4
- data/lib/active_record.rb +41 -22
- data/lib/active_record/aggregations.rb +267 -251
- data/lib/active_record/association_relation.rb +11 -6
- data/lib/active_record/associations.rb +1737 -1597
- data/lib/active_record/associations/alias_tracker.rb +29 -35
- data/lib/active_record/associations/association.rb +125 -58
- data/lib/active_record/associations/association_scope.rb +103 -132
- data/lib/active_record/associations/belongs_to_association.rb +65 -60
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +8 -12
- data/lib/active_record/associations/builder/association.rb +27 -40
- data/lib/active_record/associations/builder/belongs_to.rb +69 -55
- data/lib/active_record/associations/builder/collection_association.rb +10 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +52 -66
- data/lib/active_record/associations/builder/has_many.rb +8 -4
- data/lib/active_record/associations/builder/has_one.rb +46 -5
- data/lib/active_record/associations/builder/singular_association.rb +16 -10
- data/lib/active_record/associations/collection_association.rb +134 -286
- data/lib/active_record/associations/collection_proxy.rb +241 -146
- data/lib/active_record/associations/foreign_association.rb +10 -1
- data/lib/active_record/associations/has_many_association.rb +34 -97
- data/lib/active_record/associations/has_many_through_association.rb +60 -87
- data/lib/active_record/associations/has_one_association.rb +61 -49
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency.rb +137 -167
- data/lib/active_record/associations/join_dependency/join_association.rb +38 -88
- 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/preloader.rb +90 -92
- data/lib/active_record/associations/preloader/association.rb +90 -123
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/singular_association.rb +18 -39
- data/lib/active_record/associations/through_association.rb +38 -18
- data/lib/active_record/attribute_assignment.rb +56 -183
- data/lib/active_record/attribute_decorators.rb +39 -15
- data/lib/active_record/attribute_methods.rb +120 -135
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -8
- data/lib/active_record/attribute_methods/dirty.rb +174 -144
- data/lib/active_record/attribute_methods/primary_key.rb +91 -83
- data/lib/active_record/attribute_methods/query.rb +6 -5
- data/lib/active_record/attribute_methods/read.rb +20 -76
- data/lib/active_record/attribute_methods/serialization.rb +40 -20
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +58 -36
- data/lib/active_record/attribute_methods/write.rb +32 -54
- data/lib/active_record/attributes.rb +214 -82
- data/lib/active_record/autosave_association.rb +91 -37
- data/lib/active_record/base.rb +57 -45
- data/lib/active_record/callbacks.rb +100 -74
- data/lib/active_record/coders/json.rb +3 -1
- data/lib/active_record/coders/yaml_column.rb +24 -12
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +796 -296
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +26 -8
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +234 -115
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +82 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +170 -53
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +5 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +74 -46
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +356 -227
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +664 -244
- data/lib/active_record/connection_adapters/abstract/transaction.rb +191 -83
- data/lib/active_record/connection_adapters/abstract_adapter.rb +460 -204
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +510 -627
- data/lib/active_record/connection_adapters/column.rb +56 -43
- data/lib/active_record/connection_adapters/connection_specification.rb +174 -152
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +58 -188
- data/lib/active_record/connection_adapters/postgresql/column.rb +21 -11
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +64 -114
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +23 -25
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +50 -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 +5 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +13 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +9 -22
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +5 -3
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +31 -19
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +3 -11
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +7 -9
- data/lib/active_record/connection_adapters/postgresql/oid/{integer.rb → oid.rb} +6 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +33 -11
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +52 -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 +10 -5
- 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/quoting.rb +144 -47
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +27 -14
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +178 -108
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +470 -290
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +12 -8
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +551 -356
- data/lib/active_record/connection_adapters/schema_cache.rb +72 -25
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -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 +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +290 -345
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +176 -41
- data/lib/active_record/core.rb +251 -231
- data/lib/active_record/counter_cache.rb +67 -49
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +87 -105
- data/lib/active_record/enum.rb +163 -86
- data/lib/active_record/errors.rb +188 -53
- data/lib/active_record/explain.rb +23 -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 +35 -9
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +228 -499
- data/lib/active_record/gem_version.rb +5 -3
- data/lib/active_record/inheritance.rb +158 -112
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +123 -29
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +21 -3
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +87 -96
- data/lib/active_record/locking/pessimistic.rb +18 -6
- data/lib/active_record/log_subscriber.rb +76 -33
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/migration.rb +626 -283
- data/lib/active_record/migration/command_recorder.rb +177 -90
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +8 -6
- data/lib/active_record/model_schema.rb +314 -112
- data/lib/active_record/nested_attributes.rb +264 -222
- data/lib/active_record/no_touching.rb +14 -1
- data/lib/active_record/null_relation.rb +24 -37
- data/lib/active_record/persistence.rb +557 -125
- data/lib/active_record/query_cache.rb +19 -23
- data/lib/active_record/querying.rb +43 -29
- data/lib/active_record/railtie.rb +147 -46
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +2 -0
- data/lib/active_record/railties/controller_runtime.rb +34 -33
- data/lib/active_record/railties/databases.rake +330 -197
- data/lib/active_record/readonly_attributes.rb +5 -4
- data/lib/active_record/reflection.rb +428 -279
- data/lib/active_record/relation.rb +518 -341
- data/lib/active_record/relation/batches.rb +207 -55
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/calculations.rb +267 -253
- data/lib/active_record/relation/delegation.rb +70 -80
- data/lib/active_record/relation/finder_methods.rb +277 -241
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +78 -87
- data/lib/active_record/relation/predicate_builder.rb +114 -119
- data/lib/active_record/relation/predicate_builder/array_handler.rb +27 -26
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -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 +53 -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/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +575 -394
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +11 -13
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/result.rb +79 -42
- data/lib/active_record/runtime_registry.rb +6 -4
- data/lib/active_record/sanitization.rb +144 -121
- data/lib/active_record/schema.rb +21 -24
- data/lib/active_record/schema_dumper.rb +112 -93
- data/lib/active_record/schema_migration.rb +24 -17
- data/lib/active_record/scoping.rb +45 -26
- data/lib/active_record/scoping/default.rb +101 -85
- data/lib/active_record/scoping/named.rb +86 -33
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +5 -5
- data/lib/active_record/statement_cache.rb +73 -36
- data/lib/active_record/store.rb +127 -42
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +308 -99
- data/lib/active_record/tasks/mysql_database_tasks.rb +55 -99
- data/lib/active_record/tasks/postgresql_database_tasks.rb +81 -41
- data/lib/active_record/tasks/sqlite_database_tasks.rb +38 -16
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +86 -40
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +216 -150
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type.rb +78 -23
- data/lib/active_record/type/adapter_specific_registry.rb +129 -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 -3
- 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 +24 -15
- data/lib/active_record/type/text.rb +2 -2
- data/lib/active_record/type/time.rb +11 -16
- data/lib/active_record/type/type_map.rb +15 -17
- data/lib/active_record/type/unsigned_integer.rb +9 -7
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +13 -4
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +14 -13
- data/lib/active_record/validations/uniqueness.rb +42 -55
- data/lib/active_record/version.rb +3 -1
- data/lib/arel.rb +51 -0
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -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.rb +68 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -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 +18 -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 +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -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 +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -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 +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -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/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/rails/generators/active_record.rb +7 -5
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration.rb +31 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +42 -37
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/{migration.rb → migration.rb.tt} +11 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +19 -22
- 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
- metadata +164 -60
- 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_set.rb +0 -81
- data/lib/active_record/attribute_set/builder.rb +0 -106
- 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/infinity.rb +0 -13
- 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 -58
- 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
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module SecureToken
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
module ClassMethods
|
8
|
+
# Example using #has_secure_token
|
9
|
+
#
|
10
|
+
# # Schema: User(token:string, auth_token:string)
|
11
|
+
# class User < ActiveRecord::Base
|
12
|
+
# has_secure_token
|
13
|
+
# has_secure_token :auth_token
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
# user = User.new
|
17
|
+
# user.save
|
18
|
+
# user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
|
19
|
+
# user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
20
|
+
# user.regenerate_token # => true
|
21
|
+
# user.regenerate_auth_token # => true
|
22
|
+
#
|
23
|
+
# <tt>SecureRandom::base58</tt> is used to generate the 24-character unique token, so collisions are highly unlikely.
|
24
|
+
#
|
25
|
+
# Note that it's still possible to generate a race condition in the database in the same way that
|
26
|
+
# {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
|
27
|
+
# You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
28
|
+
def has_secure_token(attribute = :token)
|
29
|
+
# Load securerandom only when has_secure_token is used.
|
30
|
+
require "active_support/core_ext/securerandom"
|
31
|
+
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
|
32
|
+
before_create { send("#{attribute}=", self.class.generate_unique_secure_token) unless send("#{attribute}?") }
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_unique_secure_token
|
36
|
+
SecureRandom.base58(24)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -1,5 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord #:nodoc:
|
2
|
-
# = Active Record Serialization
|
4
|
+
# = Active Record \Serialization
|
3
5
|
module Serialization
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
include ActiveModel::Serializers::JSON
|
@@ -9,14 +11,12 @@ module ActiveRecord #:nodoc:
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def serializable_hash(options = nil)
|
12
|
-
options = options.try(:
|
14
|
+
options = options.try(:dup) || {}
|
13
15
|
|
14
|
-
options[:except] = Array(options[:except]).map
|
16
|
+
options[:except] = Array(options[:except]).map(&:to_s)
|
15
17
|
options[:except] |= Array(self.class.inheritance_column)
|
16
18
|
|
17
19
|
super(options)
|
18
20
|
end
|
19
21
|
end
|
20
22
|
end
|
21
|
-
|
22
|
-
require 'active_record/serializers/xml_serializer'
|
@@ -1,5 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
+
module ActiveRecord
|
3
4
|
# Statement cache is used to cache a single statement in order to avoid creating the AST again.
|
4
5
|
# Initializing the cache is done by passing the statement in the create block:
|
5
6
|
#
|
@@ -7,12 +8,14 @@ module ActiveRecord
|
|
7
8
|
# Book.where(name: "my book").where("author_id > 3")
|
8
9
|
# end
|
9
10
|
#
|
10
|
-
# The cached statement is executed by using the
|
11
|
+
# The cached statement is executed by using the
|
12
|
+
# {connection.execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute] method:
|
11
13
|
#
|
12
|
-
# cache.execute([], Book
|
14
|
+
# cache.execute([], Book.connection)
|
13
15
|
#
|
14
|
-
# The relation returned by the block is cached, and for each
|
15
|
-
#
|
16
|
+
# The relation returned by the block is cached, and for each
|
17
|
+
# {execute}[rdoc-ref:ConnectionAdapters::DatabaseStatements#execute]
|
18
|
+
# call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
|
16
19
|
#
|
17
20
|
# If you want to cache the statement without the values you can use the +bind+ method of the
|
18
21
|
# block parameter.
|
@@ -23,7 +26,7 @@ module ActiveRecord
|
|
23
26
|
#
|
24
27
|
# And pass the bind values as the first argument of +execute+ call.
|
25
28
|
#
|
26
|
-
# cache.execute(["my book"], Book
|
29
|
+
# cache.execute(["my book"], Book.connection)
|
27
30
|
class StatementCache # :nodoc:
|
28
31
|
class Substitute; end # :nodoc:
|
29
32
|
|
@@ -38,28 +41,53 @@ module ActiveRecord
|
|
38
41
|
end
|
39
42
|
|
40
43
|
class PartialQuery < Query # :nodoc:
|
41
|
-
def initialize
|
44
|
+
def initialize(values)
|
42
45
|
@values = values
|
43
|
-
@indexes = values.each_with_index.find_all { |thing,i|
|
44
|
-
|
46
|
+
@indexes = values.each_with_index.find_all { |thing, i|
|
47
|
+
Substitute === thing
|
45
48
|
}.map(&:last)
|
46
49
|
end
|
47
50
|
|
48
51
|
def sql_for(binds, connection)
|
49
52
|
val = @values.dup
|
50
|
-
|
51
|
-
@indexes.each { |i| val[i] = connection.quote(
|
53
|
+
casted_binds = binds.map(&:value_for_database)
|
54
|
+
@indexes.each { |i| val[i] = connection.quote(casted_binds.shift) }
|
52
55
|
val.join
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
56
|
-
|
57
|
-
|
59
|
+
class PartialQueryCollector
|
60
|
+
def initialize
|
61
|
+
@parts = []
|
62
|
+
@binds = []
|
63
|
+
end
|
64
|
+
|
65
|
+
def <<(str)
|
66
|
+
@parts << str
|
67
|
+
self
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_bind(obj)
|
71
|
+
@binds << obj
|
72
|
+
@parts << Substitute.new
|
73
|
+
self
|
74
|
+
end
|
75
|
+
|
76
|
+
def value
|
77
|
+
[@parts, @binds]
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.query(sql)
|
82
|
+
Query.new(sql)
|
58
83
|
end
|
59
84
|
|
60
|
-
def self.partial_query(
|
61
|
-
|
62
|
-
|
85
|
+
def self.partial_query(values)
|
86
|
+
PartialQuery.new(values)
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.partial_query_collector
|
90
|
+
PartialQueryCollector.new
|
63
91
|
end
|
64
92
|
|
65
93
|
class Params # :nodoc:
|
@@ -67,45 +95,54 @@ module ActiveRecord
|
|
67
95
|
end
|
68
96
|
|
69
97
|
class BindMap # :nodoc:
|
70
|
-
def initialize(
|
71
|
-
@indexes
|
72
|
-
@
|
98
|
+
def initialize(bound_attributes)
|
99
|
+
@indexes = []
|
100
|
+
@bound_attributes = bound_attributes
|
73
101
|
|
74
|
-
|
75
|
-
if Substitute === value
|
102
|
+
bound_attributes.each_with_index do |attr, i|
|
103
|
+
if Substitute === attr.value
|
76
104
|
@indexes << i
|
77
105
|
end
|
78
106
|
end
|
79
107
|
end
|
80
108
|
|
81
109
|
def bind(values)
|
82
|
-
|
83
|
-
@indexes.each_with_index { |offset,i|
|
84
|
-
|
110
|
+
bas = @bound_attributes.dup
|
111
|
+
@indexes.each_with_index { |offset, i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
112
|
+
bas
|
85
113
|
end
|
86
114
|
end
|
87
115
|
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
bind_map
|
93
|
-
query_builder = connection.cacheable_query relation.arel
|
94
|
-
new query_builder, bind_map
|
116
|
+
def self.create(connection, callable = nil, &block)
|
117
|
+
relation = (callable || block).call Params.new
|
118
|
+
query_builder, binds = connection.cacheable_query(self, relation.arel)
|
119
|
+
bind_map = BindMap.new(binds)
|
120
|
+
new(query_builder, bind_map, relation.klass)
|
95
121
|
end
|
96
122
|
|
97
|
-
def initialize(query_builder, bind_map)
|
123
|
+
def initialize(query_builder, bind_map, klass)
|
98
124
|
@query_builder = query_builder
|
99
|
-
@bind_map
|
125
|
+
@bind_map = bind_map
|
126
|
+
@klass = klass
|
100
127
|
end
|
101
128
|
|
102
|
-
def execute(params,
|
129
|
+
def execute(params, connection, &block)
|
103
130
|
bind_values = bind_map.bind params
|
104
131
|
|
105
132
|
sql = query_builder.sql_for bind_values, connection
|
106
133
|
|
107
|
-
klass.find_by_sql
|
134
|
+
klass.find_by_sql(sql, bind_values, preparable: true, &block)
|
135
|
+
rescue ::RangeError
|
136
|
+
nil
|
108
137
|
end
|
109
|
-
|
138
|
+
|
139
|
+
def self.unsupported_value?(value)
|
140
|
+
case value
|
141
|
+
when NilClass, Array, Range, Hash, Relation, Base then true
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
private
|
146
|
+
attr_reader :query_builder, :bind_map, :klass
|
110
147
|
end
|
111
148
|
end
|
data/lib/active_record/store.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/core_ext/hash/indifferent_access"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
# Store gives you a thin wrapper around serialize for the purpose of storing hashes in a single column.
|
@@ -9,39 +11,66 @@ module ActiveRecord
|
|
9
11
|
# of the model. This is very helpful for easily exposing store keys to a form or elsewhere that's
|
10
12
|
# already built around just accessing attributes on the model.
|
11
13
|
#
|
14
|
+
# Every accessor comes with dirty tracking methods (+key_changed?+, +key_was+ and +key_change+) and
|
15
|
+
# methods to access the changes made during the last save (+saved_change_to_key?+, +saved_change_to_key+ and
|
16
|
+
# +key_before_last_save+).
|
17
|
+
#
|
18
|
+
# NOTE: There is no +key_will_change!+ method for accessors, use +store_will_change!+ instead.
|
19
|
+
#
|
12
20
|
# Make sure that you declare the database column used for the serialized store as a text, so there's
|
13
21
|
# plenty of room.
|
14
22
|
#
|
15
23
|
# You can set custom coder to encode/decode your serialized attributes to/from different formats.
|
16
24
|
# JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
|
17
25
|
#
|
18
|
-
# NOTE
|
19
|
-
#
|
26
|
+
# NOTE: If you are using structured database data types (eg. PostgreSQL +hstore+/+json+, or MySQL 5.7+
|
27
|
+
# +json+) there is no need for the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
|
28
|
+
# Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
|
20
29
|
# the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
|
21
30
|
# using a symbol.
|
22
31
|
#
|
32
|
+
# NOTE: The default validations with the exception of +uniqueness+ will work.
|
33
|
+
# For example, if you want to check for +uniqueness+ with +hstore+ you will
|
34
|
+
# need to use a custom validation to handle it.
|
35
|
+
#
|
23
36
|
# Examples:
|
24
37
|
#
|
25
38
|
# class User < ActiveRecord::Base
|
26
39
|
# store :settings, accessors: [ :color, :homepage ], coder: JSON
|
40
|
+
# store :parent, accessors: [ :name ], coder: JSON, prefix: true
|
41
|
+
# store :spouse, accessors: [ :name ], coder: JSON, prefix: :partner
|
42
|
+
# store :settings, accessors: [ :two_factor_auth ], suffix: true
|
43
|
+
# store :settings, accessors: [ :login_retry ], suffix: :config
|
27
44
|
# end
|
28
45
|
#
|
29
|
-
# u = User.new(color: 'black', homepage: '37signals.com')
|
46
|
+
# u = User.new(color: 'black', homepage: '37signals.com', parent_name: 'Mary', partner_name: 'Lily')
|
30
47
|
# u.color # Accessor stored attribute
|
48
|
+
# u.parent_name # Accessor stored attribute with prefix
|
49
|
+
# u.partner_name # Accessor stored attribute with custom prefix
|
50
|
+
# u.two_factor_auth_settings # Accessor stored attribute with suffix
|
51
|
+
# u.login_retry_config # Accessor stored attribute with custom suffix
|
31
52
|
# u.settings[:country] = 'Denmark' # Any attribute, even if not specified with an accessor
|
32
53
|
#
|
33
54
|
# # There is no difference between strings and symbols for accessing custom attributes
|
34
55
|
# u.settings[:country] # => 'Denmark'
|
35
56
|
# u.settings['country'] # => 'Denmark'
|
36
57
|
#
|
58
|
+
# # Dirty tracking
|
59
|
+
# u.color = 'green'
|
60
|
+
# u.color_changed? # => true
|
61
|
+
# u.color_was # => 'black'
|
62
|
+
# u.color_change # => ['black', 'red']
|
63
|
+
#
|
37
64
|
# # Add additional accessors to an existing store through store_accessor
|
38
65
|
# class SuperUser < User
|
39
66
|
# store_accessor :settings, :privileges, :servants
|
67
|
+
# store_accessor :parent, :birthday, prefix: true
|
68
|
+
# store_accessor :settings, :secret_question, suffix: :config
|
40
69
|
# end
|
41
70
|
#
|
42
|
-
# The stored attribute names can be retrieved using
|
71
|
+
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
|
43
72
|
#
|
44
|
-
# User.stored_attributes[:settings] # [:color, :homepage]
|
73
|
+
# User.stored_attributes[:settings] # [:color, :homepage, :two_factor_auth, :login_retry]
|
45
74
|
#
|
46
75
|
# == Overwriting default accessors
|
47
76
|
#
|
@@ -73,22 +102,79 @@ module ActiveRecord
|
|
73
102
|
|
74
103
|
module ClassMethods
|
75
104
|
def store(store_attribute, options = {})
|
76
|
-
serialize store_attribute, IndifferentCoder.new(options[:coder])
|
77
|
-
store_accessor(store_attribute, options[:accessors]) if options.has_key? :accessors
|
105
|
+
serialize store_attribute, IndifferentCoder.new(store_attribute, options[:coder])
|
106
|
+
store_accessor(store_attribute, options[:accessors], options.slice(:prefix, :suffix)) if options.has_key? :accessors
|
78
107
|
end
|
79
108
|
|
80
|
-
def store_accessor(store_attribute, *keys)
|
109
|
+
def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
|
81
110
|
keys = keys.flatten
|
82
111
|
|
112
|
+
accessor_prefix =
|
113
|
+
case prefix
|
114
|
+
when String, Symbol
|
115
|
+
"#{prefix}_"
|
116
|
+
when TrueClass
|
117
|
+
"#{store_attribute}_"
|
118
|
+
else
|
119
|
+
""
|
120
|
+
end
|
121
|
+
accessor_suffix =
|
122
|
+
case suffix
|
123
|
+
when String, Symbol
|
124
|
+
"_#{suffix}"
|
125
|
+
when TrueClass
|
126
|
+
"_#{store_attribute}"
|
127
|
+
else
|
128
|
+
""
|
129
|
+
end
|
130
|
+
|
83
131
|
_store_accessors_module.module_eval do
|
84
132
|
keys.each do |key|
|
85
|
-
|
133
|
+
accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"
|
134
|
+
|
135
|
+
define_method("#{accessor_key}=") do |value|
|
86
136
|
write_store_attribute(store_attribute, key, value)
|
87
137
|
end
|
88
138
|
|
89
|
-
define_method(
|
139
|
+
define_method(accessor_key) do
|
90
140
|
read_store_attribute(store_attribute, key)
|
91
141
|
end
|
142
|
+
|
143
|
+
define_method("#{accessor_key}_changed?") do
|
144
|
+
return false unless attribute_changed?(store_attribute)
|
145
|
+
prev_store, new_store = changes[store_attribute]
|
146
|
+
prev_store&.dig(key) != new_store&.dig(key)
|
147
|
+
end
|
148
|
+
|
149
|
+
define_method("#{accessor_key}_change") do
|
150
|
+
return unless attribute_changed?(store_attribute)
|
151
|
+
prev_store, new_store = changes[store_attribute]
|
152
|
+
[prev_store&.dig(key), new_store&.dig(key)]
|
153
|
+
end
|
154
|
+
|
155
|
+
define_method("#{accessor_key}_was") do
|
156
|
+
return unless attribute_changed?(store_attribute)
|
157
|
+
prev_store, _new_store = changes[store_attribute]
|
158
|
+
prev_store&.dig(key)
|
159
|
+
end
|
160
|
+
|
161
|
+
define_method("saved_change_to_#{accessor_key}?") do
|
162
|
+
return false unless saved_change_to_attribute?(store_attribute)
|
163
|
+
prev_store, new_store = saved_change_to_attribute(store_attribute)
|
164
|
+
prev_store&.dig(key) != new_store&.dig(key)
|
165
|
+
end
|
166
|
+
|
167
|
+
define_method("saved_change_to_#{accessor_key}") do
|
168
|
+
return unless saved_change_to_attribute?(store_attribute)
|
169
|
+
prev_store, new_store = saved_change_to_attribute(store_attribute)
|
170
|
+
[prev_store&.dig(key), new_store&.dig(key)]
|
171
|
+
end
|
172
|
+
|
173
|
+
define_method("#{accessor_key}_before_last_save") do
|
174
|
+
return unless saved_change_to_attribute?(store_attribute)
|
175
|
+
prev_store, _new_store = saved_change_to_attribute(store_attribute)
|
176
|
+
prev_store&.dig(key)
|
177
|
+
end
|
92
178
|
end
|
93
179
|
end
|
94
180
|
|
@@ -109,27 +195,26 @@ module ActiveRecord
|
|
109
195
|
|
110
196
|
def stored_attributes
|
111
197
|
parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
|
112
|
-
if
|
113
|
-
parent.merge!(
|
198
|
+
if local_stored_attributes
|
199
|
+
parent.merge!(local_stored_attributes) { |k, a, b| a | b }
|
114
200
|
end
|
115
201
|
parent
|
116
202
|
end
|
117
203
|
end
|
118
204
|
|
119
|
-
|
120
|
-
def read_store_attribute(store_attribute, key)
|
205
|
+
private
|
206
|
+
def read_store_attribute(store_attribute, key) # :doc:
|
121
207
|
accessor = store_accessor_for(store_attribute)
|
122
208
|
accessor.read(self, store_attribute, key)
|
123
209
|
end
|
124
210
|
|
125
|
-
def write_store_attribute(store_attribute, key, value)
|
211
|
+
def write_store_attribute(store_attribute, key, value) # :doc:
|
126
212
|
accessor = store_accessor_for(store_attribute)
|
127
213
|
accessor.write(self, store_attribute, key, value)
|
128
214
|
end
|
129
215
|
|
130
|
-
private
|
131
216
|
def store_accessor_for(store_attribute)
|
132
|
-
type_for_attribute(store_attribute
|
217
|
+
type_for_attribute(store_attribute).accessor
|
133
218
|
end
|
134
219
|
|
135
220
|
class HashAccessor # :nodoc:
|
@@ -172,34 +257,34 @@ module ActiveRecord
|
|
172
257
|
end
|
173
258
|
end
|
174
259
|
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
260
|
+
class IndifferentCoder # :nodoc:
|
261
|
+
def initialize(attr_name, coder_or_class_name)
|
262
|
+
@coder =
|
263
|
+
if coder_or_class_name.respond_to?(:load) && coder_or_class_name.respond_to?(:dump)
|
264
|
+
coder_or_class_name
|
265
|
+
else
|
266
|
+
ActiveRecord::Coders::YAMLColumn.new(attr_name, coder_or_class_name || Object)
|
267
|
+
end
|
268
|
+
end
|
184
269
|
|
185
|
-
|
186
|
-
|
187
|
-
|
270
|
+
def dump(obj)
|
271
|
+
@coder.dump self.class.as_indifferent_hash(obj)
|
272
|
+
end
|
188
273
|
|
189
|
-
|
190
|
-
|
191
|
-
|
274
|
+
def load(yaml)
|
275
|
+
self.class.as_indifferent_hash(@coder.load(yaml || ""))
|
276
|
+
end
|
192
277
|
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
278
|
+
def self.as_indifferent_hash(obj)
|
279
|
+
case obj
|
280
|
+
when ActiveSupport::HashWithIndifferentAccess
|
281
|
+
obj
|
282
|
+
when Hash
|
283
|
+
obj.with_indifferent_access
|
284
|
+
else
|
285
|
+
ActiveSupport::HashWithIndifferentAccess.new
|
286
|
+
end
|
201
287
|
end
|
202
288
|
end
|
203
|
-
end
|
204
289
|
end
|
205
290
|
end
|