activerecord 3.2.6 → 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 +7 -0
- data/CHANGELOG.md +611 -6417
- data/MIT-LICENSE +4 -2
- data/README.rdoc +44 -47
- data/examples/performance.rb +79 -71
- data/examples/simple.rb +6 -5
- data/lib/active_record/aggregations.rb +268 -238
- data/lib/active_record/association_relation.rb +40 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -42
- data/lib/active_record/associations/association.rb +173 -81
- data/lib/active_record/associations/association_scope.rb +124 -92
- data/lib/active_record/associations/belongs_to_association.rb +83 -38
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
- data/lib/active_record/associations/builder/association.rb +113 -32
- data/lib/active_record/associations/builder/belongs_to.rb +105 -60
- data/lib/active_record/associations/builder/collection_association.rb +53 -56
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
- data/lib/active_record/associations/builder/has_many.rb +11 -63
- data/lib/active_record/associations/builder/has_one.rb +47 -45
- data/lib/active_record/associations/builder/singular_association.rb +30 -18
- data/lib/active_record/associations/collection_association.rb +217 -295
- data/lib/active_record/associations/collection_proxy.rb +1074 -77
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +78 -50
- data/lib/active_record/associations/has_many_through_association.rb +99 -61
- data/lib/active_record/associations/has_one_association.rb +75 -30
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
- data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
- data/lib/active_record/associations/join_dependency.rb +208 -164
- data/lib/active_record/associations/preloader/association.rb +93 -87
- data/lib/active_record/associations/preloader/through_association.rb +87 -38
- data/lib/active_record/associations/preloader.rb +134 -110
- data/lib/active_record/associations/singular_association.rb +19 -24
- data/lib/active_record/associations/through_association.rb +61 -27
- data/lib/active_record/associations.rb +1766 -1505
- data/lib/active_record/attribute_assignment.rb +57 -193
- data/lib/active_record/attribute_decorators.rb +90 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
- data/lib/active_record/attribute_methods/dirty.rb +187 -67
- data/lib/active_record/attribute_methods/primary_key.rb +100 -78
- data/lib/active_record/attribute_methods/query.rb +10 -8
- data/lib/active_record/attribute_methods/read.rb +29 -118
- data/lib/active_record/attribute_methods/serialization.rb +60 -72
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
- data/lib/active_record/attribute_methods/write.rb +36 -44
- data/lib/active_record/attribute_methods.rb +306 -161
- data/lib/active_record/attributes.rb +279 -0
- data/lib/active_record/autosave_association.rb +324 -238
- data/lib/active_record/base.rb +114 -507
- data/lib/active_record/callbacks.rb +147 -83
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +32 -23
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
- data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
- data/lib/active_record/connection_adapters/column.rb +58 -233
- data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
- 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 +75 -207
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
- data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
- 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 +528 -26
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +267 -0
- data/lib/active_record/core.rb +599 -0
- data/lib/active_record/counter_cache.rb +177 -103
- 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/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +107 -64
- data/lib/active_record/enum.rb +274 -0
- data/lib/active_record/errors.rb +254 -61
- data/lib/active_record/explain.rb +35 -70
- data/lib/active_record/explain_registry.rb +32 -0
- data/lib/active_record/explain_subscriber.rb +18 -8
- data/lib/active_record/fixture_set/file.rb +82 -0
- 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 +291 -475
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +219 -100
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +175 -17
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +9 -1
- data/lib/active_record/locking/optimistic.rb +106 -92
- data/lib/active_record/locking/pessimistic.rb +23 -11
- data/lib/active_record/log_subscriber.rb +80 -30
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +235 -56
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +17 -0
- data/lib/active_record/migration.rb +917 -301
- data/lib/active_record/model_schema.rb +351 -175
- data/lib/active_record/nested_attributes.rb +366 -235
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/null_relation.rb +68 -0
- data/lib/active_record/persistence.rb +761 -166
- data/lib/active_record/query_cache.rb +22 -44
- data/lib/active_record/querying.rb +55 -31
- data/lib/active_record/railtie.rb +185 -47
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -4
- data/lib/active_record/railties/controller_runtime.rb +35 -33
- data/lib/active_record/railties/databases.rake +366 -463
- data/lib/active_record/readonly_attributes.rb +4 -6
- data/lib/active_record/reflection.rb +736 -228
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +252 -52
- data/lib/active_record/relation/calculations.rb +340 -270
- data/lib/active_record/relation/delegation.rb +117 -36
- data/lib/active_record/relation/finder_methods.rb +439 -286
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +184 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
- 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 +19 -0
- data/lib/active_record/relation/predicate_builder.rb +131 -39
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +1163 -221
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +49 -120
- 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/relation.rb +671 -349
- data/lib/active_record/result.rb +149 -15
- data/lib/active_record/runtime_registry.rb +24 -0
- data/lib/active_record/sanitization.rb +153 -133
- data/lib/active_record/schema.rb +22 -19
- data/lib/active_record/schema_dumper.rb +178 -112
- data/lib/active_record/schema_migration.rb +60 -0
- data/lib/active_record/scoping/default.rb +107 -98
- data/lib/active_record/scoping/named.rb +130 -115
- data/lib/active_record/scoping.rb +77 -123
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +10 -6
- data/lib/active_record/statement_cache.rb +148 -0
- data/lib/active_record/store.rb +256 -16
- 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 +506 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +93 -39
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +260 -129
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
- 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 +71 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +21 -0
- data/lib/active_record/type/type_map.rb +62 -0
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +78 -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/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +35 -18
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +68 -0
- data/lib/active_record/validations/uniqueness.rb +123 -77
- data/lib/active_record/validations.rb +54 -43
- data/lib/active_record/version.rb +7 -7
- data/lib/active_record.rb +97 -49
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -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/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/nodes.rb +68 -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/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/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- 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/migration_generator.rb +59 -9
- 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.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +41 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +24 -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} +1 -1
- data/lib/rails/generators/active_record.rb +10 -16
- metadata +285 -149
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- 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_and_belongs_to_many.rb +0 -60
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
- 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_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,221 +1,85 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_model/forbidden_attributes_protection"
|
2
4
|
|
3
5
|
module ActiveRecord
|
4
6
|
module AttributeAssignment
|
5
|
-
|
6
|
-
include ActiveModel::MassAssignmentSecurity
|
7
|
-
|
8
|
-
module ClassMethods
|
9
|
-
private
|
10
|
-
|
11
|
-
# The primary key and inheritance column can never be set by mass-assignment for security reasons.
|
12
|
-
def attributes_protected_by_default
|
13
|
-
default = [ primary_key, inheritance_column ]
|
14
|
-
default << 'id' unless primary_key.eql? 'id'
|
15
|
-
default
|
16
|
-
end
|
17
|
-
end
|
7
|
+
include ActiveModel::AttributeAssignment
|
18
8
|
|
19
|
-
|
20
|
-
# matching the attribute names (which again matches the column names).
|
21
|
-
#
|
22
|
-
# If any attributes are protected by either +attr_protected+ or
|
23
|
-
# +attr_accessible+ then only settable attributes will be assigned.
|
24
|
-
#
|
25
|
-
# class User < ActiveRecord::Base
|
26
|
-
# attr_protected :is_admin
|
27
|
-
# end
|
28
|
-
#
|
29
|
-
# user = User.new
|
30
|
-
# user.attributes = { :username => 'Phusion', :is_admin => true }
|
31
|
-
# user.username # => "Phusion"
|
32
|
-
# user.is_admin? # => false
|
33
|
-
def attributes=(new_attributes)
|
34
|
-
return unless new_attributes.is_a?(Hash)
|
35
|
-
|
36
|
-
assign_attributes(new_attributes)
|
37
|
-
end
|
38
|
-
|
39
|
-
# Allows you to set all the attributes for a particular mass-assignment
|
40
|
-
# security role by passing in a hash of attributes with keys matching
|
41
|
-
# the attribute names (which again matches the column names) and the role
|
42
|
-
# name using the :as option.
|
43
|
-
#
|
44
|
-
# To bypass mass-assignment security you can use the :without_protection => true
|
45
|
-
# option.
|
46
|
-
#
|
47
|
-
# class User < ActiveRecord::Base
|
48
|
-
# attr_accessible :name
|
49
|
-
# attr_accessible :name, :is_admin, :as => :admin
|
50
|
-
# end
|
51
|
-
#
|
52
|
-
# user = User.new
|
53
|
-
# user.assign_attributes({ :name => 'Josh', :is_admin => true })
|
54
|
-
# user.name # => "Josh"
|
55
|
-
# user.is_admin? # => false
|
56
|
-
#
|
57
|
-
# user = User.new
|
58
|
-
# user.assign_attributes({ :name => 'Josh', :is_admin => true }, :as => :admin)
|
59
|
-
# user.name # => "Josh"
|
60
|
-
# user.is_admin? # => true
|
61
|
-
#
|
62
|
-
# user = User.new
|
63
|
-
# user.assign_attributes({ :name => 'Josh', :is_admin => true }, :without_protection => true)
|
64
|
-
# user.name # => "Josh"
|
65
|
-
# user.is_admin? # => true
|
66
|
-
def assign_attributes(new_attributes, options = {})
|
67
|
-
return unless new_attributes
|
68
|
-
|
69
|
-
attributes = new_attributes.stringify_keys
|
70
|
-
multi_parameter_attributes = []
|
71
|
-
nested_parameter_attributes = []
|
72
|
-
@mass_assignment_options = options
|
9
|
+
private
|
73
10
|
|
74
|
-
|
75
|
-
|
76
|
-
|
11
|
+
def _assign_attributes(attributes)
|
12
|
+
multi_parameter_attributes = {}
|
13
|
+
nested_parameter_attributes = {}
|
77
14
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
nested_parameter_attributes << [ k, v ]
|
84
|
-
else
|
85
|
-
send("#{k}=", v)
|
15
|
+
attributes.each do |k, v|
|
16
|
+
if k.include?("(")
|
17
|
+
multi_parameter_attributes[k] = attributes.delete(k)
|
18
|
+
elsif v.is_a?(Hash)
|
19
|
+
nested_parameter_attributes[k] = attributes.delete(k)
|
86
20
|
end
|
87
|
-
else
|
88
|
-
raise(UnknownAttributeError, "unknown attribute: #{k}")
|
89
21
|
end
|
90
|
-
|
22
|
+
super(attributes)
|
91
23
|
|
92
|
-
|
93
|
-
|
94
|
-
send("#{k}=", v)
|
24
|
+
assign_nested_parameter_attributes(nested_parameter_attributes) unless nested_parameter_attributes.empty?
|
25
|
+
assign_multiparameter_attributes(multi_parameter_attributes) unless multi_parameter_attributes.empty?
|
95
26
|
end
|
96
27
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
protected
|
102
|
-
|
103
|
-
def mass_assignment_options
|
104
|
-
@mass_assignment_options ||= {}
|
105
|
-
end
|
106
|
-
|
107
|
-
def mass_assignment_role
|
108
|
-
mass_assignment_options[:as] || :default
|
109
|
-
end
|
110
|
-
|
111
|
-
private
|
112
|
-
|
113
|
-
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
114
|
-
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
115
|
-
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
116
|
-
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
117
|
-
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Fixnum,
|
118
|
-
# f for Float, s for String, and a for Array. If all the values for a given attribute are empty, the
|
119
|
-
# attribute will be set to nil.
|
120
|
-
def assign_multiparameter_attributes(pairs)
|
121
|
-
execute_callstack_for_multiparameter_attributes(
|
122
|
-
extract_callstack_for_multiparameter_attributes(pairs)
|
123
|
-
)
|
124
|
-
end
|
28
|
+
# Assign any deferred nested attributes after the base attributes have been set.
|
29
|
+
def assign_nested_parameter_attributes(pairs)
|
30
|
+
pairs.each { |k, v| _assign_attribute(k, v) }
|
31
|
+
end
|
125
32
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
33
|
+
# Instantiates objects for all attribute classes that needs more than one constructor parameter. This is done
|
34
|
+
# by calling new on the column type or aggregation type (through composed_of) object with these parameters.
|
35
|
+
# So having the pairs written_on(1) = "2004", written_on(2) = "6", written_on(3) = "24", will instantiate
|
36
|
+
# written_on (a date type) with Date.new("2004", "6", "24"). You can also specify a typecast character in the
|
37
|
+
# parentheses to have the parameters typecasted before they're used in the constructor. Use i for Integer and
|
38
|
+
# f for Float. If all the values for a given attribute are empty, the attribute will be set to +nil+.
|
39
|
+
def assign_multiparameter_attributes(pairs)
|
40
|
+
execute_callstack_for_multiparameter_attributes(
|
41
|
+
extract_callstack_for_multiparameter_attributes(pairs)
|
42
|
+
)
|
131
43
|
end
|
132
|
-
end
|
133
44
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
45
|
+
def execute_callstack_for_multiparameter_attributes(callstack)
|
46
|
+
errors = []
|
47
|
+
callstack.each do |name, values_with_empty_parameters|
|
48
|
+
if values_with_empty_parameters.each_value.all?(&:nil?)
|
49
|
+
values = nil
|
50
|
+
else
|
51
|
+
values = values_with_empty_parameters
|
52
|
+
end
|
53
|
+
send("#{name}=", values)
|
139
54
|
rescue => ex
|
140
|
-
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name}", ex, name)
|
55
|
+
errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name)
|
56
|
+
end
|
57
|
+
unless errors.empty?
|
58
|
+
error_descriptions = errors.map(&:message).join(",")
|
59
|
+
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]"
|
141
60
|
end
|
142
61
|
end
|
143
|
-
unless errors.empty?
|
144
|
-
raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes"
|
145
|
-
end
|
146
|
-
end
|
147
62
|
|
148
|
-
|
149
|
-
|
150
|
-
if values_hash_from_param.values.all?{|v|v.nil?}
|
151
|
-
nil
|
152
|
-
elsif klass == Time
|
153
|
-
read_time_parameter_value(name, values_hash_from_param)
|
154
|
-
elsif klass == Date
|
155
|
-
read_date_parameter_value(name, values_hash_from_param)
|
156
|
-
else
|
157
|
-
read_other_parameter_value(klass, name, values_hash_from_param)
|
158
|
-
end
|
159
|
-
end
|
63
|
+
def extract_callstack_for_multiparameter_attributes(pairs)
|
64
|
+
attributes = {}
|
160
65
|
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
max_position = extract_max_param_for_multiparameter_attributes(values_hash_from_param, 6)
|
165
|
-
# If Date bits were provided but blank, then return nil
|
166
|
-
return nil if (1..3).any? {|position| values_hash_from_param[position].blank?}
|
66
|
+
pairs.each do |(multiparameter_name, value)|
|
67
|
+
attribute_name = multiparameter_name.split("(").first
|
68
|
+
attributes[attribute_name] ||= {}
|
167
69
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
instantiate_time_object(name, set_values)
|
172
|
-
end
|
70
|
+
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
71
|
+
attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
|
72
|
+
end
|
173
73
|
|
174
|
-
|
175
|
-
return nil if (1..3).any? {|position| values_hash_from_param[position].blank?}
|
176
|
-
set_values = [values_hash_from_param[1], values_hash_from_param[2], values_hash_from_param[3]]
|
177
|
-
begin
|
178
|
-
Date.new(*set_values)
|
179
|
-
rescue ArgumentError # if Date.new raises an exception on an invalid date
|
180
|
-
instantiate_time_object(name, set_values).to_date # we instantiate Time object and convert it back to a date thus using Time's logic in handling invalid dates
|
74
|
+
attributes
|
181
75
|
end
|
182
|
-
end
|
183
76
|
|
184
|
-
|
185
|
-
|
186
|
-
values = (1..max_position).collect do |position|
|
187
|
-
raise "Missing Parameter" if !values_hash_from_param.has_key?(position)
|
188
|
-
values_hash_from_param[position]
|
77
|
+
def type_cast_attribute_value(multiparameter_name, value)
|
78
|
+
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
189
79
|
end
|
190
|
-
klass.new(*values)
|
191
|
-
end
|
192
80
|
|
193
|
-
|
194
|
-
|
195
|
-
end
|
196
|
-
|
197
|
-
def extract_callstack_for_multiparameter_attributes(pairs)
|
198
|
-
attributes = { }
|
199
|
-
|
200
|
-
pairs.each do |pair|
|
201
|
-
multiparameter_name, value = pair
|
202
|
-
attribute_name = multiparameter_name.split("(").first
|
203
|
-
attributes[attribute_name] = {} unless attributes.include?(attribute_name)
|
204
|
-
|
205
|
-
parameter_value = value.empty? ? nil : type_cast_attribute_value(multiparameter_name, value)
|
206
|
-
attributes[attribute_name][find_parameter_position(multiparameter_name)] ||= parameter_value
|
81
|
+
def find_parameter_position(multiparameter_name)
|
82
|
+
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
207
83
|
end
|
208
|
-
|
209
|
-
attributes
|
210
|
-
end
|
211
|
-
|
212
|
-
def type_cast_attribute_value(multiparameter_name, value)
|
213
|
-
multiparameter_name =~ /\([0-9]*([if])\)/ ? value.send("to_" + $1) : value
|
214
|
-
end
|
215
|
-
|
216
|
-
def find_parameter_position(multiparameter_name)
|
217
|
-
multiparameter_name.scan(/\(([0-9]*).*\)/).first.first.to_i
|
218
|
-
end
|
219
|
-
|
220
84
|
end
|
221
85
|
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module AttributeDecorators # :nodoc:
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
class_attribute :attribute_type_decorations, instance_accessor: false, default: TypeDecorator.new # :internal:
|
9
|
+
end
|
10
|
+
|
11
|
+
module ClassMethods # :nodoc:
|
12
|
+
# This method is an internal API used to create class macros such as
|
13
|
+
# +serialize+, and features like time zone aware attributes.
|
14
|
+
#
|
15
|
+
# Used to wrap the type of an attribute in a new type.
|
16
|
+
# When the schema for a model is loaded, attributes with the same name as
|
17
|
+
# +column_name+ will have their type yielded to the given block. The
|
18
|
+
# return value of that block will be used instead.
|
19
|
+
#
|
20
|
+
# Subsequent calls where +column_name+ and +decorator_name+ are the same
|
21
|
+
# will override the previous decorator, not decorate twice. This can be
|
22
|
+
# used to create idempotent class macros like +serialize+
|
23
|
+
def decorate_attribute_type(column_name, decorator_name, &block)
|
24
|
+
matcher = ->(name, _) { name == column_name.to_s }
|
25
|
+
key = "_#{column_name}_#{decorator_name}"
|
26
|
+
decorate_matching_attribute_types(matcher, key, &block)
|
27
|
+
end
|
28
|
+
|
29
|
+
# This method is an internal API used to create higher level features like
|
30
|
+
# time zone aware attributes.
|
31
|
+
#
|
32
|
+
# When the schema for a model is loaded, +matcher+ will be called for each
|
33
|
+
# attribute with its name and type. If the matcher returns a truthy value,
|
34
|
+
# the type will then be yielded to the given block, and the return value
|
35
|
+
# of that block will replace the type.
|
36
|
+
#
|
37
|
+
# Subsequent calls to this method with the same value for +decorator_name+
|
38
|
+
# will replace the previous decorator, not decorate twice. This can be
|
39
|
+
# used to ensure that class macros are idempotent.
|
40
|
+
def decorate_matching_attribute_types(matcher, decorator_name, &block)
|
41
|
+
reload_schema_from_cache
|
42
|
+
decorator_name = decorator_name.to_s
|
43
|
+
|
44
|
+
# Create new hashes so we don't modify parent classes
|
45
|
+
self.attribute_type_decorations = attribute_type_decorations.merge(decorator_name => [matcher, block])
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def load_schema!
|
51
|
+
super
|
52
|
+
attribute_types.each do |name, type|
|
53
|
+
decorated_type = attribute_type_decorations.apply(name, type)
|
54
|
+
define_attribute(name, decorated_type)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class TypeDecorator # :nodoc:
|
60
|
+
delegate :clear, to: :@decorations
|
61
|
+
|
62
|
+
def initialize(decorations = {})
|
63
|
+
@decorations = decorations
|
64
|
+
end
|
65
|
+
|
66
|
+
def merge(*args)
|
67
|
+
TypeDecorator.new(@decorations.merge(*args))
|
68
|
+
end
|
69
|
+
|
70
|
+
def apply(name, type)
|
71
|
+
decorations = decorators_for(name, type)
|
72
|
+
decorations.inject(type) do |new_type, block|
|
73
|
+
block.call(new_type)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
private
|
78
|
+
|
79
|
+
def decorators_for(name, type)
|
80
|
+
matching(name, type).map(&:last)
|
81
|
+
end
|
82
|
+
|
83
|
+
def matching(name, type)
|
84
|
+
@decorations.values.select do |(matcher, _)|
|
85
|
+
matcher.call(name, type)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -1,31 +1,81 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
module AttributeMethods
|
5
|
+
# = Active Record Attribute Methods Before Type Cast
|
6
|
+
#
|
7
|
+
# ActiveRecord::AttributeMethods::BeforeTypeCast provides a way to
|
8
|
+
# read the value of the attributes before typecasting and deserialization.
|
9
|
+
#
|
10
|
+
# class Task < ActiveRecord::Base
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# task = Task.new(id: '1', completed_on: '2012-10-21')
|
14
|
+
# task.id # => 1
|
15
|
+
# task.completed_on # => Sun, 21 Oct 2012
|
16
|
+
#
|
17
|
+
# task.attributes_before_type_cast
|
18
|
+
# # => {"id"=>"1", "completed_on"=>"2012-10-21", ... }
|
19
|
+
# task.read_attribute_before_type_cast('id') # => "1"
|
20
|
+
# task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
|
21
|
+
#
|
22
|
+
# In addition to #read_attribute_before_type_cast and #attributes_before_type_cast,
|
23
|
+
# it declares a method for all attributes with the <tt>*_before_type_cast</tt>
|
24
|
+
# suffix.
|
25
|
+
#
|
26
|
+
# task.id_before_type_cast # => "1"
|
27
|
+
# task.completed_on_before_type_cast # => "2012-10-21"
|
3
28
|
module BeforeTypeCast
|
4
29
|
extend ActiveSupport::Concern
|
5
30
|
|
6
31
|
included do
|
7
32
|
attribute_method_suffix "_before_type_cast"
|
33
|
+
attribute_method_suffix "_came_from_user?"
|
8
34
|
end
|
9
35
|
|
36
|
+
# Returns the value of the attribute identified by +attr_name+ before
|
37
|
+
# typecasting and deserialization.
|
38
|
+
#
|
39
|
+
# class Task < ActiveRecord::Base
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# task = Task.new(id: '1', completed_on: '2012-10-21')
|
43
|
+
# task.read_attribute('id') # => 1
|
44
|
+
# task.read_attribute_before_type_cast('id') # => '1'
|
45
|
+
# task.read_attribute('completed_on') # => Sun, 21 Oct 2012
|
46
|
+
# task.read_attribute_before_type_cast('completed_on') # => "2012-10-21"
|
47
|
+
# task.read_attribute_before_type_cast(:completed_on) # => "2012-10-21"
|
10
48
|
def read_attribute_before_type_cast(attr_name)
|
11
|
-
@
|
49
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
50
|
+
@attributes[attr_name.to_s].value_before_type_cast
|
12
51
|
end
|
13
52
|
|
14
53
|
# Returns a hash of attributes before typecasting and deserialization.
|
54
|
+
#
|
55
|
+
# class Task < ActiveRecord::Base
|
56
|
+
# end
|
57
|
+
#
|
58
|
+
# task = Task.new(title: nil, is_done: true, completed_on: '2012-10-21')
|
59
|
+
# task.attributes
|
60
|
+
# # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>Sun, 21 Oct 2012, "created_at"=>nil, "updated_at"=>nil}
|
61
|
+
# task.attributes_before_type_cast
|
62
|
+
# # => {"id"=>nil, "title"=>nil, "is_done"=>true, "completed_on"=>"2012-10-21", "created_at"=>nil, "updated_at"=>nil}
|
15
63
|
def attributes_before_type_cast
|
16
|
-
@
|
64
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
65
|
+
@attributes.values_before_type_cast
|
17
66
|
end
|
18
67
|
|
19
68
|
private
|
20
69
|
|
21
|
-
|
22
|
-
|
23
|
-
if attribute_name == 'id'
|
24
|
-
read_attribute_before_type_cast(self.class.primary_key)
|
25
|
-
else
|
70
|
+
# Dispatch target for <tt>*_before_type_cast</tt> attribute methods.
|
71
|
+
def attribute_before_type_cast(attribute_name)
|
26
72
|
read_attribute_before_type_cast(attribute_name)
|
27
73
|
end
|
28
|
-
|
74
|
+
|
75
|
+
def attribute_came_from_user?(attribute_name)
|
76
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
77
|
+
@attributes[attribute_name].came_from_user?
|
78
|
+
end
|
29
79
|
end
|
30
80
|
end
|
31
81
|
end
|