activerecord 3.2.6 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/CHANGELOG.md +611 -6417
- data/MIT-LICENSE +4 -2
- data/README.rdoc +44 -47
- data/examples/performance.rb +79 -71
- data/examples/simple.rb +6 -5
- data/lib/active_record/aggregations.rb +268 -238
- data/lib/active_record/association_relation.rb +40 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -42
- data/lib/active_record/associations/association.rb +173 -81
- data/lib/active_record/associations/association_scope.rb +124 -92
- data/lib/active_record/associations/belongs_to_association.rb +83 -38
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +11 -9
- data/lib/active_record/associations/builder/association.rb +113 -32
- data/lib/active_record/associations/builder/belongs_to.rb +105 -60
- data/lib/active_record/associations/builder/collection_association.rb +53 -56
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +98 -41
- data/lib/active_record/associations/builder/has_many.rb +11 -63
- data/lib/active_record/associations/builder/has_one.rb +47 -45
- data/lib/active_record/associations/builder/singular_association.rb +30 -18
- data/lib/active_record/associations/collection_association.rb +217 -295
- data/lib/active_record/associations/collection_proxy.rb +1074 -77
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +78 -50
- data/lib/active_record/associations/has_many_through_association.rb +99 -61
- data/lib/active_record/associations/has_one_association.rb +75 -30
- data/lib/active_record/associations/has_one_through_association.rb +20 -11
- data/lib/active_record/associations/join_dependency/join_association.rb +45 -119
- data/lib/active_record/associations/join_dependency/join_base.rb +11 -12
- data/lib/active_record/associations/join_dependency/join_part.rb +35 -42
- data/lib/active_record/associations/join_dependency.rb +208 -164
- data/lib/active_record/associations/preloader/association.rb +93 -87
- data/lib/active_record/associations/preloader/through_association.rb +87 -38
- data/lib/active_record/associations/preloader.rb +134 -110
- data/lib/active_record/associations/singular_association.rb +19 -24
- data/lib/active_record/associations/through_association.rb +61 -27
- data/lib/active_record/associations.rb +1766 -1505
- data/lib/active_record/attribute_assignment.rb +57 -193
- data/lib/active_record/attribute_decorators.rb +90 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +58 -8
- data/lib/active_record/attribute_methods/dirty.rb +187 -67
- data/lib/active_record/attribute_methods/primary_key.rb +100 -78
- data/lib/active_record/attribute_methods/query.rb +10 -8
- data/lib/active_record/attribute_methods/read.rb +29 -118
- data/lib/active_record/attribute_methods/serialization.rb +60 -72
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +69 -42
- data/lib/active_record/attribute_methods/write.rb +36 -44
- data/lib/active_record/attribute_methods.rb +306 -161
- data/lib/active_record/attributes.rb +279 -0
- data/lib/active_record/autosave_association.rb +324 -238
- data/lib/active_record/base.rb +114 -507
- data/lib/active_record/callbacks.rb +147 -83
- data/lib/active_record/coders/json.rb +15 -0
- data/lib/active_record/coders/yaml_column.rb +32 -23
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +962 -279
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +32 -5
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +331 -209
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +95 -23
- data/lib/active_record/connection_adapters/abstract/quoting.rb +201 -65
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +23 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +510 -289
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +93 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1182 -313
- data/lib/active_record/connection_adapters/abstract/transaction.rb +323 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +585 -120
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +610 -463
- data/lib/active_record/connection_adapters/column.rb +58 -233
- data/lib/active_record/connection_adapters/connection_specification.rb +297 -0
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +29 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +27 -0
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +200 -0
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/quoting.rb +81 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +72 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +95 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +88 -0
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +264 -0
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +31 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +75 -207
- data/lib/active_record/connection_adapters/postgresql/column.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +182 -0
- data/lib/active_record/connection_adapters/postgresql/explain_pretty_printer.rb +44 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +92 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +53 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +17 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +71 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +45 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +41 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +65 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +97 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +18 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +113 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +34 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +205 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +76 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +222 -0
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +776 -0
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +81 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +695 -1052
- data/lib/active_record/connection_adapters/schema_cache.rb +115 -24
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +118 -0
- data/lib/active_record/connection_adapters/sqlite3/explain_pretty_printer.rb +21 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +103 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +17 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_definitions.rb +19 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_dumper.rb +18 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +137 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +528 -26
- data/lib/active_record/connection_adapters/statement_pool.rb +34 -13
- data/lib/active_record/connection_handling.rb +267 -0
- data/lib/active_record/core.rb +599 -0
- data/lib/active_record/counter_cache.rb +177 -103
- data/lib/active_record/database_configurations/database_config.rb +37 -0
- data/lib/active_record/database_configurations/hash_config.rb +50 -0
- data/lib/active_record/database_configurations/url_config.rb +79 -0
- data/lib/active_record/database_configurations.rb +233 -0
- data/lib/active_record/define_callbacks.rb +22 -0
- data/lib/active_record/dynamic_matchers.rb +107 -64
- data/lib/active_record/enum.rb +274 -0
- data/lib/active_record/errors.rb +254 -61
- data/lib/active_record/explain.rb +35 -70
- data/lib/active_record/explain_registry.rb +32 -0
- data/lib/active_record/explain_subscriber.rb +18 -8
- data/lib/active_record/fixture_set/file.rb +82 -0
- data/lib/active_record/fixture_set/model_metadata.rb +33 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +153 -0
- data/lib/active_record/fixture_set/table_rows.rb +47 -0
- data/lib/active_record/fixtures.rb +291 -475
- data/lib/active_record/gem_version.rb +17 -0
- data/lib/active_record/inheritance.rb +219 -100
- data/lib/active_record/insert_all.rb +179 -0
- data/lib/active_record/integration.rb +175 -17
- data/lib/active_record/internal_metadata.rb +53 -0
- data/lib/active_record/legacy_yaml_adapter.rb +48 -0
- data/lib/active_record/locale/en.yml +9 -1
- data/lib/active_record/locking/optimistic.rb +106 -92
- data/lib/active_record/locking/pessimistic.rb +23 -11
- data/lib/active_record/log_subscriber.rb +80 -30
- data/lib/active_record/middleware/database_selector/resolver/session.rb +45 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +75 -0
- data/lib/active_record/migration/command_recorder.rb +235 -56
- data/lib/active_record/migration/compatibility.rb +244 -0
- data/lib/active_record/migration/join_table.rb +17 -0
- data/lib/active_record/migration.rb +917 -301
- data/lib/active_record/model_schema.rb +351 -175
- data/lib/active_record/nested_attributes.rb +366 -235
- data/lib/active_record/no_touching.rb +65 -0
- data/lib/active_record/null_relation.rb +68 -0
- data/lib/active_record/persistence.rb +761 -166
- data/lib/active_record/query_cache.rb +22 -44
- data/lib/active_record/querying.rb +55 -31
- data/lib/active_record/railtie.rb +185 -47
- data/lib/active_record/railties/collection_cache_association_loading.rb +34 -0
- data/lib/active_record/railties/console_sandbox.rb +5 -4
- data/lib/active_record/railties/controller_runtime.rb +35 -33
- data/lib/active_record/railties/databases.rake +366 -463
- data/lib/active_record/readonly_attributes.rb +4 -6
- data/lib/active_record/reflection.rb +736 -228
- data/lib/active_record/relation/batches/batch_enumerator.rb +69 -0
- data/lib/active_record/relation/batches.rb +252 -52
- data/lib/active_record/relation/calculations.rb +340 -270
- data/lib/active_record/relation/delegation.rb +117 -36
- data/lib/active_record/relation/finder_methods.rb +439 -286
- data/lib/active_record/relation/from_clause.rb +26 -0
- data/lib/active_record/relation/merger.rb +184 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +49 -0
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +43 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +18 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +53 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +22 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +19 -0
- data/lib/active_record/relation/predicate_builder.rb +131 -39
- data/lib/active_record/relation/query_attribute.rb +50 -0
- data/lib/active_record/relation/query_methods.rb +1163 -221
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +49 -120
- data/lib/active_record/relation/where_clause.rb +190 -0
- data/lib/active_record/relation/where_clause_factory.rb +33 -0
- data/lib/active_record/relation.rb +671 -349
- data/lib/active_record/result.rb +149 -15
- data/lib/active_record/runtime_registry.rb +24 -0
- data/lib/active_record/sanitization.rb +153 -133
- data/lib/active_record/schema.rb +22 -19
- data/lib/active_record/schema_dumper.rb +178 -112
- data/lib/active_record/schema_migration.rb +60 -0
- data/lib/active_record/scoping/default.rb +107 -98
- data/lib/active_record/scoping/named.rb +130 -115
- data/lib/active_record/scoping.rb +77 -123
- data/lib/active_record/secure_token.rb +40 -0
- data/lib/active_record/serialization.rb +10 -6
- data/lib/active_record/statement_cache.rb +148 -0
- data/lib/active_record/store.rb +256 -16
- data/lib/active_record/suppressor.rb +61 -0
- data/lib/active_record/table_metadata.rb +75 -0
- data/lib/active_record/tasks/database_tasks.rb +506 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +115 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +141 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +77 -0
- data/lib/active_record/test_databases.rb +23 -0
- data/lib/active_record/test_fixtures.rb +224 -0
- data/lib/active_record/timestamp.rb +93 -39
- data/lib/active_record/touch_later.rb +66 -0
- data/lib/active_record/transactions.rb +260 -129
- data/lib/active_record/translation.rb +3 -1
- data/lib/active_record/type/adapter_specific_registry.rb +129 -0
- data/lib/active_record/type/date.rb +9 -0
- data/lib/active_record/type/date_time.rb +9 -0
- data/lib/active_record/type/decimal_without_scale.rb +15 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +25 -0
- data/lib/active_record/type/internal/timezone.rb +17 -0
- data/lib/active_record/type/json.rb +30 -0
- data/lib/active_record/type/serialized.rb +71 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +21 -0
- data/lib/active_record/type/type_map.rb +62 -0
- data/lib/active_record/type/unsigned_integer.rb +17 -0
- data/lib/active_record/type.rb +78 -0
- data/lib/active_record/type_caster/connection.rb +34 -0
- data/lib/active_record/type_caster/map.rb +20 -0
- data/lib/active_record/type_caster.rb +9 -0
- data/lib/active_record/validations/absence.rb +25 -0
- data/lib/active_record/validations/associated.rb +35 -18
- data/lib/active_record/validations/length.rb +26 -0
- data/lib/active_record/validations/presence.rb +68 -0
- data/lib/active_record/validations/uniqueness.rb +123 -77
- data/lib/active_record/validations.rb +54 -43
- data/lib/active_record/version.rb +7 -7
- data/lib/active_record.rb +97 -49
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +37 -0
- data/lib/arel/attributes.rb +22 -0
- data/lib/arel/collectors/bind.rb +24 -0
- data/lib/arel/collectors/composite.rb +31 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +20 -0
- data/lib/arel/collectors/substitute_binds.rb +28 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +52 -0
- data/lib/arel/nodes/bind_param.rb +36 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +50 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +18 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +8 -0
- data/lib/arel/nodes/in.rb +8 -0
- data/lib/arel/nodes/infix_operation.rb +80 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +50 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +16 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +27 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +45 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +68 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +257 -0
- data/lib/arel/select_manager.rb +271 -0
- data/lib/arel/table.rb +110 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/depth_first.rb +204 -0
- data/lib/arel/visitors/dot.rb +297 -0
- data/lib/arel/visitors/ibm_db.rb +34 -0
- data/lib/arel/visitors/informix.rb +62 -0
- data/lib/arel/visitors/mssql.rb +157 -0
- data/lib/arel/visitors/mysql.rb +83 -0
- data/lib/arel/visitors/oracle.rb +159 -0
- data/lib/arel/visitors/oracle12.rb +66 -0
- data/lib/arel/visitors/postgresql.rb +110 -0
- data/lib/arel/visitors/sqlite.rb +39 -0
- data/lib/arel/visitors/to_sql.rb +889 -0
- data/lib/arel/visitors/visitor.rb +46 -0
- data/lib/arel/visitors/where_sql.rb +23 -0
- data/lib/arel/visitors.rb +20 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +51 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +27 -0
- data/lib/rails/generators/active_record/application_record/templates/application_record.rb.tt +5 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +59 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +24 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +48 -0
- data/lib/rails/generators/active_record/migration.rb +41 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +24 -22
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +22 -0
- data/lib/rails/generators/active_record/model/templates/{module.rb → module.rb.tt} +1 -1
- data/lib/rails/generators/active_record.rb +10 -16
- metadata +285 -149
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- data/lib/active_record/associations/preloader/belongs_to.rb +0 -17
- data/lib/active_record/associations/preloader/collection_association.rb +0 -24
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- data/lib/active_record/associations/preloader/has_many.rb +0 -17
- data/lib/active_record/associations/preloader/has_many_through.rb +0 -15
- data/lib/active_record/associations/preloader/has_one.rb +0 -23
- data/lib/active_record/associations/preloader/has_one_through.rb +0 -9
- data/lib/active_record/associations/preloader/singular_association.rb +0 -21
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -188
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -426
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -579
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/railties/jdbcmysql_error.rb +0 -16
- data/lib/active_record/serializers/xml_serializer.rb +0 -203
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -73
- data/lib/rails/generators/active_record/migration/templates/migration.rb +0 -34
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +0 -12
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,36 +1,30 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "yaml"
|
5
|
+
require "zlib"
|
6
|
+
require "set"
|
7
|
+
require "active_support/dependencies"
|
8
|
+
require "active_support/core_ext/digest/uuid"
|
9
|
+
require "active_record/fixture_set/file"
|
10
|
+
require "active_record/fixture_set/render_context"
|
11
|
+
require "active_record/fixture_set/table_rows"
|
12
|
+
require "active_record/test_fixtures"
|
13
|
+
require "active_record/errors"
|
2
14
|
|
3
|
-
|
4
|
-
require 'psych'
|
5
|
-
rescue LoadError
|
6
|
-
end
|
7
|
-
|
8
|
-
require 'yaml'
|
9
|
-
require 'zlib'
|
10
|
-
require 'active_support/dependencies'
|
11
|
-
require 'active_support/core_ext/array/wrap'
|
12
|
-
require 'active_support/core_ext/object/blank'
|
13
|
-
require 'active_support/core_ext/logger'
|
14
|
-
require 'active_support/ordered_hash'
|
15
|
-
require 'active_record/fixtures/file'
|
16
|
-
|
17
|
-
if defined? ActiveRecord
|
15
|
+
module ActiveRecord
|
18
16
|
class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
|
19
17
|
end
|
20
|
-
else
|
21
|
-
class FixtureClassNotFound < StandardError #:nodoc:
|
22
|
-
end
|
23
|
-
end
|
24
18
|
|
25
|
-
module ActiveRecord
|
26
19
|
# \Fixtures are a way of organizing data that you want to test against; in short, sample data.
|
27
20
|
#
|
28
21
|
# They are stored in YAML files, one file per model, which are placed in the directory
|
29
22
|
# appointed by <tt>ActiveSupport::TestCase.fixture_path=(path)</tt> (this is automatically
|
30
23
|
# configured for Rails, so you can just put your files in <tt><your-rails-app>/test/fixtures/</tt>).
|
31
|
-
# The fixture file ends with the
|
32
|
-
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
|
33
|
-
#
|
24
|
+
# The fixture file ends with the +.yml+ file extension, for example:
|
25
|
+
# <tt><your-rails-app>/test/fixtures/web_sites.yml</tt>).
|
26
|
+
#
|
27
|
+
# The format of a fixture file looks like this:
|
34
28
|
#
|
35
29
|
# rubyonrails:
|
36
30
|
# id: 1
|
@@ -46,7 +40,7 @@ module ActiveRecord
|
|
46
40
|
# is followed by an indented list of key/value pairs in the "key: value" format. Records are
|
47
41
|
# separated by a blank line for your viewing pleasure.
|
48
42
|
#
|
49
|
-
# Note
|
43
|
+
# Note: Fixtures are unordered. If you want ordered fixtures, use the omap YAML type.
|
50
44
|
# See http://yaml.org/type/omap.html
|
51
45
|
# for the specification. You will need ordered fixtures when you have foreign key constraints
|
52
46
|
# on keys in the same table. This is commonly needed for tree structures. Example:
|
@@ -74,20 +68,39 @@ module ActiveRecord
|
|
74
68
|
# end
|
75
69
|
# end
|
76
70
|
#
|
77
|
-
# By default,
|
78
|
-
# so this test will succeed.
|
71
|
+
# By default, +test_helper.rb+ will load all of your fixtures into your test
|
72
|
+
# database, so this test will succeed.
|
79
73
|
#
|
80
|
-
# The testing environment will automatically load the
|
74
|
+
# The testing environment will automatically load all the fixtures into the database before each
|
81
75
|
# test. To ensure consistent data, the environment deletes the fixtures before running the load.
|
82
76
|
#
|
83
77
|
# In addition to being available in the database, the fixture's data may also be accessed by
|
84
|
-
# using a special dynamic method, which has the same name as the model
|
85
|
-
#
|
78
|
+
# using a special dynamic method, which has the same name as the model.
|
79
|
+
#
|
80
|
+
# Passing in a fixture name to this dynamic method returns the fixture matching this name:
|
86
81
|
#
|
87
|
-
# test "find" do
|
82
|
+
# test "find one" do
|
88
83
|
# assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
|
89
84
|
# end
|
90
85
|
#
|
86
|
+
# Passing in multiple fixture names returns all fixtures matching these names:
|
87
|
+
#
|
88
|
+
# test "find all by name" do
|
89
|
+
# assert_equal 2, web_sites(:rubyonrails, :google).length
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# Passing in no arguments returns all fixtures:
|
93
|
+
#
|
94
|
+
# test "find all" do
|
95
|
+
# assert_equal 2, web_sites.length
|
96
|
+
# end
|
97
|
+
#
|
98
|
+
# Passing in any fixture name that does not exist will raise <tt>StandardError</tt>:
|
99
|
+
#
|
100
|
+
# test "find by name that does not exist" do
|
101
|
+
# assert_raise(StandardError) { web_sites(:reddit) }
|
102
|
+
# end
|
103
|
+
#
|
91
104
|
# Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
|
92
105
|
# following tests:
|
93
106
|
#
|
@@ -96,11 +109,11 @@ module ActiveRecord
|
|
96
109
|
# end
|
97
110
|
#
|
98
111
|
# test "find_alt_method_2" do
|
99
|
-
# assert_equal "Ruby on Rails", @rubyonrails.
|
112
|
+
# assert_equal "Ruby on Rails", @rubyonrails.name
|
100
113
|
# end
|
101
114
|
#
|
102
|
-
# In order to use these methods to access fixtured data within your
|
103
|
-
# following in your
|
115
|
+
# In order to use these methods to access fixtured data within your test cases, you must specify one of the
|
116
|
+
# following in your ActiveSupport::TestCase-derived class:
|
104
117
|
#
|
105
118
|
# - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
|
106
119
|
# self.use_instantiated_fixtures = true
|
@@ -114,14 +127,14 @@ module ActiveRecord
|
|
114
127
|
#
|
115
128
|
# = Dynamic fixtures with ERB
|
116
129
|
#
|
117
|
-
#
|
130
|
+
# Sometimes you don't care about the content of the fixtures as much as you care about the volume.
|
118
131
|
# In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
|
119
132
|
# testing, like:
|
120
133
|
#
|
121
134
|
# <% 1.upto(1000) do |i| %>
|
122
135
|
# fix_<%= i %>:
|
123
136
|
# id: <%= i %>
|
124
|
-
# name: guy_<%=
|
137
|
+
# name: guy_<%= i %>
|
125
138
|
# <% end %>
|
126
139
|
#
|
127
140
|
# This will create 1000 very simple fixtures.
|
@@ -133,34 +146,51 @@ module ActiveRecord
|
|
133
146
|
# perhaps you should reexamine whether your application is properly testable. Hence, dynamic values
|
134
147
|
# in fixtures are to be considered a code smell.
|
135
148
|
#
|
136
|
-
#
|
149
|
+
# Helper methods defined in a fixture will not be available in other fixtures, to prevent against
|
150
|
+
# unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
|
151
|
+
# that is included in ActiveRecord::FixtureSet.context_class.
|
152
|
+
#
|
153
|
+
# - define a helper method in <tt>test_helper.rb</tt>
|
154
|
+
# module FixtureFileHelpers
|
155
|
+
# def file_sha(path)
|
156
|
+
# Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
157
|
+
# end
|
158
|
+
# end
|
159
|
+
# ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
|
160
|
+
#
|
161
|
+
# - use the helper method in a fixture
|
162
|
+
# photo:
|
163
|
+
# name: kitten.png
|
164
|
+
# sha: <%= file_sha 'files/kitten.png' %>
|
165
|
+
#
|
166
|
+
# = Transactional Tests
|
137
167
|
#
|
138
168
|
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
|
139
169
|
# delete+insert for every test case.
|
140
170
|
#
|
141
171
|
# class FooTest < ActiveSupport::TestCase
|
142
|
-
# self.
|
172
|
+
# self.use_transactional_tests = true
|
143
173
|
#
|
144
174
|
# test "godzilla" do
|
145
|
-
#
|
175
|
+
# assert_not_empty Foo.all
|
146
176
|
# Foo.destroy_all
|
147
|
-
#
|
177
|
+
# assert_empty Foo.all
|
148
178
|
# end
|
149
179
|
#
|
150
180
|
# test "godzilla aftermath" do
|
151
|
-
#
|
181
|
+
# assert_not_empty Foo.all
|
152
182
|
# end
|
153
183
|
# end
|
154
184
|
#
|
155
|
-
# If you preload your test database with all fixture data (probably
|
156
|
-
# transactional
|
185
|
+
# If you preload your test database with all fixture data (probably by running `rails db:fixtures:load`)
|
186
|
+
# and use transactional tests, then you may omit all fixtures declarations in your test cases since
|
157
187
|
# all the data's already there and every case rolls back its changes.
|
158
188
|
#
|
159
189
|
# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
|
160
190
|
# true. This will provide access to fixture data for every table that has been loaded through
|
161
191
|
# fixtures (depending on the value of +use_instantiated_fixtures+).
|
162
192
|
#
|
163
|
-
# When *not* to use transactional
|
193
|
+
# When *not* to use transactional tests:
|
164
194
|
#
|
165
195
|
# 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
|
166
196
|
# all parent transactions commit, particularly, the fixtures transaction which is begun in setup
|
@@ -176,6 +206,9 @@ module ActiveRecord
|
|
176
206
|
# * Stable, autogenerated IDs
|
177
207
|
# * Label references for associations (belongs_to, has_one, has_many)
|
178
208
|
# * HABTM associations as inline lists
|
209
|
+
#
|
210
|
+
# There are some more advanced features available even if the id is specified:
|
211
|
+
#
|
179
212
|
# * Autofilled timestamp columns
|
180
213
|
# * Fixture label interpolation
|
181
214
|
# * Support for YAML defaults
|
@@ -262,7 +295,7 @@ module ActiveRecord
|
|
262
295
|
#
|
263
296
|
# ### in fruit.rb
|
264
297
|
#
|
265
|
-
# belongs_to :eater, :
|
298
|
+
# belongs_to :eater, polymorphic: true
|
266
299
|
#
|
267
300
|
# ### in fruits.yml
|
268
301
|
#
|
@@ -358,201 +391,255 @@ module ActiveRecord
|
|
358
391
|
# geeksomnia:
|
359
392
|
# name: Geeksomnia's Account
|
360
393
|
# subdomain: $LABEL
|
394
|
+
# email: $LABEL@email.com
|
361
395
|
#
|
362
396
|
# Also, sometimes (like when porting older join table fixtures) you'll need
|
363
397
|
# to be able to get a hold of the identifier for a given label. ERB
|
364
398
|
# to the rescue:
|
365
399
|
#
|
366
400
|
# george_reginald:
|
367
|
-
# monkey_id: <%= ActiveRecord::
|
368
|
-
# pirate_id: <%= ActiveRecord::
|
401
|
+
# monkey_id: <%= ActiveRecord::FixtureSet.identify(:reginald) %>
|
402
|
+
# pirate_id: <%= ActiveRecord::FixtureSet.identify(:george) %>
|
369
403
|
#
|
370
404
|
# == Support for YAML defaults
|
371
405
|
#
|
372
|
-
# You
|
373
|
-
#
|
406
|
+
# You can set and reuse defaults in your fixtures YAML file.
|
407
|
+
# This is the same technique used in the +database.yml+ file to specify
|
408
|
+
# defaults:
|
374
409
|
#
|
375
410
|
# DEFAULTS: &DEFAULTS
|
376
411
|
# created_on: <%= 3.weeks.ago.to_s(:db) %>
|
377
412
|
#
|
378
413
|
# first:
|
379
414
|
# name: Smurf
|
380
|
-
# *DEFAULTS
|
415
|
+
# <<: *DEFAULTS
|
381
416
|
#
|
382
417
|
# second:
|
383
418
|
# name: Fraggle
|
384
|
-
# *DEFAULTS
|
419
|
+
# <<: *DEFAULTS
|
385
420
|
#
|
386
421
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
387
|
-
|
388
|
-
|
422
|
+
#
|
423
|
+
# == Configure the fixture model class
|
424
|
+
#
|
425
|
+
# It's possible to set the fixture's model class directly in the YAML file.
|
426
|
+
# This is helpful when fixtures are loaded outside tests and
|
427
|
+
# +set_fixture_class+ is not available (e.g.
|
428
|
+
# when running <tt>rails db:fixtures:load</tt>).
|
429
|
+
#
|
430
|
+
# _fixture:
|
431
|
+
# model_class: User
|
432
|
+
# david:
|
433
|
+
# name: David
|
434
|
+
#
|
435
|
+
# Any fixtures labeled "_fixture" are safely ignored.
|
436
|
+
class FixtureSet
|
437
|
+
#--
|
438
|
+
# An instance of FixtureSet is normally stored in a single YAML file and
|
439
|
+
# possibly in a folder with the same name.
|
440
|
+
#++
|
389
441
|
|
390
|
-
|
442
|
+
MAX_ID = 2**30 - 1
|
391
443
|
|
392
|
-
|
393
|
-
ActiveRecord::Base.pluralize_table_names ?
|
394
|
-
table_name.to_s.singularize.camelize :
|
395
|
-
table_name.to_s.camelize
|
396
|
-
end
|
444
|
+
@@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
|
397
445
|
|
398
|
-
|
399
|
-
@@all_cached_fixtures.clear
|
400
|
-
end
|
446
|
+
cattr_accessor :all_loaded_fixtures, default: {}
|
401
447
|
|
402
|
-
|
403
|
-
|
404
|
-
|
448
|
+
class ClassCache
|
449
|
+
def initialize(class_names, config)
|
450
|
+
@class_names = class_names.stringify_keys
|
451
|
+
@config = config
|
405
452
|
|
406
|
-
|
407
|
-
|
408
|
-
|
453
|
+
# Remove string values that aren't constants or subclasses of AR
|
454
|
+
@class_names.delete_if do |klass_name, klass|
|
455
|
+
!insert_class(@class_names, klass_name, klass)
|
456
|
+
end
|
457
|
+
end
|
409
458
|
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
459
|
+
def [](fs_name)
|
460
|
+
@class_names.fetch(fs_name) do
|
461
|
+
klass = default_fixture_model(fs_name, @config).safe_constantize
|
462
|
+
insert_class(@class_names, fs_name, klass)
|
463
|
+
end
|
415
464
|
end
|
416
|
-
end
|
417
465
|
|
418
|
-
|
419
|
-
cache_for_connection(connection).update(fixtures_map)
|
420
|
-
end
|
466
|
+
private
|
421
467
|
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
fixture_set.each do |fixture_name, fixture|
|
429
|
-
begin
|
430
|
-
object.instance_variable_set "@#{fixture_name}", fixture.find
|
431
|
-
rescue FixtureClassNotFound
|
432
|
-
nil
|
468
|
+
def insert_class(class_names, name, klass)
|
469
|
+
# We only want to deal with AR objects.
|
470
|
+
if klass && klass < ActiveRecord::Base
|
471
|
+
class_names[name] = klass
|
472
|
+
else
|
473
|
+
class_names[name] = nil
|
433
474
|
end
|
434
475
|
end
|
435
|
-
|
476
|
+
|
477
|
+
def default_fixture_model(fs_name, config)
|
478
|
+
ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
|
479
|
+
end
|
436
480
|
end
|
437
481
|
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
unless load_instances == true || load_instances == false
|
444
|
-
ActiveSupport::Deprecation.warn(
|
445
|
-
"ActiveRecord::Fixtures.instantiate_fixtures with parameters (object, fixture_set_name, fixture_set, load_instances = true) is deprecated and shall be removed from future releases. Use it with parameters (object, fixture_set, load_instances = true) instead (skip fixture_set_name).",
|
446
|
-
caller)
|
447
|
-
fixture_set = load_instances
|
448
|
-
load_instances = rails_3_2_compatibility_argument
|
482
|
+
class << self
|
483
|
+
def default_fixture_model_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
484
|
+
config.pluralize_table_names ?
|
485
|
+
fixture_set_name.singularize.camelize :
|
486
|
+
fixture_set_name.camelize
|
449
487
|
end
|
450
|
-
instantiate_fixtures__with_new_arity(object, fixture_set, load_instances)
|
451
|
-
end
|
452
488
|
|
453
|
-
|
454
|
-
|
455
|
-
|
489
|
+
def default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
490
|
+
"#{ config.table_name_prefix }"\
|
491
|
+
"#{ fixture_set_name.tr('/', '_') }"\
|
492
|
+
"#{ config.table_name_suffix }".to_sym
|
493
|
+
end
|
494
|
+
|
495
|
+
def reset_cache
|
496
|
+
@@all_cached_fixtures.clear
|
456
497
|
end
|
457
|
-
end
|
458
498
|
|
459
|
-
|
460
|
-
|
499
|
+
def cache_for_connection(connection)
|
500
|
+
@@all_cached_fixtures[connection]
|
501
|
+
end
|
461
502
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/')
|
466
|
-
}
|
503
|
+
def fixture_is_cached?(connection, table_name)
|
504
|
+
cache_for_connection(connection)[table_name]
|
505
|
+
end
|
467
506
|
|
468
|
-
|
469
|
-
|
507
|
+
def cached_fixtures(connection, keys_to_fetch = nil)
|
508
|
+
if keys_to_fetch
|
509
|
+
cache_for_connection(connection).values_at(*keys_to_fetch)
|
510
|
+
else
|
511
|
+
cache_for_connection(connection).values
|
512
|
+
end
|
513
|
+
end
|
470
514
|
|
471
|
-
|
472
|
-
|
473
|
-
|
515
|
+
def cache_fixtures(connection, fixtures_map)
|
516
|
+
cache_for_connection(connection).update(fixtures_map)
|
517
|
+
end
|
474
518
|
|
475
|
-
|
476
|
-
|
477
|
-
|
519
|
+
def instantiate_fixtures(object, fixture_set, load_instances = true)
|
520
|
+
return unless load_instances
|
521
|
+
fixture_set.each do |fixture_name, fixture|
|
522
|
+
object.instance_variable_set "@#{fixture_name}", fixture.find
|
523
|
+
rescue FixtureClassNotFound
|
524
|
+
nil
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
def instantiate_all_loaded_fixtures(object, load_instances = true)
|
529
|
+
all_loaded_fixtures.each_value do |fixture_set|
|
530
|
+
instantiate_fixtures(object, fixture_set, load_instances)
|
531
|
+
end
|
532
|
+
end
|
478
533
|
|
479
|
-
|
480
|
-
|
534
|
+
def create_fixtures(fixtures_directory, fixture_set_names, class_names = {}, config = ActiveRecord::Base, &block)
|
535
|
+
fixture_set_names = Array(fixture_set_names).map(&:to_s)
|
536
|
+
class_names = ClassCache.new class_names, config
|
537
|
+
|
538
|
+
# FIXME: Apparently JK uses this.
|
539
|
+
connection = block_given? ? block : lambda { ActiveRecord::Base.connection }
|
540
|
+
|
541
|
+
fixture_files_to_read = fixture_set_names.reject do |fs_name|
|
542
|
+
fixture_is_cached?(connection.call, fs_name)
|
543
|
+
end
|
544
|
+
|
545
|
+
if fixture_files_to_read.any?
|
546
|
+
fixtures_map = read_and_insert(
|
547
|
+
fixtures_directory,
|
548
|
+
fixture_files_to_read,
|
549
|
+
class_names,
|
550
|
+
connection,
|
551
|
+
)
|
552
|
+
cache_fixtures(connection.call, fixtures_map)
|
553
|
+
end
|
554
|
+
cached_fixtures(connection.call, fixture_set_names)
|
555
|
+
end
|
556
|
+
|
557
|
+
# Returns a consistent, platform-independent identifier for +label+.
|
558
|
+
# Integer identifiers are values less than 2^30. UUIDs are RFC 4122 version 5 SHA-1 hashes.
|
559
|
+
def identify(label, column_type = :integer)
|
560
|
+
if column_type == :uuid
|
561
|
+
Digest::UUID.uuid_v5(Digest::UUID::OID_NAMESPACE, label.to_s)
|
562
|
+
else
|
563
|
+
Zlib.crc32(label.to_s) % MAX_ID
|
564
|
+
end
|
565
|
+
end
|
566
|
+
|
567
|
+
# Superclass for the evaluation contexts used by ERB fixtures.
|
568
|
+
def context_class
|
569
|
+
@context_class ||= Class.new
|
570
|
+
end
|
481
571
|
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
572
|
+
private
|
573
|
+
|
574
|
+
def read_and_insert(fixtures_directory, fixture_files, class_names, connection) # :nodoc:
|
575
|
+
fixtures_map = {}
|
576
|
+
fixture_sets = fixture_files.map do |fixture_set_name|
|
577
|
+
klass = class_names[fixture_set_name]
|
578
|
+
fixtures_map[fixture_set_name] = new( # ActiveRecord::FixtureSet.new
|
579
|
+
nil,
|
580
|
+
fixture_set_name,
|
581
|
+
klass,
|
582
|
+
::File.join(fixtures_directory, fixture_set_name)
|
583
|
+
)
|
487
584
|
end
|
585
|
+
update_all_loaded_fixtures(fixtures_map)
|
488
586
|
|
489
|
-
|
587
|
+
insert(fixture_sets, connection)
|
490
588
|
|
491
|
-
|
492
|
-
|
493
|
-
conn = ff.model_class.respond_to?(:connection) ? ff.model_class.connection : connection
|
494
|
-
table_rows = ff.table_rows
|
589
|
+
fixtures_map
|
590
|
+
end
|
495
591
|
|
496
|
-
|
497
|
-
|
498
|
-
|
592
|
+
def insert(fixture_sets, connection) # :nodoc:
|
593
|
+
fixture_sets_by_connection = fixture_sets.group_by do |fixture_set|
|
594
|
+
if fixture_set.model_class
|
595
|
+
fixture_set.model_class.connection
|
596
|
+
else
|
597
|
+
connection.call
|
598
|
+
end
|
599
|
+
end
|
600
|
+
|
601
|
+
fixture_sets_by_connection.each do |conn, set|
|
602
|
+
table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
|
499
603
|
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
end
|
604
|
+
set.each do |fixture_set|
|
605
|
+
fixture_set.table_rows.each do |table, rows|
|
606
|
+
table_rows_for_connection[table].unshift(*rows)
|
504
607
|
end
|
505
608
|
end
|
506
609
|
|
610
|
+
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
611
|
+
|
507
612
|
# Cap primary key sequences to max(pk).
|
508
|
-
if
|
509
|
-
|
510
|
-
connection.reset_pk_sequence!(table_name.tr('/', '_'))
|
511
|
-
end
|
613
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
614
|
+
set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
|
512
615
|
end
|
513
616
|
end
|
617
|
+
end
|
514
618
|
|
515
|
-
|
619
|
+
def update_all_loaded_fixtures(fixtures_map) # :nodoc:
|
620
|
+
all_loaded_fixtures.update(fixtures_map)
|
516
621
|
end
|
517
|
-
end
|
518
|
-
cached_fixtures(connection, table_names)
|
519
622
|
end
|
520
623
|
|
521
|
-
|
522
|
-
# Identifiers are positive integers less than 2^32.
|
523
|
-
def self.identify(label)
|
524
|
-
Zlib.crc32(label.to_s) % MAX_ID
|
525
|
-
end
|
624
|
+
attr_reader :table_name, :name, :fixtures, :model_class, :config
|
526
625
|
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
@
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
@
|
535
|
-
|
536
|
-
@fixtures = ActiveSupport::OrderedHash.new
|
537
|
-
@table_name = "#{ActiveRecord::Base.table_name_prefix}#{@table_name}#{ActiveRecord::Base.table_name_suffix}"
|
538
|
-
|
539
|
-
# Should be an AR::Base type class
|
540
|
-
if class_name.is_a?(Class)
|
541
|
-
@table_name = class_name.table_name
|
542
|
-
@connection = class_name.connection
|
543
|
-
@model_class = class_name
|
544
|
-
else
|
545
|
-
@model_class = class_name.constantize rescue nil
|
546
|
-
end
|
626
|
+
def initialize(_, name, class_name, path, config = ActiveRecord::Base)
|
627
|
+
@name = name
|
628
|
+
@path = path
|
629
|
+
@config = config
|
630
|
+
|
631
|
+
self.model_class = class_name
|
632
|
+
|
633
|
+
@fixtures = read_fixture_files(path)
|
547
634
|
|
548
|
-
|
635
|
+
@table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
|
549
636
|
end
|
550
637
|
|
551
638
|
def [](x)
|
552
639
|
fixtures[x]
|
553
640
|
end
|
554
641
|
|
555
|
-
def []=(k,v)
|
642
|
+
def []=(k, v)
|
556
643
|
fixtures[k] = v
|
557
644
|
end
|
558
645
|
|
@@ -564,120 +651,51 @@ module ActiveRecord
|
|
564
651
|
fixtures.size
|
565
652
|
end
|
566
653
|
|
567
|
-
#
|
654
|
+
# Returns a hash of rows to be inserted. The key is the table, the value is
|
568
655
|
# a list of rows to insert to that table.
|
569
656
|
def table_rows
|
570
|
-
now = ActiveRecord::Base.default_timezone == :utc ? Time.now.utc : Time.now
|
571
|
-
now = now.to_s(:db)
|
572
|
-
|
573
657
|
# allow a standard key to be used for doing defaults in YAML
|
574
|
-
fixtures.delete(
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
if model_class && model_class < ActiveRecord::Base
|
583
|
-
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
584
|
-
if model_class.record_timestamps
|
585
|
-
timestamp_column_names.each do |name|
|
586
|
-
row[name] = now unless row.key?(name)
|
587
|
-
end
|
588
|
-
end
|
589
|
-
|
590
|
-
# interpolate the fixture label
|
591
|
-
row.each do |key, value|
|
592
|
-
row[key] = label if value == "$LABEL"
|
593
|
-
end
|
594
|
-
|
595
|
-
# generate a primary key if necessary
|
596
|
-
if has_primary_key_column? && !row.include?(primary_key_name)
|
597
|
-
row[primary_key_name] = ActiveRecord::Fixtures.identify(label)
|
598
|
-
end
|
599
|
-
|
600
|
-
# If STI is used, find the correct subclass for association reflection
|
601
|
-
reflection_class =
|
602
|
-
if row.include?(inheritance_column_name)
|
603
|
-
row[inheritance_column_name].constantize rescue model_class
|
604
|
-
else
|
605
|
-
model_class
|
606
|
-
end
|
607
|
-
|
608
|
-
reflection_class.reflect_on_all_associations.each do |association|
|
609
|
-
case association.macro
|
610
|
-
when :belongs_to
|
611
|
-
# Do not replace association name with association foreign key if they are named the same
|
612
|
-
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
613
|
-
|
614
|
-
if association.name.to_s != fk_name && value = row.delete(association.name.to_s)
|
615
|
-
if association.options[:polymorphic] && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
616
|
-
# support polymorphic belongs_to as "label (Type)"
|
617
|
-
row[association.foreign_type] = $1
|
618
|
-
end
|
619
|
-
|
620
|
-
row[fk_name] = ActiveRecord::Fixtures.identify(value)
|
621
|
-
end
|
622
|
-
when :has_and_belongs_to_many
|
623
|
-
if (targets = row.delete(association.name.to_s))
|
624
|
-
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
625
|
-
table_name = association.options[:join_table]
|
626
|
-
rows[table_name].concat targets.map { |target|
|
627
|
-
{ association.foreign_key => row[primary_key_name],
|
628
|
-
association.association_foreign_key => ActiveRecord::Fixtures.identify(target) }
|
629
|
-
}
|
630
|
-
end
|
631
|
-
end
|
632
|
-
end
|
633
|
-
end
|
634
|
-
|
635
|
-
row
|
636
|
-
end
|
637
|
-
rows
|
658
|
+
fixtures.delete("DEFAULTS")
|
659
|
+
|
660
|
+
TableRows.new(
|
661
|
+
table_name,
|
662
|
+
model_class: model_class,
|
663
|
+
fixtures: fixtures,
|
664
|
+
config: config,
|
665
|
+
).to_hash
|
638
666
|
end
|
639
667
|
|
640
668
|
private
|
641
|
-
def primary_key_name
|
642
|
-
@primary_key_name ||= model_class && model_class.primary_key
|
643
|
-
end
|
644
|
-
|
645
|
-
def has_primary_key_column?
|
646
|
-
@has_primary_key_column ||= primary_key_name &&
|
647
|
-
model_class.columns.any? { |c| c.name == primary_key_name }
|
648
|
-
end
|
649
|
-
|
650
|
-
def timestamp_column_names
|
651
|
-
@timestamp_column_names ||=
|
652
|
-
%w(created_at created_on updated_at updated_on) & column_names
|
653
|
-
end
|
654
669
|
|
655
|
-
def
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
670
|
+
def model_class=(class_name)
|
671
|
+
if class_name.is_a?(Class) # TODO: Should be an AR::Base type class, or any?
|
672
|
+
@model_class = class_name
|
673
|
+
else
|
674
|
+
@model_class = class_name.safe_constantize if class_name
|
675
|
+
end
|
661
676
|
end
|
662
677
|
|
663
|
-
|
664
|
-
|
678
|
+
# Loads the fixtures from the YAML file at +path+.
|
679
|
+
# If the file sets the +model_class+ and current instance value is not set,
|
680
|
+
# it uses the file value.
|
681
|
+
def read_fixture_files(path)
|
682
|
+
yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
|
665
683
|
::File.file?(f)
|
666
|
-
} + [yaml_file_path]
|
684
|
+
} + [yaml_file_path(path)]
|
667
685
|
|
668
|
-
yaml_files.
|
669
|
-
|
670
|
-
fh.
|
671
|
-
|
686
|
+
yaml_files.each_with_object({}) do |file, fixtures|
|
687
|
+
FixtureSet::File.open(file) do |fh|
|
688
|
+
self.model_class ||= fh.model_class if fh.model_class
|
689
|
+
fh.each do |fixture_name, row|
|
690
|
+
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
672
691
|
end
|
673
692
|
end
|
674
693
|
end
|
675
694
|
end
|
676
695
|
|
677
|
-
def yaml_file_path
|
678
|
-
"#{
|
696
|
+
def yaml_file_path(path)
|
697
|
+
"#{path}.yml"
|
679
698
|
end
|
680
|
-
|
681
699
|
end
|
682
700
|
|
683
701
|
class Fixture #:nodoc:
|
@@ -711,212 +729,10 @@ module ActiveRecord
|
|
711
729
|
alias :to_hash :fixture
|
712
730
|
|
713
731
|
def find
|
714
|
-
|
732
|
+
raise FixtureClassNotFound, "No class attached to find." unless model_class
|
733
|
+
model_class.unscoped do
|
715
734
|
model_class.find(fixture[model_class.primary_key])
|
716
|
-
else
|
717
|
-
raise FixtureClassNotFound, "No class attached to find."
|
718
|
-
end
|
719
|
-
end
|
720
|
-
end
|
721
|
-
end
|
722
|
-
|
723
|
-
module ActiveRecord
|
724
|
-
module TestFixtures
|
725
|
-
extend ActiveSupport::Concern
|
726
|
-
|
727
|
-
included do
|
728
|
-
setup :setup_fixtures
|
729
|
-
teardown :teardown_fixtures
|
730
|
-
|
731
|
-
class_attribute :fixture_path
|
732
|
-
class_attribute :fixture_table_names
|
733
|
-
class_attribute :fixture_class_names
|
734
|
-
class_attribute :use_transactional_fixtures
|
735
|
-
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
736
|
-
class_attribute :pre_loaded_fixtures
|
737
|
-
|
738
|
-
self.fixture_table_names = []
|
739
|
-
self.use_transactional_fixtures = true
|
740
|
-
self.use_instantiated_fixtures = false
|
741
|
-
self.pre_loaded_fixtures = false
|
742
|
-
|
743
|
-
self.fixture_class_names = Hash.new do |h, table_name|
|
744
|
-
h[table_name] = ActiveRecord::Fixtures.find_table_name(table_name)
|
745
|
-
end
|
746
|
-
end
|
747
|
-
|
748
|
-
module ClassMethods
|
749
|
-
def set_fixture_class(class_names = {})
|
750
|
-
self.fixture_class_names = self.fixture_class_names.merge(class_names)
|
751
|
-
end
|
752
|
-
|
753
|
-
def fixtures(*fixture_names)
|
754
|
-
if fixture_names.first == :all
|
755
|
-
fixture_names = Dir["#{fixture_path}/**/*.{yml}"]
|
756
|
-
fixture_names.map! { |f| f[(fixture_path.size + 1)..-5] }
|
757
|
-
else
|
758
|
-
fixture_names = fixture_names.flatten.map { |n| n.to_s }
|
759
|
-
end
|
760
|
-
|
761
|
-
self.fixture_table_names |= fixture_names
|
762
|
-
require_fixture_classes(fixture_names)
|
763
|
-
setup_fixture_accessors(fixture_names)
|
764
|
-
end
|
765
|
-
|
766
|
-
def try_to_load_dependency(file_name)
|
767
|
-
require_dependency file_name
|
768
|
-
rescue LoadError => e
|
769
|
-
# Let's hope the developer has included it himself
|
770
|
-
|
771
|
-
# Let's warn in case this is a subdependency, otherwise
|
772
|
-
# subdependency error messages are totally cryptic
|
773
|
-
if ActiveRecord::Base.logger
|
774
|
-
ActiveRecord::Base.logger.warn("Unable to load #{file_name}, underlying cause #{e.message} \n\n #{e.backtrace.join("\n")}")
|
775
|
-
end
|
776
|
-
end
|
777
|
-
|
778
|
-
def require_fixture_classes(fixture_names = nil)
|
779
|
-
(fixture_names || fixture_table_names).each do |fixture_name|
|
780
|
-
file_name = fixture_name.to_s
|
781
|
-
file_name = file_name.singularize if ActiveRecord::Base.pluralize_table_names
|
782
|
-
try_to_load_dependency(file_name)
|
783
|
-
end
|
784
|
-
end
|
785
|
-
|
786
|
-
def setup_fixture_accessors(fixture_names = nil)
|
787
|
-
fixture_names = Array.wrap(fixture_names || fixture_table_names)
|
788
|
-
methods = Module.new do
|
789
|
-
fixture_names.each do |fixture_name|
|
790
|
-
fixture_name = fixture_name.to_s.tr('./', '_')
|
791
|
-
|
792
|
-
define_method(fixture_name) do |*fixtures|
|
793
|
-
force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
|
794
|
-
|
795
|
-
@fixture_cache[fixture_name] ||= {}
|
796
|
-
|
797
|
-
instances = fixtures.map do |fixture|
|
798
|
-
@fixture_cache[fixture_name].delete(fixture) if force_reload
|
799
|
-
|
800
|
-
if @loaded_fixtures[fixture_name][fixture.to_s]
|
801
|
-
ActiveRecord::IdentityMap.without do
|
802
|
-
@fixture_cache[fixture_name][fixture] ||= @loaded_fixtures[fixture_name][fixture.to_s].find
|
803
|
-
end
|
804
|
-
else
|
805
|
-
raise StandardError, "No fixture with name '#{fixture}' found for table '#{fixture_name}'"
|
806
|
-
end
|
807
|
-
end
|
808
|
-
|
809
|
-
instances.size == 1 ? instances.first : instances
|
810
|
-
end
|
811
|
-
private fixture_name
|
812
|
-
end
|
813
|
-
end
|
814
|
-
include methods
|
815
735
|
end
|
816
|
-
|
817
|
-
def uses_transaction(*methods)
|
818
|
-
@uses_transaction = [] unless defined?(@uses_transaction)
|
819
|
-
@uses_transaction.concat methods.map { |m| m.to_s }
|
820
|
-
end
|
821
|
-
|
822
|
-
def uses_transaction?(method)
|
823
|
-
@uses_transaction = [] unless defined?(@uses_transaction)
|
824
|
-
@uses_transaction.include?(method.to_s)
|
825
|
-
end
|
826
|
-
end
|
827
|
-
|
828
|
-
def run_in_transaction?
|
829
|
-
use_transactional_fixtures &&
|
830
|
-
!self.class.uses_transaction?(method_name)
|
831
736
|
end
|
832
|
-
|
833
|
-
def setup_fixtures
|
834
|
-
return unless !ActiveRecord::Base.configurations.blank?
|
835
|
-
|
836
|
-
if pre_loaded_fixtures && !use_transactional_fixtures
|
837
|
-
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
|
838
|
-
end
|
839
|
-
|
840
|
-
@fixture_cache = {}
|
841
|
-
@fixture_connections = []
|
842
|
-
@@already_loaded_fixtures ||= {}
|
843
|
-
|
844
|
-
# Load fixtures once and begin transaction.
|
845
|
-
if run_in_transaction?
|
846
|
-
if @@already_loaded_fixtures[self.class]
|
847
|
-
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
848
|
-
else
|
849
|
-
@loaded_fixtures = load_fixtures
|
850
|
-
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
851
|
-
end
|
852
|
-
@fixture_connections = enlist_fixture_connections
|
853
|
-
@fixture_connections.each do |connection|
|
854
|
-
connection.increment_open_transactions
|
855
|
-
connection.transaction_joinable = false
|
856
|
-
connection.begin_db_transaction
|
857
|
-
end
|
858
|
-
# Load fixtures for every test.
|
859
|
-
else
|
860
|
-
ActiveRecord::Fixtures.reset_cache
|
861
|
-
@@already_loaded_fixtures[self.class] = nil
|
862
|
-
@loaded_fixtures = load_fixtures
|
863
|
-
end
|
864
|
-
|
865
|
-
# Instantiate fixtures for every test if requested.
|
866
|
-
instantiate_fixtures if use_instantiated_fixtures
|
867
|
-
end
|
868
|
-
|
869
|
-
def teardown_fixtures
|
870
|
-
return unless defined?(ActiveRecord) && !ActiveRecord::Base.configurations.blank?
|
871
|
-
|
872
|
-
unless run_in_transaction?
|
873
|
-
ActiveRecord::Fixtures.reset_cache
|
874
|
-
end
|
875
|
-
|
876
|
-
# Rollback changes if a transaction is active.
|
877
|
-
if run_in_transaction?
|
878
|
-
@fixture_connections.each do |connection|
|
879
|
-
if connection.open_transactions != 0
|
880
|
-
connection.rollback_db_transaction
|
881
|
-
connection.decrement_open_transactions
|
882
|
-
end
|
883
|
-
end
|
884
|
-
@fixture_connections.clear
|
885
|
-
end
|
886
|
-
ActiveRecord::Base.clear_active_connections!
|
887
|
-
end
|
888
|
-
|
889
|
-
def enlist_fixture_connections
|
890
|
-
ActiveRecord::Base.connection_handler.connection_pools.values.map(&:connection)
|
891
|
-
end
|
892
|
-
|
893
|
-
private
|
894
|
-
def load_fixtures
|
895
|
-
fixtures = ActiveRecord::Fixtures.create_fixtures(fixture_path, fixture_table_names, fixture_class_names)
|
896
|
-
Hash[fixtures.map { |f| [f.name, f] }]
|
897
|
-
end
|
898
|
-
|
899
|
-
# for pre_loaded_fixtures, only require the classes once. huge speed improvement
|
900
|
-
@@required_fixture_classes = false
|
901
|
-
|
902
|
-
def instantiate_fixtures
|
903
|
-
if pre_loaded_fixtures
|
904
|
-
raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::Fixtures.all_loaded_fixtures.empty?
|
905
|
-
unless @@required_fixture_classes
|
906
|
-
self.class.require_fixture_classes ActiveRecord::Fixtures.all_loaded_fixtures.keys
|
907
|
-
@@required_fixture_classes = true
|
908
|
-
end
|
909
|
-
ActiveRecord::Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
|
910
|
-
else
|
911
|
-
raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
|
912
|
-
@loaded_fixtures.each_value do |fixture_set|
|
913
|
-
ActiveRecord::Fixtures.instantiate_fixtures(self, fixture_set, load_instances?)
|
914
|
-
end
|
915
|
-
end
|
916
|
-
end
|
917
|
-
|
918
|
-
def load_instances?
|
919
|
-
use_instantiated_fixtures != :no_instances
|
920
|
-
end
|
921
737
|
end
|
922
738
|
end
|