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
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ActiveRecord
|
2
4
|
# = Active Record No Touching
|
3
5
|
module NoTouching
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
6
8
|
module ClassMethods
|
7
|
-
# Lets you selectively disable calls to
|
9
|
+
# Lets you selectively disable calls to +touch+ for the
|
8
10
|
# duration of a block.
|
9
11
|
#
|
10
12
|
# ==== Examples
|
@@ -41,10 +43,21 @@ module ActiveRecord
|
|
41
43
|
end
|
42
44
|
end
|
43
45
|
|
46
|
+
# Returns +true+ if the class has +no_touching+ set, +false+ otherwise.
|
47
|
+
#
|
48
|
+
# Project.no_touching do
|
49
|
+
# Project.first.no_touching? # true
|
50
|
+
# Message.first.no_touching? # false
|
51
|
+
# end
|
52
|
+
#
|
44
53
|
def no_touching?
|
45
54
|
NoTouching.applied_to?(self.class)
|
46
55
|
end
|
47
56
|
|
57
|
+
def touch_later(*) # :nodoc:
|
58
|
+
super unless no_touching?
|
59
|
+
end
|
60
|
+
|
48
61
|
def touch(*) # :nodoc:
|
49
62
|
super unless no_touching?
|
50
63
|
end
|
@@ -1,20 +1,16 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module ActiveRecord
|
4
4
|
module NullRelation # :nodoc:
|
5
|
-
def exec_queries
|
6
|
-
@records = []
|
7
|
-
end
|
8
|
-
|
9
5
|
def pluck(*column_names)
|
10
6
|
[]
|
11
7
|
end
|
12
8
|
|
13
|
-
def delete_all
|
9
|
+
def delete_all
|
14
10
|
0
|
15
11
|
end
|
16
12
|
|
17
|
-
def update_all(_updates
|
13
|
+
def update_all(_updates)
|
18
14
|
0
|
19
15
|
end
|
20
16
|
|
@@ -22,11 +18,11 @@ module ActiveRecord
|
|
22
18
|
0
|
23
19
|
end
|
24
20
|
|
25
|
-
def
|
26
|
-
|
21
|
+
def empty?
|
22
|
+
true
|
27
23
|
end
|
28
24
|
|
29
|
-
def
|
25
|
+
def none?
|
30
26
|
true
|
31
27
|
end
|
32
28
|
|
@@ -34,6 +30,10 @@ module ActiveRecord
|
|
34
30
|
false
|
35
31
|
end
|
36
32
|
|
33
|
+
def one?
|
34
|
+
false
|
35
|
+
end
|
36
|
+
|
37
37
|
def many?
|
38
38
|
false
|
39
39
|
end
|
@@ -42,40 +42,27 @@ module ActiveRecord
|
|
42
42
|
""
|
43
43
|
end
|
44
44
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
45
|
+
def calculate(operation, _column_name)
|
46
|
+
case operation
|
47
|
+
when :count, :sum
|
48
|
+
group_values.any? ? Hash.new : 0
|
49
|
+
when :average, :minimum, :maximum
|
50
|
+
group_values.any? ? Hash.new : nil
|
51
|
+
end
|
51
52
|
end
|
52
53
|
|
53
|
-
def
|
54
|
-
|
54
|
+
def exists?(_conditions = :none)
|
55
|
+
false
|
55
56
|
end
|
56
57
|
|
57
|
-
def
|
58
|
-
|
58
|
+
def or(other)
|
59
|
+
other.spawn
|
59
60
|
end
|
60
61
|
|
61
|
-
|
62
|
-
calculate :maximum, nil
|
63
|
-
end
|
62
|
+
private
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
# activerecord-deprecated_finders.
|
68
|
-
if [:count, :sum, :size].include? operation
|
69
|
-
group_values.any? ? Hash.new : 0
|
70
|
-
elsif [:average, :minimum, :maximum].include?(operation) && group_values.any?
|
71
|
-
Hash.new
|
72
|
-
else
|
73
|
-
nil
|
64
|
+
def exec_queries
|
65
|
+
@records = [].freeze
|
74
66
|
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def exists?(_id = false)
|
78
|
-
false
|
79
|
-
end
|
80
67
|
end
|
81
68
|
end
|
@@ -1,5 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/insert_all"
|
4
|
+
|
1
5
|
module ActiveRecord
|
2
|
-
# = Active Record Persistence
|
6
|
+
# = Active Record \Persistence
|
3
7
|
module Persistence
|
4
8
|
extend ActiveSupport::Concern
|
5
9
|
|
@@ -53,6 +57,192 @@ module ActiveRecord
|
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
60
|
+
# Inserts a single record into the database in a single SQL INSERT
|
61
|
+
# statement. It does not instantiate any models nor does it trigger
|
62
|
+
# Active Record callbacks or validations. Though passed values
|
63
|
+
# go through Active Record's type casting and serialization.
|
64
|
+
#
|
65
|
+
# See <tt>ActiveRecord::Persistence#insert_all</tt> for documentation.
|
66
|
+
def insert(attributes, returning: nil, unique_by: nil)
|
67
|
+
insert_all([ attributes ], returning: returning, unique_by: unique_by)
|
68
|
+
end
|
69
|
+
|
70
|
+
# Inserts multiple records into the database in a single SQL INSERT
|
71
|
+
# statement. It does not instantiate any models nor does it trigger
|
72
|
+
# Active Record callbacks or validations. Though passed values
|
73
|
+
# go through Active Record's type casting and serialization.
|
74
|
+
#
|
75
|
+
# The +attributes+ parameter is an Array of Hashes. Every Hash determines
|
76
|
+
# the attributes for a single row and must have the same keys.
|
77
|
+
#
|
78
|
+
# Rows are considered to be unique by every unique index on the table. Any
|
79
|
+
# duplicate rows are skipped.
|
80
|
+
# Override with <tt>:unique_by</tt> (see below).
|
81
|
+
#
|
82
|
+
# Returns an <tt>ActiveRecord::Result</tt> with its contents based on
|
83
|
+
# <tt>:returning</tt> (see below).
|
84
|
+
#
|
85
|
+
# ==== Options
|
86
|
+
#
|
87
|
+
# [:returning]
|
88
|
+
# (PostgreSQL only) An array of attributes to return for all successfully
|
89
|
+
# inserted records, which by default is the primary key.
|
90
|
+
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
91
|
+
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
92
|
+
# clause entirely.
|
93
|
+
#
|
94
|
+
# [:unique_by]
|
95
|
+
# (PostgreSQL and SQLite only) By default rows are considered to be unique
|
96
|
+
# by every unique index on the table. Any duplicate rows are skipped.
|
97
|
+
#
|
98
|
+
# To skip rows according to just one unique index pass <tt>:unique_by</tt>.
|
99
|
+
#
|
100
|
+
# Consider a Book model where no duplicate ISBNs make sense, but if any
|
101
|
+
# row has an existing id, or is not unique by another unique index,
|
102
|
+
# <tt>ActiveRecord::RecordNotUnique</tt> is raised.
|
103
|
+
#
|
104
|
+
# Unique indexes can be identified by columns or name:
|
105
|
+
#
|
106
|
+
# unique_by: :isbn
|
107
|
+
# unique_by: %i[ author_id name ]
|
108
|
+
# unique_by: :index_books_on_isbn
|
109
|
+
#
|
110
|
+
# Because it relies on the index information from the database
|
111
|
+
# <tt>:unique_by</tt> is recommended to be paired with
|
112
|
+
# Active Record's schema_cache.
|
113
|
+
#
|
114
|
+
# ==== Example
|
115
|
+
#
|
116
|
+
# # Insert records and skip inserting any duplicates.
|
117
|
+
# # Here "Eloquent Ruby" is skipped because its id is not unique.
|
118
|
+
#
|
119
|
+
# Book.insert_all([
|
120
|
+
# { id: 1, title: "Rework", author: "David" },
|
121
|
+
# { id: 1, title: "Eloquent Ruby", author: "Russ" }
|
122
|
+
# ])
|
123
|
+
def insert_all(attributes, returning: nil, unique_by: nil)
|
124
|
+
InsertAll.new(self, attributes, on_duplicate: :skip, returning: returning, unique_by: unique_by).execute
|
125
|
+
end
|
126
|
+
|
127
|
+
# Inserts a single record into the database in a single SQL INSERT
|
128
|
+
# statement. It does not instantiate any models nor does it trigger
|
129
|
+
# Active Record callbacks or validations. Though passed values
|
130
|
+
# go through Active Record's type casting and serialization.
|
131
|
+
#
|
132
|
+
# See <tt>ActiveRecord::Persistence#insert_all!</tt> for more.
|
133
|
+
def insert!(attributes, returning: nil)
|
134
|
+
insert_all!([ attributes ], returning: returning)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Inserts multiple records into the database in a single SQL INSERT
|
138
|
+
# statement. It does not instantiate any models nor does it trigger
|
139
|
+
# Active Record callbacks or validations. Though passed values
|
140
|
+
# go through Active Record's type casting and serialization.
|
141
|
+
#
|
142
|
+
# The +attributes+ parameter is an Array of Hashes. Every Hash determines
|
143
|
+
# the attributes for a single row and must have the same keys.
|
144
|
+
#
|
145
|
+
# Raises <tt>ActiveRecord::RecordNotUnique</tt> if any rows violate a
|
146
|
+
# unique index on the table. In that case, no rows are inserted.
|
147
|
+
#
|
148
|
+
# To skip duplicate rows, see <tt>ActiveRecord::Persistence#insert_all</tt>.
|
149
|
+
# To replace them, see <tt>ActiveRecord::Persistence#upsert_all</tt>.
|
150
|
+
#
|
151
|
+
# Returns an <tt>ActiveRecord::Result</tt> with its contents based on
|
152
|
+
# <tt>:returning</tt> (see below).
|
153
|
+
#
|
154
|
+
# ==== Options
|
155
|
+
#
|
156
|
+
# [:returning]
|
157
|
+
# (PostgreSQL only) An array of attributes to return for all successfully
|
158
|
+
# inserted records, which by default is the primary key.
|
159
|
+
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
160
|
+
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
161
|
+
# clause entirely.
|
162
|
+
#
|
163
|
+
# ==== Examples
|
164
|
+
#
|
165
|
+
# # Insert multiple records
|
166
|
+
# Book.insert_all!([
|
167
|
+
# { title: "Rework", author: "David" },
|
168
|
+
# { title: "Eloquent Ruby", author: "Russ" }
|
169
|
+
# ])
|
170
|
+
#
|
171
|
+
# # Raises ActiveRecord::RecordNotUnique because "Eloquent Ruby"
|
172
|
+
# # does not have a unique id.
|
173
|
+
# Book.insert_all!([
|
174
|
+
# { id: 1, title: "Rework", author: "David" },
|
175
|
+
# { id: 1, title: "Eloquent Ruby", author: "Russ" }
|
176
|
+
# ])
|
177
|
+
def insert_all!(attributes, returning: nil)
|
178
|
+
InsertAll.new(self, attributes, on_duplicate: :raise, returning: returning).execute
|
179
|
+
end
|
180
|
+
|
181
|
+
# Updates or inserts (upserts) a single record into the database in a
|
182
|
+
# single SQL INSERT statement. It does not instantiate any models nor does
|
183
|
+
# it trigger Active Record callbacks or validations. Though passed values
|
184
|
+
# go through Active Record's type casting and serialization.
|
185
|
+
#
|
186
|
+
# See <tt>ActiveRecord::Persistence#upsert_all</tt> for documentation.
|
187
|
+
def upsert(attributes, returning: nil, unique_by: nil)
|
188
|
+
upsert_all([ attributes ], returning: returning, unique_by: unique_by)
|
189
|
+
end
|
190
|
+
|
191
|
+
# Updates or inserts (upserts) multiple records into the database in a
|
192
|
+
# single SQL INSERT statement. It does not instantiate any models nor does
|
193
|
+
# it trigger Active Record callbacks or validations. Though passed values
|
194
|
+
# go through Active Record's type casting and serialization.
|
195
|
+
#
|
196
|
+
# The +attributes+ parameter is an Array of Hashes. Every Hash determines
|
197
|
+
# the attributes for a single row and must have the same keys.
|
198
|
+
#
|
199
|
+
# Returns an <tt>ActiveRecord::Result</tt> with its contents based on
|
200
|
+
# <tt>:returning</tt> (see below).
|
201
|
+
#
|
202
|
+
# ==== Options
|
203
|
+
#
|
204
|
+
# [:returning]
|
205
|
+
# (PostgreSQL only) An array of attributes to return for all successfully
|
206
|
+
# inserted records, which by default is the primary key.
|
207
|
+
# Pass <tt>returning: %w[ id name ]</tt> for both id and name
|
208
|
+
# or <tt>returning: false</tt> to omit the underlying <tt>RETURNING</tt> SQL
|
209
|
+
# clause entirely.
|
210
|
+
#
|
211
|
+
# [:unique_by]
|
212
|
+
# (PostgreSQL and SQLite only) By default rows are considered to be unique
|
213
|
+
# by every unique index on the table. Any duplicate rows are skipped.
|
214
|
+
#
|
215
|
+
# To skip rows according to just one unique index pass <tt>:unique_by</tt>.
|
216
|
+
#
|
217
|
+
# Consider a Book model where no duplicate ISBNs make sense, but if any
|
218
|
+
# row has an existing id, or is not unique by another unique index,
|
219
|
+
# <tt>ActiveRecord::RecordNotUnique</tt> is raised.
|
220
|
+
#
|
221
|
+
# Unique indexes can be identified by columns or name:
|
222
|
+
#
|
223
|
+
# unique_by: :isbn
|
224
|
+
# unique_by: %i[ author_id name ]
|
225
|
+
# unique_by: :index_books_on_isbn
|
226
|
+
#
|
227
|
+
# Because it relies on the index information from the database
|
228
|
+
# <tt>:unique_by</tt> is recommended to be paired with
|
229
|
+
# Active Record's schema_cache.
|
230
|
+
#
|
231
|
+
# ==== Examples
|
232
|
+
#
|
233
|
+
# # Inserts multiple records, performing an upsert when records have duplicate ISBNs.
|
234
|
+
# # Here "Eloquent Ruby" overwrites "Rework" because its ISBN is duplicate.
|
235
|
+
#
|
236
|
+
# Book.upsert_all([
|
237
|
+
# { title: "Rework", author: "David", isbn: "1" },
|
238
|
+
# { title: "Eloquent Ruby", author: "Russ", isbn: "1" }
|
239
|
+
# ], unique_by: :isbn)
|
240
|
+
#
|
241
|
+
# Book.find_by(isbn: "1").title # => "Eloquent Ruby"
|
242
|
+
def upsert_all(attributes, returning: nil, unique_by: nil)
|
243
|
+
InsertAll.new(self, attributes, on_duplicate: :update, returning: returning, unique_by: unique_by).execute
|
244
|
+
end
|
245
|
+
|
56
246
|
# Given an attributes hash, +instantiate+ returns a new instance of
|
57
247
|
# the appropriate class. Accepts only keys as strings.
|
58
248
|
#
|
@@ -61,15 +251,158 @@ module ActiveRecord
|
|
61
251
|
# +instantiate+ instead of +new+, finder methods ensure they get new
|
62
252
|
# instances of the appropriate class for each record.
|
63
253
|
#
|
64
|
-
# See
|
254
|
+
# See <tt>ActiveRecord::Inheritance#discriminate_class_for_record</tt> to see
|
65
255
|
# how this "single-table" inheritance mapping is implemented.
|
66
|
-
def instantiate(attributes, column_types = {})
|
256
|
+
def instantiate(attributes, column_types = {}, &block)
|
67
257
|
klass = discriminate_class_for_record(attributes)
|
68
|
-
|
69
|
-
|
258
|
+
instantiate_instance_of(klass, attributes, column_types, &block)
|
259
|
+
end
|
260
|
+
|
261
|
+
# Updates an object (or multiple objects) and saves it to the database, if validations pass.
|
262
|
+
# The resulting object is returned whether the object was saved successfully to the database or not.
|
263
|
+
#
|
264
|
+
# ==== Parameters
|
265
|
+
#
|
266
|
+
# * +id+ - This should be the id or an array of ids to be updated.
|
267
|
+
# * +attributes+ - This should be a hash of attributes or an array of hashes.
|
268
|
+
#
|
269
|
+
# ==== Examples
|
270
|
+
#
|
271
|
+
# # Updates one record
|
272
|
+
# Person.update(15, user_name: "Samuel", group: "expert")
|
273
|
+
#
|
274
|
+
# # Updates multiple records
|
275
|
+
# people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } }
|
276
|
+
# Person.update(people.keys, people.values)
|
277
|
+
#
|
278
|
+
# # Updates multiple records from the result of a relation
|
279
|
+
# people = Person.where(group: "expert")
|
280
|
+
# people.update(group: "masters")
|
281
|
+
#
|
282
|
+
# Note: Updating a large number of records will run an UPDATE
|
283
|
+
# query for each record, which may cause a performance issue.
|
284
|
+
# When running callbacks is not needed for each record update,
|
285
|
+
# it is preferred to use {update_all}[rdoc-ref:Relation#update_all]
|
286
|
+
# for updating all records in a single query.
|
287
|
+
def update(id = :all, attributes)
|
288
|
+
if id.is_a?(Array)
|
289
|
+
id.map { |one_id| find(one_id) }.each_with_index { |object, idx|
|
290
|
+
object.update(attributes[idx])
|
291
|
+
}
|
292
|
+
elsif id == :all
|
293
|
+
all.each { |record| record.update(attributes) }
|
294
|
+
else
|
295
|
+
if ActiveRecord::Base === id
|
296
|
+
raise ArgumentError,
|
297
|
+
"You are passing an instance of ActiveRecord::Base to `update`. " \
|
298
|
+
"Please pass the id of the object by calling `.id`."
|
299
|
+
end
|
300
|
+
object = find(id)
|
301
|
+
object.update(attributes)
|
302
|
+
object
|
303
|
+
end
|
304
|
+
end
|
305
|
+
|
306
|
+
# Destroy an object (or multiple objects) that has the given id. The object is instantiated first,
|
307
|
+
# therefore all callbacks and filters are fired off before the object is deleted. This method is
|
308
|
+
# less efficient than #delete but allows cleanup methods and other actions to be run.
|
309
|
+
#
|
310
|
+
# This essentially finds the object (or multiple objects) with the given id, creates a new object
|
311
|
+
# from the attributes, and then calls destroy on it.
|
312
|
+
#
|
313
|
+
# ==== Parameters
|
314
|
+
#
|
315
|
+
# * +id+ - This should be the id or an array of ids to be destroyed.
|
316
|
+
#
|
317
|
+
# ==== Examples
|
318
|
+
#
|
319
|
+
# # Destroy a single object
|
320
|
+
# Todo.destroy(1)
|
321
|
+
#
|
322
|
+
# # Destroy multiple objects
|
323
|
+
# todos = [1,2,3]
|
324
|
+
# Todo.destroy(todos)
|
325
|
+
def destroy(id)
|
326
|
+
if id.is_a?(Array)
|
327
|
+
find(id).each(&:destroy)
|
328
|
+
else
|
329
|
+
find(id).destroy
|
330
|
+
end
|
331
|
+
end
|
332
|
+
|
333
|
+
# Deletes the row with a primary key matching the +id+ argument, using an
|
334
|
+
# SQL +DELETE+ statement, and returns the number of rows deleted. Active
|
335
|
+
# Record objects are not instantiated, so the object's callbacks are not
|
336
|
+
# executed, including any <tt>:dependent</tt> association options.
|
337
|
+
#
|
338
|
+
# You can delete multiple rows at once by passing an Array of <tt>id</tt>s.
|
339
|
+
#
|
340
|
+
# Note: Although it is often much faster than the alternative, #destroy,
|
341
|
+
# skipping callbacks might bypass business logic in your application
|
342
|
+
# that ensures referential integrity or performs other essential jobs.
|
343
|
+
#
|
344
|
+
# ==== Examples
|
345
|
+
#
|
346
|
+
# # Delete a single row
|
347
|
+
# Todo.delete(1)
|
348
|
+
#
|
349
|
+
# # Delete multiple rows
|
350
|
+
# Todo.delete([2,3,4])
|
351
|
+
def delete(id_or_array)
|
352
|
+
delete_by(primary_key => id_or_array)
|
353
|
+
end
|
354
|
+
|
355
|
+
def _insert_record(values) # :nodoc:
|
356
|
+
primary_key = self.primary_key
|
357
|
+
primary_key_value = nil
|
358
|
+
|
359
|
+
if primary_key && Hash === values
|
360
|
+
primary_key_value = values[primary_key]
|
361
|
+
|
362
|
+
if !primary_key_value && prefetch_primary_key?
|
363
|
+
primary_key_value = next_sequence_value
|
364
|
+
values[primary_key] = primary_key_value
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
368
|
+
if values.empty?
|
369
|
+
im = arel_table.compile_insert(connection.empty_insert_statement_value(primary_key))
|
370
|
+
im.into arel_table
|
371
|
+
else
|
372
|
+
im = arel_table.compile_insert(_substitute_values(values))
|
373
|
+
end
|
374
|
+
|
375
|
+
connection.insert(im, "#{self} Create", primary_key || false, primary_key_value)
|
376
|
+
end
|
377
|
+
|
378
|
+
def _update_record(values, constraints) # :nodoc:
|
379
|
+
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
380
|
+
|
381
|
+
um = arel_table.where(
|
382
|
+
constraints.reduce(&:and)
|
383
|
+
).compile_update(_substitute_values(values), primary_key)
|
384
|
+
|
385
|
+
connection.update(um, "#{self} Update")
|
386
|
+
end
|
387
|
+
|
388
|
+
def _delete_record(constraints) # :nodoc:
|
389
|
+
constraints = _substitute_values(constraints).map { |attr, bind| attr.eq(bind) }
|
390
|
+
|
391
|
+
dm = Arel::DeleteManager.new
|
392
|
+
dm.from(arel_table)
|
393
|
+
dm.wheres = constraints
|
394
|
+
|
395
|
+
connection.delete(dm, "#{self} Destroy")
|
70
396
|
end
|
71
397
|
|
72
398
|
private
|
399
|
+
# Given a class, an attributes hash, +instantiate_instance_of+ returns a
|
400
|
+
# new instance of the class. Accepts only keys as strings.
|
401
|
+
def instantiate_instance_of(klass, attributes, column_types = {}, &block)
|
402
|
+
attributes = klass.attributes_builder.build_from_database(attributes, column_types)
|
403
|
+
klass.allocate.init_with_attributes(attributes, &block)
|
404
|
+
end
|
405
|
+
|
73
406
|
# Called by +instantiate+ to decide which class to use for a new
|
74
407
|
# record instance.
|
75
408
|
#
|
@@ -78,68 +411,96 @@ module ActiveRecord
|
|
78
411
|
def discriminate_class_for_record(record)
|
79
412
|
self
|
80
413
|
end
|
414
|
+
|
415
|
+
def _substitute_values(values)
|
416
|
+
values.map do |name, value|
|
417
|
+
attr = arel_attribute(name)
|
418
|
+
bind = predicate_builder.build_bind_attribute(name, value)
|
419
|
+
[attr, bind]
|
420
|
+
end
|
421
|
+
end
|
81
422
|
end
|
82
423
|
|
83
424
|
# Returns true if this object hasn't been saved yet -- that is, a record
|
84
425
|
# for the object doesn't exist in the database yet; otherwise, returns false.
|
85
426
|
def new_record?
|
86
|
-
sync_with_transaction_state
|
427
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
87
428
|
@new_record
|
88
429
|
end
|
89
430
|
|
90
431
|
# Returns true if this object has been destroyed, otherwise returns false.
|
91
432
|
def destroyed?
|
92
|
-
sync_with_transaction_state
|
433
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
93
434
|
@destroyed
|
94
435
|
end
|
95
436
|
|
96
437
|
# Returns true if the record is persisted, i.e. it's not a new record and it was
|
97
438
|
# not destroyed, otherwise returns false.
|
98
439
|
def persisted?
|
99
|
-
|
440
|
+
sync_with_transaction_state if @transaction_state&.finalized?
|
441
|
+
!(@new_record || @destroyed)
|
100
442
|
end
|
101
443
|
|
444
|
+
##
|
445
|
+
# :call-seq:
|
446
|
+
# save(*args)
|
447
|
+
#
|
102
448
|
# Saves the model.
|
103
449
|
#
|
104
|
-
# If the model is new a record gets created in the database, otherwise
|
450
|
+
# If the model is new, a record gets created in the database, otherwise
|
105
451
|
# the existing record gets updated.
|
106
452
|
#
|
107
|
-
# By default, save always
|
108
|
-
# is cancelled and
|
109
|
-
# validate: false
|
453
|
+
# By default, save always runs validations. If any of them fail the action
|
454
|
+
# is cancelled and #save returns +false+, and the record won't be saved. However, if you supply
|
455
|
+
# <tt>validate: false</tt>, validations are bypassed altogether. See
|
110
456
|
# ActiveRecord::Validations for more information.
|
111
457
|
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
458
|
+
# By default, #save also sets the +updated_at+/+updated_on+ attributes to
|
459
|
+
# the current time. However, if you supply <tt>touch: false</tt>, these
|
460
|
+
# timestamps will not be updated.
|
461
|
+
#
|
462
|
+
# There's a series of callbacks associated with #save. If any of the
|
463
|
+
# <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled and
|
464
|
+
# #save returns +false+. See ActiveRecord::Callbacks for further
|
115
465
|
# details.
|
116
466
|
#
|
117
467
|
# Attributes marked as readonly are silently ignored if the record is
|
118
468
|
# being updated.
|
119
|
-
def save(*)
|
120
|
-
create_or_update
|
469
|
+
def save(*args, &block)
|
470
|
+
create_or_update(*args, &block)
|
121
471
|
rescue ActiveRecord::RecordInvalid
|
122
472
|
false
|
123
473
|
end
|
124
474
|
|
475
|
+
##
|
476
|
+
# :call-seq:
|
477
|
+
# save!(*args)
|
478
|
+
#
|
125
479
|
# Saves the model.
|
126
480
|
#
|
127
|
-
# If the model is new a record gets created in the database, otherwise
|
481
|
+
# If the model is new, a record gets created in the database, otherwise
|
128
482
|
# the existing record gets updated.
|
129
483
|
#
|
130
|
-
#
|
131
|
-
# ActiveRecord::RecordInvalid gets raised.
|
132
|
-
#
|
484
|
+
# By default, #save! always runs validations. If any of them fail
|
485
|
+
# ActiveRecord::RecordInvalid gets raised, and the record won't be saved. However, if you supply
|
486
|
+
# <tt>validate: false</tt>, validations are bypassed altogether. See
|
487
|
+
# ActiveRecord::Validations for more information.
|
133
488
|
#
|
134
|
-
#
|
135
|
-
# the
|
136
|
-
#
|
489
|
+
# By default, #save! also sets the +updated_at+/+updated_on+ attributes to
|
490
|
+
# the current time. However, if you supply <tt>touch: false</tt>, these
|
491
|
+
# timestamps will not be updated.
|
492
|
+
#
|
493
|
+
# There's a series of callbacks associated with #save!. If any of
|
494
|
+
# the <tt>before_*</tt> callbacks throws +:abort+ the action is cancelled
|
495
|
+
# and #save! raises ActiveRecord::RecordNotSaved. See
|
137
496
|
# ActiveRecord::Callbacks for further details.
|
138
497
|
#
|
139
498
|
# Attributes marked as readonly are silently ignored if the record is
|
140
499
|
# being updated.
|
141
|
-
|
142
|
-
|
500
|
+
#
|
501
|
+
# Unless an error is raised, returns true.
|
502
|
+
def save!(*args, &block)
|
503
|
+
create_or_update(*args, &block) || raise(RecordNotSaved.new("Failed to save the record", self))
|
143
504
|
end
|
144
505
|
|
145
506
|
# Deletes the record in the database and freezes this instance to
|
@@ -149,11 +510,13 @@ module ActiveRecord
|
|
149
510
|
# The row is simply removed with an SQL +DELETE+ statement on the
|
150
511
|
# record's primary key, and no callbacks are executed.
|
151
512
|
#
|
513
|
+
# Note that this will also delete records marked as {#readonly?}[rdoc-ref:Core#readonly?].
|
514
|
+
#
|
152
515
|
# To enforce the object's +before_destroy+ and +after_destroy+
|
153
516
|
# callbacks or any <tt>:dependent</tt> association
|
154
517
|
# options, use <tt>#destroy</tt>.
|
155
518
|
def delete
|
156
|
-
|
519
|
+
_delete_row if persisted?
|
157
520
|
@destroyed = true
|
158
521
|
freeze
|
159
522
|
end
|
@@ -161,15 +524,18 @@ module ActiveRecord
|
|
161
524
|
# Deletes the record in the database and freezes this instance to reflect
|
162
525
|
# that no changes should be made (since they can't be persisted).
|
163
526
|
#
|
164
|
-
# There's a series of callbacks associated with
|
165
|
-
#
|
166
|
-
# and
|
167
|
-
# ActiveRecord::Callbacks for further details.
|
527
|
+
# There's a series of callbacks associated with #destroy. If the
|
528
|
+
# <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
|
529
|
+
# and #destroy returns +false+.
|
530
|
+
# See ActiveRecord::Callbacks for further details.
|
168
531
|
def destroy
|
169
|
-
|
532
|
+
_raise_readonly_record_error if readonly?
|
170
533
|
destroy_associations
|
171
|
-
|
172
|
-
|
534
|
+
@_trigger_destroy_callback = if persisted?
|
535
|
+
destroy_row > 0
|
536
|
+
else
|
537
|
+
true
|
538
|
+
end
|
173
539
|
@destroyed = true
|
174
540
|
freeze
|
175
541
|
end
|
@@ -177,12 +543,12 @@ module ActiveRecord
|
|
177
543
|
# Deletes the record in the database and freezes this instance to reflect
|
178
544
|
# that no changes should be made (since they can't be persisted).
|
179
545
|
#
|
180
|
-
# There's a series of callbacks associated with
|
181
|
-
#
|
182
|
-
# and
|
183
|
-
# ActiveRecord::Callbacks for further details.
|
546
|
+
# There's a series of callbacks associated with #destroy!. If the
|
547
|
+
# <tt>before_destroy</tt> callback throws +:abort+ the action is cancelled
|
548
|
+
# and #destroy! raises ActiveRecord::RecordNotDestroyed.
|
549
|
+
# See ActiveRecord::Callbacks for further details.
|
184
550
|
def destroy!
|
185
|
-
destroy ||
|
551
|
+
destroy || _raise_record_not_destroyed
|
186
552
|
end
|
187
553
|
|
188
554
|
# Returns an instance of the specified +klass+ with the attributes of the
|
@@ -194,19 +560,21 @@ module ActiveRecord
|
|
194
560
|
# instance using the companies/company partial instead of clients/client.
|
195
561
|
#
|
196
562
|
# Note: The new instance will share a link to the same attributes as the original class.
|
197
|
-
#
|
563
|
+
# Therefore the sti column value will still be the same.
|
564
|
+
# Any change to the attributes on either instance will affect both instances.
|
565
|
+
# If you want to change the sti column as well, use #becomes! instead.
|
198
566
|
def becomes(klass)
|
199
|
-
became = klass.
|
567
|
+
became = klass.allocate
|
568
|
+
became.send(:initialize)
|
200
569
|
became.instance_variable_set("@attributes", @attributes)
|
201
|
-
|
202
|
-
became.instance_variable_set("@changed_attributes", changed_attributes || {})
|
570
|
+
became.instance_variable_set("@mutations_from_database", @mutations_from_database ||= nil)
|
203
571
|
became.instance_variable_set("@new_record", new_record?)
|
204
572
|
became.instance_variable_set("@destroyed", destroyed?)
|
205
|
-
became.
|
573
|
+
became.errors.copy!(errors)
|
206
574
|
became
|
207
575
|
end
|
208
576
|
|
209
|
-
# Wrapper around
|
577
|
+
# Wrapper around #becomes that also changes the instance's sti column value.
|
210
578
|
# This is especially useful if you want to persist the changed class in your
|
211
579
|
# database.
|
212
580
|
#
|
@@ -226,18 +594,19 @@ module ActiveRecord
|
|
226
594
|
# This is especially useful for boolean flags on existing records. Also note that
|
227
595
|
#
|
228
596
|
# * Validation is skipped.
|
229
|
-
# * Callbacks are invoked.
|
597
|
+
# * \Callbacks are invoked.
|
230
598
|
# * updated_at/updated_on column is updated if that column is available.
|
231
599
|
# * Updates all the attributes that are dirty in this object.
|
232
600
|
#
|
233
|
-
# This method raises an
|
601
|
+
# This method raises an ActiveRecord::ActiveRecordError if the
|
234
602
|
# attribute is marked as readonly.
|
235
603
|
#
|
236
|
-
#
|
604
|
+
# Also see #update_column.
|
237
605
|
def update_attribute(name, value)
|
238
606
|
name = name.to_s
|
239
607
|
verify_readonly_attribute(name)
|
240
|
-
|
608
|
+
public_send("#{name}=", value)
|
609
|
+
|
241
610
|
save(validate: false)
|
242
611
|
end
|
243
612
|
|
@@ -254,9 +623,10 @@ module ActiveRecord
|
|
254
623
|
end
|
255
624
|
|
256
625
|
alias update_attributes update
|
626
|
+
deprecate update_attributes: "please, use update instead"
|
257
627
|
|
258
|
-
# Updates its receiver just like
|
259
|
-
# of +save+, so an exception is raised if the record is invalid.
|
628
|
+
# Updates its receiver just like #update but calls #save! instead
|
629
|
+
# of +save+, so an exception is raised if the record is invalid and saving will fail.
|
260
630
|
def update!(attributes)
|
261
631
|
# The following transaction covers any possible database side-effects of the
|
262
632
|
# attributes assignment. For example, setting the IDs of a child collection.
|
@@ -267,6 +637,7 @@ module ActiveRecord
|
|
267
637
|
end
|
268
638
|
|
269
639
|
alias update_attributes! update!
|
640
|
+
deprecate update_attributes!: "please, use update! instead"
|
270
641
|
|
271
642
|
# Equivalent to <code>update_columns(name => value)</code>.
|
272
643
|
def update_column(name, value)
|
@@ -282,27 +653,37 @@ module ActiveRecord
|
|
282
653
|
# the database, but take into account that in consequence the regular update
|
283
654
|
# procedures are totally bypassed. In particular:
|
284
655
|
#
|
285
|
-
# * Validations are skipped.
|
286
|
-
# * Callbacks are skipped.
|
656
|
+
# * \Validations are skipped.
|
657
|
+
# * \Callbacks are skipped.
|
287
658
|
# * +updated_at+/+updated_on+ are not updated.
|
659
|
+
# * However, attributes are serialized with the same rules as ActiveRecord::Relation#update_all
|
288
660
|
#
|
289
|
-
# This method raises an
|
661
|
+
# This method raises an ActiveRecord::ActiveRecordError when called on new
|
290
662
|
# objects, or when at least one of the attributes is marked as readonly.
|
291
663
|
def update_columns(attributes)
|
292
664
|
raise ActiveRecordError, "cannot update a new record" if new_record?
|
293
665
|
raise ActiveRecordError, "cannot update a destroyed record" if destroyed?
|
294
666
|
|
295
|
-
attributes.
|
296
|
-
|
667
|
+
attributes = attributes.transform_keys do |key|
|
668
|
+
name = key.to_s
|
669
|
+
self.class.attribute_aliases[name] || name
|
297
670
|
end
|
298
671
|
|
299
|
-
|
672
|
+
attributes.each_key do |key|
|
673
|
+
verify_readonly_attribute(key)
|
674
|
+
end
|
300
675
|
|
676
|
+
id_in_database = self.id_in_database
|
301
677
|
attributes.each do |k, v|
|
302
|
-
|
678
|
+
write_attribute_without_type_cast(k, v)
|
303
679
|
end
|
304
680
|
|
305
|
-
|
681
|
+
affected_rows = self.class._update_record(
|
682
|
+
attributes,
|
683
|
+
@primary_key => id_in_database
|
684
|
+
)
|
685
|
+
|
686
|
+
affected_rows == 1
|
306
687
|
end
|
307
688
|
|
308
689
|
# Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1).
|
@@ -314,42 +695,56 @@ module ActiveRecord
|
|
314
695
|
self
|
315
696
|
end
|
316
697
|
|
317
|
-
# Wrapper around
|
318
|
-
#
|
319
|
-
#
|
320
|
-
#
|
321
|
-
|
322
|
-
|
698
|
+
# Wrapper around #increment that writes the update to the database.
|
699
|
+
# Only +attribute+ is updated; the record itself is not saved.
|
700
|
+
# This means that any other modified attributes will still be dirty.
|
701
|
+
# Validations and callbacks are skipped. Supports the +touch+ option from
|
702
|
+
# +update_counters+, see that for more.
|
703
|
+
# Returns +self+.
|
704
|
+
def increment!(attribute, by = 1, touch: nil)
|
705
|
+
increment(attribute, by)
|
706
|
+
change = public_send(attribute) - (attribute_in_database(attribute.to_s) || 0)
|
707
|
+
self.class.update_counters(id, attribute => change, touch: touch)
|
708
|
+
clear_attribute_change(attribute) # eww
|
709
|
+
self
|
323
710
|
end
|
324
711
|
|
325
712
|
# Initializes +attribute+ to zero if +nil+ and subtracts the value passed as +by+ (default is 1).
|
326
713
|
# The decrement is performed directly on the underlying attribute, no setter is invoked.
|
327
714
|
# Only makes sense for number-based attributes. Returns +self+.
|
328
715
|
def decrement(attribute, by = 1)
|
329
|
-
|
330
|
-
self[attribute] -= by
|
331
|
-
self
|
716
|
+
increment(attribute, -by)
|
332
717
|
end
|
333
718
|
|
334
|
-
# Wrapper around
|
335
|
-
#
|
336
|
-
#
|
337
|
-
#
|
338
|
-
|
339
|
-
|
719
|
+
# Wrapper around #decrement that writes the update to the database.
|
720
|
+
# Only +attribute+ is updated; the record itself is not saved.
|
721
|
+
# This means that any other modified attributes will still be dirty.
|
722
|
+
# Validations and callbacks are skipped. Supports the +touch+ option from
|
723
|
+
# +update_counters+, see that for more.
|
724
|
+
# Returns +self+.
|
725
|
+
def decrement!(attribute, by = 1, touch: nil)
|
726
|
+
increment!(attribute, -by, touch: touch)
|
340
727
|
end
|
341
728
|
|
342
729
|
# Assigns to +attribute+ the boolean opposite of <tt>attribute?</tt>. So
|
343
730
|
# if the predicate returns +true+ the attribute will become +false+. This
|
344
731
|
# method toggles directly the underlying value without calling any setter.
|
345
732
|
# Returns +self+.
|
733
|
+
#
|
734
|
+
# Example:
|
735
|
+
#
|
736
|
+
# user = User.first
|
737
|
+
# user.banned? # => false
|
738
|
+
# user.toggle(:banned)
|
739
|
+
# user.banned? # => true
|
740
|
+
#
|
346
741
|
def toggle(attribute)
|
347
|
-
self[attribute] = !
|
742
|
+
self[attribute] = !public_send("#{attribute}?")
|
348
743
|
self
|
349
744
|
end
|
350
745
|
|
351
|
-
# Wrapper around
|
352
|
-
# its non-bang version in that it passes through the attribute setter.
|
746
|
+
# Wrapper around #toggle that saves the record. This method differs from
|
747
|
+
# its non-bang version in the sense that it passes through the attribute setter.
|
353
748
|
# Saving is not subjected to validation checks. Returns +true+ if the
|
354
749
|
# record could be saved.
|
355
750
|
def toggle!(attribute)
|
@@ -358,8 +753,8 @@ module ActiveRecord
|
|
358
753
|
|
359
754
|
# Reloads the record from the database.
|
360
755
|
#
|
361
|
-
# This method finds record by its primary key (which could be assigned
|
362
|
-
# modifies the receiver in-place:
|
756
|
+
# This method finds the record by its primary key (which could be assigned
|
757
|
+
# manually) and modifies the receiver in-place:
|
363
758
|
#
|
364
759
|
# account = Account.new
|
365
760
|
# # => #<Account id: nil, email: nil>
|
@@ -371,7 +766,7 @@ module ActiveRecord
|
|
371
766
|
# Attributes are reloaded from the database, and caches busted, in
|
372
767
|
# particular the associations cache and the QueryCache.
|
373
768
|
#
|
374
|
-
# If the record no longer exists in the database
|
769
|
+
# If the record no longer exists in the database ActiveRecord::RecordNotFound
|
375
770
|
# is raised. Otherwise, in addition to the in-place modification the method
|
376
771
|
# returns +self+ for convenience.
|
377
772
|
#
|
@@ -405,8 +800,6 @@ module ActiveRecord
|
|
405
800
|
# end
|
406
801
|
#
|
407
802
|
def reload(options = nil)
|
408
|
-
clear_aggregation_cache
|
409
|
-
clear_association_cache
|
410
803
|
self.class.connection.clear_query_cache
|
411
804
|
|
412
805
|
fresh_object =
|
@@ -416,24 +809,27 @@ module ActiveRecord
|
|
416
809
|
self.class.unscoped { self.class.find(id) }
|
417
810
|
end
|
418
811
|
|
419
|
-
@attributes = fresh_object.instance_variable_get(
|
812
|
+
@attributes = fresh_object.instance_variable_get("@attributes")
|
420
813
|
@new_record = false
|
421
814
|
self
|
422
815
|
end
|
423
816
|
|
424
|
-
# Saves the record with the updated_at/on attributes set to the current time
|
817
|
+
# Saves the record with the updated_at/on attributes set to the current time
|
818
|
+
# or the time specified.
|
425
819
|
# Please note that no validation is performed and only the +after_touch+,
|
426
820
|
# +after_commit+ and +after_rollback+ callbacks are executed.
|
427
821
|
#
|
822
|
+
# This method can be passed attribute names and an optional time argument.
|
428
823
|
# If attribute names are passed, they are updated along with updated_at/on
|
429
|
-
# attributes.
|
824
|
+
# attributes. If no time argument is passed, the current time is used as default.
|
430
825
|
#
|
431
|
-
# product.touch # updates updated_at/on
|
826
|
+
# product.touch # updates updated_at/on with current time
|
827
|
+
# product.touch(time: Time.new(2015, 2, 16, 0, 0, 0)) # updates updated_at/on with specified time
|
432
828
|
# product.touch(:designed_at) # updates the designed_at attribute and updated_at/on
|
433
829
|
# product.touch(:started_at, :ended_at) # updates started_at, ended_at and updated_at/on attributes
|
434
830
|
#
|
435
|
-
# If used along with
|
436
|
-
# associated object.
|
831
|
+
# If used along with {belongs_to}[rdoc-ref:Associations::ClassMethods#belongs_to]
|
832
|
+
# then +touch+ will invoke +touch+ method on associated object.
|
437
833
|
#
|
438
834
|
# class Brake < ActiveRecord::Base
|
439
835
|
# belongs_to :car, touch: true
|
@@ -452,26 +848,22 @@ module ActiveRecord
|
|
452
848
|
# ball = Ball.new
|
453
849
|
# ball.touch(:updated_at) # => raises ActiveRecordError
|
454
850
|
#
|
455
|
-
def touch(*names)
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
current_time = current_time_from_proper_timezone
|
463
|
-
changes = {}
|
464
|
-
|
465
|
-
attributes.each do |column|
|
466
|
-
column = column.to_s
|
467
|
-
changes[column] = write_attribute(column, current_time)
|
468
|
-
end
|
851
|
+
def touch(*names, time: nil)
|
852
|
+
unless persisted?
|
853
|
+
raise ActiveRecordError, <<-MSG.squish
|
854
|
+
cannot touch on a new or destroyed record object. Consider using
|
855
|
+
persisted?, new_record?, or destroyed? before touching
|
856
|
+
MSG
|
857
|
+
end
|
469
858
|
|
470
|
-
|
859
|
+
attribute_names = timestamp_attributes_for_update_in_model
|
860
|
+
attribute_names |= names.map!(&:to_s).map! { |name|
|
861
|
+
self.class.attribute_aliases[name] || name
|
862
|
+
}
|
471
863
|
|
472
|
-
|
473
|
-
|
474
|
-
|
864
|
+
unless attribute_names.empty?
|
865
|
+
affected_rows = _touch_row(attribute_names, time)
|
866
|
+
@_trigger_update_callback = affected_rows == 1
|
475
867
|
else
|
476
868
|
true
|
477
869
|
end
|
@@ -484,52 +876,92 @@ module ActiveRecord
|
|
484
876
|
end
|
485
877
|
|
486
878
|
def destroy_row
|
487
|
-
|
879
|
+
_delete_row
|
880
|
+
end
|
881
|
+
|
882
|
+
def _delete_row
|
883
|
+
self.class._delete_record(@primary_key => id_in_database)
|
488
884
|
end
|
489
885
|
|
490
|
-
def
|
491
|
-
|
492
|
-
column = self.class.columns_hash[pk]
|
493
|
-
substitute = self.class.connection.substitute_at(column)
|
886
|
+
def _touch_row(attribute_names, time)
|
887
|
+
time ||= current_time_from_proper_timezone
|
494
888
|
|
495
|
-
|
496
|
-
|
889
|
+
attribute_names.each do |attr_name|
|
890
|
+
_write_attribute(attr_name, time)
|
891
|
+
end
|
892
|
+
|
893
|
+
_update_row(attribute_names, "touch")
|
894
|
+
end
|
497
895
|
|
498
|
-
|
499
|
-
|
896
|
+
def _update_row(attribute_names, attempted_action = "update")
|
897
|
+
self.class._update_record(
|
898
|
+
attributes_with_values(attribute_names),
|
899
|
+
@primary_key => id_in_database
|
900
|
+
)
|
500
901
|
end
|
501
902
|
|
502
|
-
def create_or_update
|
503
|
-
|
504
|
-
|
903
|
+
def create_or_update(**, &block)
|
904
|
+
_raise_readonly_record_error if readonly?
|
905
|
+
return false if destroyed?
|
906
|
+
result = new_record? ? _create_record(&block) : _update_record(&block)
|
505
907
|
result != false
|
506
908
|
end
|
507
909
|
|
508
910
|
# Updates the associated record with values matching those of the instance attributes.
|
509
911
|
# Returns the number of affected rows.
|
510
912
|
def _update_record(attribute_names = self.attribute_names)
|
511
|
-
|
512
|
-
|
513
|
-
|
913
|
+
attribute_names = attributes_for_update(attribute_names)
|
914
|
+
|
915
|
+
if attribute_names.empty?
|
916
|
+
affected_rows = 0
|
917
|
+
@_trigger_update_callback = true
|
514
918
|
else
|
515
|
-
|
919
|
+
affected_rows = _update_row(attribute_names)
|
920
|
+
@_trigger_update_callback = affected_rows == 1
|
516
921
|
end
|
922
|
+
|
923
|
+
yield(self) if block_given?
|
924
|
+
|
925
|
+
affected_rows
|
517
926
|
end
|
518
927
|
|
519
928
|
# Creates a record with values matching those of the instance attributes
|
520
929
|
# and returns its id.
|
521
930
|
def _create_record(attribute_names = self.attribute_names)
|
522
|
-
|
931
|
+
attribute_names = attributes_for_create(attribute_names)
|
932
|
+
|
933
|
+
new_id = self.class._insert_record(
|
934
|
+
attributes_with_values(attribute_names)
|
935
|
+
)
|
523
936
|
|
524
|
-
new_id
|
525
|
-
self.id ||= new_id if self.class.primary_key
|
937
|
+
self.id ||= new_id if @primary_key
|
526
938
|
|
527
939
|
@new_record = false
|
940
|
+
|
941
|
+
yield(self) if block_given?
|
942
|
+
|
528
943
|
id
|
529
944
|
end
|
530
945
|
|
531
946
|
def verify_readonly_attribute(name)
|
532
947
|
raise ActiveRecordError, "#{name} is marked as readonly" if self.class.readonly_attributes.include?(name)
|
533
948
|
end
|
949
|
+
|
950
|
+
def _raise_record_not_destroyed
|
951
|
+
@_association_destroy_exception ||= nil
|
952
|
+
raise @_association_destroy_exception || RecordNotDestroyed.new("Failed to destroy the record", self)
|
953
|
+
ensure
|
954
|
+
@_association_destroy_exception = nil
|
955
|
+
end
|
956
|
+
|
957
|
+
# The name of the method used to touch a +belongs_to+ association when the
|
958
|
+
# +:touch+ option is used.
|
959
|
+
def belongs_to_touch_method
|
960
|
+
:touch
|
961
|
+
end
|
962
|
+
|
963
|
+
def _raise_readonly_record_error
|
964
|
+
raise ReadOnlyRecord, "#{self.class} is marked as readonly"
|
965
|
+
end
|
534
966
|
end
|
535
967
|
end
|