activerecord 4.2.0 → 6.1.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/CHANGELOG.md +1221 -796
- 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 +267 -249
- data/lib/active_record/association_relation.rb +45 -7
- data/lib/active_record/associations/alias_tracker.rb +40 -43
- data/lib/active_record/associations/association.rb +172 -67
- data/lib/active_record/associations/association_scope.rb +105 -129
- data/lib/active_record/associations/belongs_to_association.rb +85 -59
- 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 -33
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +57 -70
- 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 +168 -279
- data/lib/active_record/associations/collection_proxy.rb +263 -155
- data/lib/active_record/associations/foreign_association.rb +33 -0
- data/lib/active_record/associations/has_many_association.rb +57 -84
- data/lib/active_record/associations/has_many_through_association.rb +70 -82
- data/lib/active_record/associations/has_one_association.rb +74 -47
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +54 -73
- 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 +175 -164
- data/lib/active_record/associations/preloader/association.rb +107 -112
- data/lib/active_record/associations/preloader/through_association.rb +85 -65
- data/lib/active_record/associations/preloader.rb +99 -96
- data/lib/active_record/associations/singular_association.rb +18 -45
- data/lib/active_record/associations/through_association.rb +49 -24
- data/lib/active_record/associations.rb +1845 -1597
- data/lib/active_record/attribute_assignment.rb +59 -185
- data/lib/active_record/attribute_methods/before_type_cast.rb +20 -7
- data/lib/active_record/attribute_methods/dirty.rb +168 -138
- 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 +59 -36
- data/lib/active_record/attribute_methods/write.rb +25 -56
- data/lib/active_record/attribute_methods.rb +153 -162
- data/lib/active_record/attributes.rb +234 -70
- data/lib/active_record/autosave_association.rb +157 -69
- data/lib/active_record/base.rb +49 -50
- 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 +46 -13
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +887 -317
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +17 -41
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +301 -113
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +78 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +187 -60
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +9 -7
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +157 -93
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +485 -253
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +79 -36
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +909 -263
- data/lib/active_record/connection_adapters/abstract/transaction.rb +254 -92
- data/lib/active_record/connection_adapters/abstract_adapter.rb +492 -221
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +580 -608
- 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 +196 -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 +271 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +40 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +81 -199
- 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 +78 -161
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +49 -57
- 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 +5 -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 +17 -13
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +3 -1
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +6 -3
- 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 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +67 -51
- 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 +171 -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 +499 -293
- 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 +595 -382
- data/lib/active_record/connection_adapters/schema_cache.rb +191 -29
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +45 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -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 -389
- 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 +488 -243
- data/lib/active_record/counter_cache.rb +71 -50
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -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 +273 -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 +212 -94
- data/lib/active_record/errors.rb +225 -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 +11 -6
- 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 +273 -496
- 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 +64 -0
- data/lib/active_record/legacy_yaml_adapter.rb +52 -0
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +103 -95
- 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 +298 -0
- data/lib/active_record/migration/join_table.rb +8 -7
- data/lib/active_record/migration.rb +685 -309
- data/lib/active_record/model_schema.rb +420 -113
- data/lib/active_record/nested_attributes.rb +265 -216
- data/lib/active_record/no_touching.rb +15 -2
- data/lib/active_record/null_relation.rb +24 -38
- data/lib/active_record/persistence.rb +574 -135
- data/lib/active_record/query_cache.rb +29 -23
- data/lib/active_record/querying.rb +50 -31
- data/lib/active_record/railtie.rb +175 -54
- 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 +533 -216
- data/lib/active_record/readonly_attributes.rb +9 -4
- data/lib/active_record/reflection.rb +485 -310
- 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 +326 -244
- data/lib/active_record/relation/delegation.rb +76 -84
- data/lib/active_record/relation/finder_methods.rb +318 -256
- data/lib/active_record/relation/from_clause.rb +30 -0
- data/lib/active_record/relation/merger.rb +99 -84
- data/lib/active_record/relation/predicate_builder/array_handler.rb +26 -25
- 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 +139 -96
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +757 -409
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +23 -21
- data/lib/active_record/relation/where_clause.rb +239 -0
- data/lib/active_record/relation.rb +554 -342
- 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 -26
- data/lib/active_record/scoping/default.rb +96 -82
- 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 +133 -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 +366 -129
- data/lib/active_record/tasks/mysql_database_tasks.rb +68 -100
- data/lib/active_record/tasks/postgresql_database_tasks.rb +87 -39
- 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 +291 -0
- data/lib/active_record/timestamp.rb +86 -43
- data/lib/active_record/touch_later.rb +65 -0
- data/lib/active_record/transactions.rb +181 -152
- 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 -41
- data/lib/active_record/type/date_time.rb +4 -38
- data/lib/active_record/type/decimal_without_scale.rb +6 -2
- data/lib/active_record/type/hash_lookup_type_map.rb +12 -5
- 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 +33 -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 +65 -48
- data/lib/active_record/validations.rb +39 -35
- data/lib/active_record/version.rb +3 -1
- data/lib/active_record.rb +44 -28
- 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 -10
- 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.rb +7 -5
- metadata +175 -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 -149
- data/lib/active_record/attribute_decorators.rb +0 -66
- data/lib/active_record/attribute_set/builder.rb +0 -86
- data/lib/active_record/attribute_set.rb +0 -77
- 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 -30
- data/lib/active_record/type/decimal.rb +0 -40
- 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 -55
- 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 -36
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/value.rb +0 -101
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +0 -22
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -10
- /data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +0 -0
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record Autosave Association
|
3
5
|
#
|
4
|
-
#
|
6
|
+
# AutosaveAssociation is a module that takes care of automatically saving
|
5
7
|
# associated records when their parent is saved. In addition to saving, it
|
6
8
|
# also destroys any associated records that were marked for destruction.
|
7
|
-
# (See
|
9
|
+
# (See #mark_for_destruction and #marked_for_destruction?).
|
8
10
|
#
|
9
11
|
# Saving of the parent, its associations, and the destruction of marked
|
10
12
|
# associations, all happen inside a transaction. This should never leave the
|
@@ -22,14 +24,14 @@ module ActiveRecord
|
|
22
24
|
#
|
23
25
|
# == Validation
|
24
26
|
#
|
25
|
-
#
|
27
|
+
# Child records are validated unless <tt>:validate</tt> is +false+.
|
26
28
|
#
|
27
29
|
# == Callbacks
|
28
30
|
#
|
29
31
|
# Association with autosave option defines several callbacks on your
|
30
|
-
# model (before_save, after_create, after_update). Please note that
|
32
|
+
# model (around_save, before_save, after_create, after_update). Please note that
|
31
33
|
# callbacks are executed in the order they were defined in
|
32
|
-
# model. You should avoid modifying the association content
|
34
|
+
# model. You should avoid modifying the association content before
|
33
35
|
# autosave callbacks are executed. Placing your callbacks after
|
34
36
|
# associations is usually a good practice.
|
35
37
|
#
|
@@ -89,8 +91,9 @@ module ActiveRecord
|
|
89
91
|
# post.save # => saves both post and comment
|
90
92
|
#
|
91
93
|
# post = Post.create(title: 'ruby rocks')
|
92
|
-
# post.comments.create(body: 'hello world')
|
93
|
-
#
|
94
|
+
# comment = post.comments.create(body: 'hello world')
|
95
|
+
# comment.body = 'hi everyone'
|
96
|
+
# post.save # => saves post, but not comment
|
94
97
|
#
|
95
98
|
# When <tt>:autosave</tt> is true all children are saved, no matter whether they
|
96
99
|
# are new records or not:
|
@@ -100,11 +103,10 @@ module ActiveRecord
|
|
100
103
|
# end
|
101
104
|
#
|
102
105
|
# post = Post.create(title: 'ruby rocks')
|
103
|
-
# post.comments.create(body: 'hello world')
|
104
|
-
#
|
106
|
+
# comment = post.comments.create(body: 'hello world')
|
107
|
+
# comment.body = 'hi everyone'
|
105
108
|
# post.comments.build(body: "good morning.")
|
106
|
-
# post.
|
107
|
-
# post.save # => saves both post and comments.
|
109
|
+
# post.save # => saves post and both comments.
|
108
110
|
#
|
109
111
|
# Destroying one of the associated models as part of the parent's save action
|
110
112
|
# is as simple as marking it for destruction:
|
@@ -125,7 +127,14 @@ module ActiveRecord
|
|
125
127
|
# Now it _is_ removed from the database:
|
126
128
|
#
|
127
129
|
# Comment.find_by(id: id).nil? # => true
|
128
|
-
|
130
|
+
#
|
131
|
+
# === Caveats
|
132
|
+
#
|
133
|
+
# Note that autosave will only trigger for already-persisted association records
|
134
|
+
# if the records themselves have been changed. This is to protect against
|
135
|
+
# <tt>SystemStackError</tt> caused by circular association validations. The one
|
136
|
+
# exception is if a custom validation context is used, in which case the validations
|
137
|
+
# will always fire on the associated records.
|
129
138
|
module AutosaveAssociation
|
130
139
|
extend ActiveSupport::Concern
|
131
140
|
|
@@ -141,22 +150,37 @@ module ActiveRecord
|
|
141
150
|
|
142
151
|
included do
|
143
152
|
Associations::Builder::Association.extensions << AssociationBuilderExtension
|
153
|
+
mattr_accessor :index_nested_attribute_errors, instance_writer: false, default: false
|
144
154
|
end
|
145
155
|
|
146
|
-
module ClassMethods
|
156
|
+
module ClassMethods # :nodoc:
|
147
157
|
private
|
158
|
+
if Module.method(:method_defined?).arity == 1 # MRI 2.5 and older
|
159
|
+
using Module.new {
|
160
|
+
refine Module do
|
161
|
+
def method_defined?(method, inherit = true)
|
162
|
+
if inherit
|
163
|
+
super(method)
|
164
|
+
else
|
165
|
+
instance_methods(false).include?(method.to_sym)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
169
|
+
}
|
170
|
+
end
|
148
171
|
|
149
172
|
def define_non_cyclic_method(name, &block)
|
150
|
-
return if method_defined?(name)
|
173
|
+
return if method_defined?(name, false)
|
174
|
+
|
151
175
|
define_method(name) do |*args|
|
152
176
|
result = true; @_already_called ||= {}
|
153
177
|
# Loop prevention for validation of associations
|
154
178
|
unless @_already_called[name]
|
155
179
|
begin
|
156
|
-
@_already_called[name]=true
|
180
|
+
@_already_called[name] = true
|
157
181
|
result = instance_eval(&block)
|
158
182
|
ensure
|
159
|
-
@_already_called[name]=false
|
183
|
+
@_already_called[name] = false
|
160
184
|
end
|
161
185
|
end
|
162
186
|
|
@@ -177,11 +201,9 @@ module ActiveRecord
|
|
177
201
|
# before actually defining them.
|
178
202
|
def add_autosave_association_callbacks(reflection)
|
179
203
|
save_method = :"autosave_associated_records_for_#{reflection.name}"
|
180
|
-
validation_method = :"validate_associated_records_for_#{reflection.name}"
|
181
|
-
collection = reflection.collection?
|
182
204
|
|
183
|
-
if collection
|
184
|
-
|
205
|
+
if reflection.collection?
|
206
|
+
around_save :around_save_collection_association
|
185
207
|
|
186
208
|
define_non_cyclic_method(save_method) { save_collection_association(reflection) }
|
187
209
|
# Doesn't use after_save as that would save associations added in after_create/after_update twice
|
@@ -200,14 +222,25 @@ module ActiveRecord
|
|
200
222
|
after_create save_method
|
201
223
|
after_update save_method
|
202
224
|
else
|
203
|
-
define_non_cyclic_method(save_method) { save_belongs_to_association(reflection) }
|
225
|
+
define_non_cyclic_method(save_method) { throw(:abort) if save_belongs_to_association(reflection) == false }
|
204
226
|
before_save save_method
|
205
227
|
end
|
206
228
|
|
229
|
+
define_autosave_validation_callbacks(reflection)
|
230
|
+
end
|
231
|
+
|
232
|
+
def define_autosave_validation_callbacks(reflection)
|
233
|
+
validation_method = :"validate_associated_records_for_#{reflection.name}"
|
207
234
|
if reflection.validate? && !method_defined?(validation_method)
|
208
|
-
|
235
|
+
if reflection.collection?
|
236
|
+
method = :validate_collection_association
|
237
|
+
else
|
238
|
+
method = :validate_single_association
|
239
|
+
end
|
240
|
+
|
209
241
|
define_non_cyclic_method(validation_method) { send(method, reflection) }
|
210
242
|
validate validation_method
|
243
|
+
after_validation :_ensure_no_duplicate_errors
|
211
244
|
end
|
212
245
|
end
|
213
246
|
end
|
@@ -219,7 +252,7 @@ module ActiveRecord
|
|
219
252
|
super
|
220
253
|
end
|
221
254
|
|
222
|
-
# Marks this record to be destroyed as part of the
|
255
|
+
# Marks this record to be destroyed as part of the parent's save transaction.
|
223
256
|
# This does _not_ actually destroy the record instantly, rather child record will be destroyed
|
224
257
|
# when <tt>parent.save</tt> is called.
|
225
258
|
#
|
@@ -228,7 +261,7 @@ module ActiveRecord
|
|
228
261
|
@marked_for_destruction = true
|
229
262
|
end
|
230
263
|
|
231
|
-
# Returns whether or not this record will be destroyed as part of the
|
264
|
+
# Returns whether or not this record will be destroyed as part of the parent's save transaction.
|
232
265
|
#
|
233
266
|
# Only useful if the <tt>:autosave</tt> option on the parent is enabled for this associated model.
|
234
267
|
def marked_for_destruction?
|
@@ -251,32 +284,39 @@ module ActiveRecord
|
|
251
284
|
# Returns whether or not this record has been changed in any way (including whether
|
252
285
|
# any of its nested autosave associations are likewise changed)
|
253
286
|
def changed_for_autosave?
|
254
|
-
new_record? ||
|
287
|
+
new_record? || has_changes_to_save? || marked_for_destruction? || nested_records_changed_for_autosave?
|
255
288
|
end
|
256
289
|
|
257
290
|
private
|
258
|
-
|
259
291
|
# Returns the record for an association collection that should be validated
|
260
292
|
# or saved. If +autosave+ is +false+ only new records will be returned,
|
261
293
|
# unless the parent is/was a new record itself.
|
262
294
|
def associated_records_to_validate_or_save(association, new_record, autosave)
|
263
|
-
if new_record
|
295
|
+
if new_record || custom_validation_context?
|
264
296
|
association && association.target
|
265
297
|
elsif autosave
|
266
|
-
association.target.find_all
|
298
|
+
association.target.find_all(&:changed_for_autosave?)
|
267
299
|
else
|
268
|
-
association.target.find_all
|
300
|
+
association.target.find_all(&:new_record?)
|
269
301
|
end
|
270
302
|
end
|
271
303
|
|
272
|
-
#
|
273
|
-
# any new ones), and return true if
|
304
|
+
# Go through nested autosave associations that are loaded in memory (without loading
|
305
|
+
# any new ones), and return true if any are changed for autosave.
|
306
|
+
# Returns false if already called to prevent an infinite loop.
|
274
307
|
def nested_records_changed_for_autosave?
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
308
|
+
@_nested_records_changed_for_autosave_already_called ||= false
|
309
|
+
return false if @_nested_records_changed_for_autosave_already_called
|
310
|
+
begin
|
311
|
+
@_nested_records_changed_for_autosave_already_called = true
|
312
|
+
self.class._reflections.values.any? do |reflection|
|
313
|
+
if reflection.options[:autosave]
|
314
|
+
association = association_instance_get(reflection.name)
|
315
|
+
association && Array.wrap(association.target).any?(&:changed_for_autosave?)
|
316
|
+
end
|
279
317
|
end
|
318
|
+
ensure
|
319
|
+
@_nested_records_changed_for_autosave_already_called = false
|
280
320
|
end
|
281
321
|
end
|
282
322
|
|
@@ -285,7 +325,7 @@ module ActiveRecord
|
|
285
325
|
def validate_single_association(reflection)
|
286
326
|
association = association_instance_get(reflection.name)
|
287
327
|
record = association && association.reader
|
288
|
-
association_valid?(reflection, record) if record
|
328
|
+
association_valid?(reflection, record) if record && (record.changed_for_autosave? || custom_validation_context?)
|
289
329
|
end
|
290
330
|
|
291
331
|
# Validate the associated records if <tt>:validate</tt> or
|
@@ -294,7 +334,7 @@ module ActiveRecord
|
|
294
334
|
def validate_collection_association(reflection)
|
295
335
|
if association = association_instance_get(reflection.name)
|
296
336
|
if records = associated_records_to_validate_or_save(association, new_record?, reflection.options[:autosave])
|
297
|
-
records.
|
337
|
+
records.each_with_index { |record, index| association_valid?(reflection, record, index) }
|
298
338
|
end
|
299
339
|
end
|
300
340
|
end
|
@@ -302,17 +342,25 @@ module ActiveRecord
|
|
302
342
|
# Returns whether or not the association is valid and applies any errors to
|
303
343
|
# the parent, <tt>self</tt>, if it wasn't. Skips any <tt>:autosave</tt>
|
304
344
|
# enabled records if they're marked_for_destruction? or destroyed.
|
305
|
-
def association_valid?(reflection, record)
|
306
|
-
return true if record.destroyed? || record.marked_for_destruction?
|
345
|
+
def association_valid?(reflection, record, index = nil)
|
346
|
+
return true if record.destroyed? || (reflection.options[:autosave] && record.marked_for_destruction?)
|
307
347
|
|
308
|
-
|
309
|
-
|
348
|
+
context = validation_context if custom_validation_context?
|
349
|
+
|
350
|
+
unless valid = record.valid?(context)
|
310
351
|
if reflection.options[:autosave]
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
352
|
+
indexed_attribute = !index.nil? && (reflection.options[:index_errors] || ActiveRecord::Base.index_nested_attribute_errors)
|
353
|
+
|
354
|
+
record.errors.group_by_attribute.each { |attribute, errors|
|
355
|
+
attribute = normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
|
356
|
+
|
357
|
+
errors.each { |error|
|
358
|
+
self.errors.import(
|
359
|
+
error,
|
360
|
+
attribute: attribute
|
361
|
+
)
|
362
|
+
}
|
363
|
+
}
|
316
364
|
else
|
317
365
|
errors.add(reflection.name)
|
318
366
|
end
|
@@ -320,18 +368,30 @@ module ActiveRecord
|
|
320
368
|
valid
|
321
369
|
end
|
322
370
|
|
323
|
-
|
371
|
+
def normalize_reflection_attribute(indexed_attribute, reflection, index, attribute)
|
372
|
+
if indexed_attribute
|
373
|
+
"#{reflection.name}[#{index}].#{attribute}"
|
374
|
+
else
|
375
|
+
"#{reflection.name}.#{attribute}"
|
376
|
+
end
|
377
|
+
end
|
378
|
+
|
379
|
+
# Is used as an around_save callback to check while saving a collection
|
324
380
|
# association whether or not the parent was a new record before saving.
|
325
|
-
def
|
326
|
-
@new_record_before_save
|
327
|
-
|
381
|
+
def around_save_collection_association
|
382
|
+
previously_new_record_before_save = (@new_record_before_save ||= false)
|
383
|
+
@new_record_before_save = !previously_new_record_before_save && new_record?
|
384
|
+
|
385
|
+
yield
|
386
|
+
ensure
|
387
|
+
@new_record_before_save = previously_new_record_before_save
|
328
388
|
end
|
329
389
|
|
330
390
|
# Saves any new associated records, or all loaded autosave associations if
|
331
391
|
# <tt>:autosave</tt> is enabled on the association.
|
332
392
|
#
|
333
393
|
# In addition, it destroys all children that were marked for destruction
|
334
|
-
# with mark_for_destruction.
|
394
|
+
# with #mark_for_destruction.
|
335
395
|
#
|
336
396
|
# This all happens inside a transaction, _if_ the Transactions module is included into
|
337
397
|
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
|
@@ -339,7 +399,14 @@ module ActiveRecord
|
|
339
399
|
if association = association_instance_get(reflection.name)
|
340
400
|
autosave = reflection.options[:autosave]
|
341
401
|
|
342
|
-
|
402
|
+
# By saving the instance variable in a local variable,
|
403
|
+
# we make the whole callback re-entrant.
|
404
|
+
new_record_before_save = @new_record_before_save
|
405
|
+
|
406
|
+
# reconstruct the scope now that we know the owner's id
|
407
|
+
association.reset_scope
|
408
|
+
|
409
|
+
if records = associated_records_to_validate_or_save(association, new_record_before_save, autosave)
|
343
410
|
if autosave
|
344
411
|
records_to_destroy = records.select(&:marked_for_destruction?)
|
345
412
|
records_to_destroy.each { |record| association.destroy(record) }
|
@@ -351,22 +418,24 @@ module ActiveRecord
|
|
351
418
|
|
352
419
|
saved = true
|
353
420
|
|
354
|
-
if autosave != false && (
|
421
|
+
if autosave != false && (new_record_before_save || record.new_record?)
|
355
422
|
if autosave
|
356
423
|
saved = association.insert_record(record, false)
|
357
|
-
|
358
|
-
association.insert_record(record)
|
424
|
+
elsif !reflection.nested?
|
425
|
+
association_saved = association.insert_record(record)
|
426
|
+
|
427
|
+
if reflection.validate?
|
428
|
+
errors.add(reflection.name) unless association_saved
|
429
|
+
saved = association_saved
|
430
|
+
end
|
359
431
|
end
|
360
432
|
elsif autosave
|
361
|
-
saved = record.save(:
|
433
|
+
saved = record.save(validate: false)
|
362
434
|
end
|
363
435
|
|
364
|
-
raise
|
436
|
+
raise(RecordInvalid.new(association.owner)) unless saved
|
365
437
|
end
|
366
438
|
end
|
367
|
-
|
368
|
-
# reconstruct the scope now that we know the owner's id
|
369
|
-
association.reset_scope if association.respond_to?(:reset_scope)
|
370
439
|
end
|
371
440
|
end
|
372
441
|
|
@@ -374,7 +443,7 @@ module ActiveRecord
|
|
374
443
|
# on the association.
|
375
444
|
#
|
376
445
|
# In addition, it will destroy the association if it was marked for
|
377
|
-
# destruction with mark_for_destruction.
|
446
|
+
# destruction with #mark_for_destruction.
|
378
447
|
#
|
379
448
|
# This all happens inside a transaction, _if_ the Transactions module is included into
|
380
449
|
# ActiveRecord::Base after the AutosaveAssociation module, which it does by default.
|
@@ -388,14 +457,17 @@ module ActiveRecord
|
|
388
457
|
if autosave && record.marked_for_destruction?
|
389
458
|
record.destroy
|
390
459
|
elsif autosave != false
|
391
|
-
key = reflection.options[:primary_key] ?
|
460
|
+
key = reflection.options[:primary_key] ? public_send(reflection.options[:primary_key]) : id
|
392
461
|
|
393
|
-
if (autosave && record.changed_for_autosave?) ||
|
462
|
+
if (autosave && record.changed_for_autosave?) || record_changed?(reflection, record, key)
|
394
463
|
unless reflection.through_reflection
|
395
464
|
record[reflection.foreign_key] = key
|
465
|
+
if inverse_reflection = reflection.inverse_of
|
466
|
+
record.association(inverse_reflection.name).inversed_from(self)
|
467
|
+
end
|
396
468
|
end
|
397
469
|
|
398
|
-
saved = record.save(:
|
470
|
+
saved = record.save(validate: !autosave)
|
399
471
|
raise ActiveRecord::Rollback if !saved && autosave
|
400
472
|
saved
|
401
473
|
end
|
@@ -406,8 +478,14 @@ module ActiveRecord
|
|
406
478
|
# If the record is new or it has changed, returns true.
|
407
479
|
def record_changed?(reflection, record, key)
|
408
480
|
record.new_record? ||
|
409
|
-
|
410
|
-
record.
|
481
|
+
association_foreign_key_changed?(reflection, record, key) ||
|
482
|
+
record.will_save_change_to_attribute?(reflection.foreign_key)
|
483
|
+
end
|
484
|
+
|
485
|
+
def association_foreign_key_changed?(reflection, record, key)
|
486
|
+
return false if reflection.through_reflection?
|
487
|
+
|
488
|
+
record._has_attribute?(reflection.foreign_key) && record._read_attribute(reflection.foreign_key) != key
|
411
489
|
end
|
412
490
|
|
413
491
|
# Saves the associated record if it's new or <tt>:autosave</tt> is enabled.
|
@@ -415,7 +493,9 @@ module ActiveRecord
|
|
415
493
|
# In addition, it will destroy the association if it was marked for destruction.
|
416
494
|
def save_belongs_to_association(reflection)
|
417
495
|
association = association_instance_get(reflection.name)
|
418
|
-
|
496
|
+
return unless association && association.loaded? && !association.stale_target?
|
497
|
+
|
498
|
+
record = association.load_target
|
419
499
|
if record && !record.destroyed?
|
420
500
|
autosave = reflection.options[:autosave]
|
421
501
|
|
@@ -423,10 +503,10 @@ module ActiveRecord
|
|
423
503
|
self[reflection.foreign_key] = nil
|
424
504
|
record.destroy
|
425
505
|
elsif autosave != false
|
426
|
-
saved = record.save(:
|
506
|
+
saved = record.save(validate: !autosave) if record.new_record? || (autosave && record.changed_for_autosave?)
|
427
507
|
|
428
508
|
if association.updated?
|
429
|
-
association_id = record.
|
509
|
+
association_id = record.public_send(reflection.options[:primary_key] || :id)
|
430
510
|
self[reflection.foreign_key] = association_id
|
431
511
|
association.loaded!
|
432
512
|
end
|
@@ -435,5 +515,13 @@ module ActiveRecord
|
|
435
515
|
end
|
436
516
|
end
|
437
517
|
end
|
518
|
+
|
519
|
+
def custom_validation_context?
|
520
|
+
validation_context && [:create, :update].exclude?(validation_context)
|
521
|
+
end
|
522
|
+
|
523
|
+
def _ensure_no_duplicate_errors
|
524
|
+
errors.uniq!
|
525
|
+
end
|
438
526
|
end
|
439
527
|
end
|
data/lib/active_record/base.rb
CHANGED
@@ -1,27 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
9
|
-
require
|
10
|
-
require
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require 'active_support/core_ext/kernel/singleton_class'
|
15
|
-
require 'active_support/core_ext/module/introspection'
|
16
|
-
require 'active_support/core_ext/object/duplicable'
|
17
|
-
require 'active_support/core_ext/class/subclasses'
|
18
|
-
require 'arel'
|
19
|
-
require 'active_record/attribute_decorators'
|
20
|
-
require 'active_record/errors'
|
21
|
-
require 'active_record/log_subscriber'
|
22
|
-
require 'active_record/explain_subscriber'
|
23
|
-
require 'active_record/relation/delegation'
|
24
|
-
require 'active_record/attributes'
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_support/benchmarkable"
|
4
|
+
require "active_support/dependencies"
|
5
|
+
require "active_support/descendants_tracker"
|
6
|
+
require "active_support/time"
|
7
|
+
require "active_support/core_ext/class/subclasses"
|
8
|
+
require "active_record/log_subscriber"
|
9
|
+
require "active_record/explain_subscriber"
|
10
|
+
require "active_record/relation/delegation"
|
11
|
+
require "active_record/attributes"
|
12
|
+
require "active_record/type_caster"
|
13
|
+
require "active_record/database_configurations"
|
25
14
|
|
26
15
|
module ActiveRecord #:nodoc:
|
27
16
|
# = Active Record
|
@@ -119,29 +108,25 @@ module ActiveRecord #:nodoc:
|
|
119
108
|
# All column values are automatically available through basic accessors on the Active Record
|
120
109
|
# object, but sometimes you want to specialize this behavior. This can be done by overwriting
|
121
110
|
# the default accessors (using the same name as the attribute) and calling
|
122
|
-
#
|
123
|
-
# change things.
|
111
|
+
# +super+ to actually change things.
|
124
112
|
#
|
125
113
|
# class Song < ActiveRecord::Base
|
126
114
|
# # Uses an integer of seconds to hold the length of the song
|
127
115
|
#
|
128
116
|
# def length=(minutes)
|
129
|
-
#
|
117
|
+
# super(minutes.to_i * 60)
|
130
118
|
# end
|
131
119
|
#
|
132
120
|
# def length
|
133
|
-
#
|
121
|
+
# super / 60
|
134
122
|
# end
|
135
123
|
# end
|
136
124
|
#
|
137
|
-
# You can alternatively use <tt>self[:attribute]=(value)</tt> and <tt>self[:attribute]</tt>
|
138
|
-
# instead of <tt>write_attribute(:attribute, value)</tt> and <tt>read_attribute(:attribute)</tt>.
|
139
|
-
#
|
140
125
|
# == Attribute query methods
|
141
126
|
#
|
142
127
|
# In addition to the basic accessors, query methods are also automatically available on the Active Record object.
|
143
128
|
# Query methods allow you to test whether an attribute value is present.
|
144
|
-
#
|
129
|
+
# Additionally, when dealing with numeric values, a query method will return false if the value is zero.
|
145
130
|
#
|
146
131
|
# For example, an Active Record User with the <tt>name</tt> attribute has a <tt>name?</tt> method that you can call
|
147
132
|
# to determine whether the user has a name:
|
@@ -172,10 +157,11 @@ module ActiveRecord #:nodoc:
|
|
172
157
|
# <tt>Person.find_by_user_name(user_name)</tt>.
|
173
158
|
#
|
174
159
|
# It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an
|
175
|
-
#
|
160
|
+
# ActiveRecord::RecordNotFound error if they do not return any records,
|
176
161
|
# like <tt>Person.find_by_last_name!</tt>.
|
177
162
|
#
|
178
|
-
# It's also possible to use multiple attributes in the same
|
163
|
+
# It's also possible to use multiple attributes in the same <tt>find_by_</tt> by separating them with
|
164
|
+
# "_and_".
|
179
165
|
#
|
180
166
|
# Person.find_by(user_name: user_name, password: password)
|
181
167
|
# Person.find_by_user_name_and_password(user_name, password) # with dynamic finder
|
@@ -187,7 +173,8 @@ module ActiveRecord #:nodoc:
|
|
187
173
|
# == Saving arrays, hashes, and other non-mappable objects in text columns
|
188
174
|
#
|
189
175
|
# Active Record can serialize any object in text columns using YAML. To do so, you must
|
190
|
-
# specify this with a call to the class method
|
176
|
+
# specify this with a call to the class method
|
177
|
+
# {serialize}[rdoc-ref:AttributeMethods::Serialization::ClassMethods#serialize].
|
191
178
|
# This makes it possible to store arrays, hashes, and other non-mappable objects without doing
|
192
179
|
# any additional work.
|
193
180
|
#
|
@@ -227,39 +214,47 @@ module ActiveRecord #:nodoc:
|
|
227
214
|
#
|
228
215
|
# == Connection to multiple databases in different models
|
229
216
|
#
|
230
|
-
# Connections are usually created through
|
217
|
+
# Connections are usually created through
|
218
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] and retrieved
|
231
219
|
# by ActiveRecord::Base.connection. All classes inheriting from ActiveRecord::Base will use this
|
232
220
|
# connection. But you can also set a class-specific connection. For example, if Course is an
|
233
221
|
# ActiveRecord::Base, but resides in a different database, you can just say <tt>Course.establish_connection</tt>
|
234
222
|
# and Course and all of its subclasses will use this connection instead.
|
235
223
|
#
|
236
224
|
# This feature is implemented by keeping a connection pool in ActiveRecord::Base that is
|
237
|
-
# a
|
225
|
+
# a hash indexed by the class. If a connection is requested, the
|
226
|
+
# {ActiveRecord::Base.retrieve_connection}[rdoc-ref:ConnectionHandling#retrieve_connection] method
|
238
227
|
# will go up the class-hierarchy until a connection is found in the connection pool.
|
239
228
|
#
|
240
229
|
# == Exceptions
|
241
230
|
#
|
242
231
|
# * ActiveRecordError - Generic error class and superclass of all other errors raised by Active Record.
|
243
|
-
# * AdapterNotSpecified - The configuration hash used in
|
244
|
-
#
|
245
|
-
#
|
246
|
-
#
|
232
|
+
# * AdapterNotSpecified - The configuration hash used in
|
233
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
|
234
|
+
# didn't include an <tt>:adapter</tt> key.
|
235
|
+
# * AdapterNotFound - The <tt>:adapter</tt> key used in
|
236
|
+
# {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection]
|
237
|
+
# specified a non-existent adapter
|
247
238
|
# (or a bad spelling of an existing one).
|
248
239
|
# * AssociationTypeMismatch - The object assigned to the association wasn't of the type
|
249
240
|
# specified in the association definition.
|
250
241
|
# * AttributeAssignmentError - An error occurred while doing a mass assignment through the
|
251
|
-
#
|
242
|
+
# {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
|
252
243
|
# You can inspect the +attribute+ property of the exception object to determine which attribute
|
253
244
|
# triggered the error.
|
254
|
-
# * ConnectionNotEstablished - No connection has been established.
|
255
|
-
# before querying.
|
245
|
+
# * ConnectionNotEstablished - No connection has been established.
|
246
|
+
# Use {ActiveRecord::Base.establish_connection}[rdoc-ref:ConnectionHandling#establish_connection] before querying.
|
256
247
|
# * MultiparameterAssignmentErrors - Collection of errors that occurred during a mass assignment using the
|
257
|
-
#
|
248
|
+
# {ActiveRecord::Base#attributes=}[rdoc-ref:AttributeAssignment#attributes=] method.
|
249
|
+
# The +errors+ property of this exception contains an array of
|
258
250
|
# AttributeAssignmentError
|
259
251
|
# objects that should be inspected to determine which attributes triggered the errors.
|
260
|
-
# * RecordInvalid - raised by save! and
|
261
|
-
#
|
262
|
-
#
|
252
|
+
# * RecordInvalid - raised by {ActiveRecord::Base#save!}[rdoc-ref:Persistence#save!] and
|
253
|
+
# {ActiveRecord::Base.create!}[rdoc-ref:Persistence::ClassMethods#create!]
|
254
|
+
# when the record is invalid.
|
255
|
+
# * RecordNotFound - No record responded to the {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] method.
|
256
|
+
# Either the row with the given ID doesn't exist or the row didn't meet the additional restrictions.
|
257
|
+
# Some {ActiveRecord::Base.find}[rdoc-ref:FinderMethods#find] calls do not raise this exception to signal
|
263
258
|
# nothing was found, please check its documentation for further details.
|
264
259
|
# * SerializationTypeMismatch - The serialized object wasn't of the class specified as the second parameter.
|
265
260
|
# * StatementInvalid - The database server rejected the SQL statement. The precise error is added in the message.
|
@@ -278,9 +273,11 @@ module ActiveRecord #:nodoc:
|
|
278
273
|
extend Querying
|
279
274
|
extend Translation
|
280
275
|
extend DynamicMatchers
|
276
|
+
extend DelegatedType
|
281
277
|
extend Explain
|
282
278
|
extend Enum
|
283
279
|
extend Delegation::DelegateCache
|
280
|
+
extend Aggregations::ClassMethods
|
284
281
|
|
285
282
|
include Core
|
286
283
|
include Persistence
|
@@ -295,7 +292,6 @@ module ActiveRecord #:nodoc:
|
|
295
292
|
include Validations
|
296
293
|
include CounterCache
|
297
294
|
include Attributes
|
298
|
-
include AttributeDecorators
|
299
295
|
include Locking::Optimistic
|
300
296
|
include Locking::Pessimistic
|
301
297
|
include AttributeMethods
|
@@ -305,12 +301,15 @@ module ActiveRecord #:nodoc:
|
|
305
301
|
include ActiveModel::SecurePassword
|
306
302
|
include AutosaveAssociation
|
307
303
|
include NestedAttributes
|
308
|
-
include Aggregations
|
309
304
|
include Transactions
|
305
|
+
include TouchLater
|
310
306
|
include NoTouching
|
311
307
|
include Reflection
|
312
308
|
include Serialization
|
313
309
|
include Store
|
310
|
+
include SecureToken
|
311
|
+
include SignedId
|
312
|
+
include Suppressor
|
314
313
|
end
|
315
314
|
|
316
315
|
ActiveSupport.run_load_hooks(:active_record, Base)
|