activerecord 4.2.11.3 → 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 +4 -4
- data/CHANGELOG.md +613 -1643
- 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 +131 -287
- 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 -86
- 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 -243
- 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 -635
- 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 -180
- 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 +6 -4
- 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 +621 -303
- 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 +312 -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 +143 -44
- 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 +328 -185
- 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 +307 -100
- 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 -59
- 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 -498
- 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 -64
- 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,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "erb"
|
4
|
+
require "yaml"
|
3
5
|
|
4
6
|
module ActiveRecord
|
5
7
|
class FixtureSet
|
@@ -17,38 +19,62 @@ module ActiveRecord
|
|
17
19
|
|
18
20
|
def initialize(file)
|
19
21
|
@file = file
|
20
|
-
@rows = nil
|
21
22
|
end
|
22
23
|
|
23
24
|
def each(&block)
|
24
25
|
rows.each(&block)
|
25
26
|
end
|
26
27
|
|
28
|
+
def model_class
|
29
|
+
config_row["model_class"]
|
30
|
+
end
|
27
31
|
|
28
32
|
private
|
29
33
|
def rows
|
30
|
-
|
34
|
+
@rows ||= raw_rows.reject { |fixture_name, _| fixture_name == "_fixture" }
|
35
|
+
end
|
31
36
|
|
32
|
-
|
37
|
+
def config_row
|
38
|
+
@config_row ||= begin
|
39
|
+
row = raw_rows.find { |fixture_name, _| fixture_name == "_fixture" }
|
40
|
+
if row
|
41
|
+
row.last
|
42
|
+
else
|
43
|
+
{ 'model_class': nil }
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def raw_rows
|
49
|
+
@raw_rows ||= begin
|
33
50
|
data = YAML.load(render(IO.read(@file)))
|
51
|
+
data ? validate(data).to_a : []
|
34
52
|
rescue ArgumentError, Psych::SyntaxError => error
|
35
53
|
raise Fixture::FormatError, "a YAML error occurred parsing #{@file}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n #{error.class}: #{error}", error.backtrace
|
36
54
|
end
|
37
|
-
|
55
|
+
end
|
56
|
+
|
57
|
+
def prepare_erb(content)
|
58
|
+
erb = ERB.new(content)
|
59
|
+
erb.filename = @file
|
60
|
+
erb
|
38
61
|
end
|
39
62
|
|
40
63
|
def render(content)
|
41
64
|
context = ActiveRecord::FixtureSet::RenderContext.create_subclass.new
|
42
|
-
|
65
|
+
prepare_erb(content).result(context.get_binding)
|
43
66
|
end
|
44
67
|
|
45
68
|
# Validate our unmarshalled data.
|
46
69
|
def validate(data)
|
47
70
|
unless Hash === data || YAML::Omap === data
|
48
|
-
raise Fixture::FormatError,
|
71
|
+
raise Fixture::FormatError, "fixture is not a hash: #{@file}"
|
49
72
|
end
|
50
73
|
|
51
|
-
|
74
|
+
invalid = data.reject { |_, row| Hash === row }
|
75
|
+
if invalid.any?
|
76
|
+
raise Fixture::FormatError, "fixture key is not a hash: #{@file}, keys: #{invalid.keys.inspect}"
|
77
|
+
end
|
52
78
|
data
|
53
79
|
end
|
54
80
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class FixtureSet
|
5
|
+
class ModelMetadata # :nodoc:
|
6
|
+
def initialize(model_class)
|
7
|
+
@model_class = model_class
|
8
|
+
end
|
9
|
+
|
10
|
+
def primary_key_name
|
11
|
+
@primary_key_name ||= @model_class && @model_class.primary_key
|
12
|
+
end
|
13
|
+
|
14
|
+
def primary_key_type
|
15
|
+
@primary_key_type ||= @model_class && @model_class.type_for_attribute(@model_class.primary_key).type
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_primary_key_column?
|
19
|
+
@has_primary_key_column ||= primary_key_name &&
|
20
|
+
@model_class.columns.any? { |col| col.name == primary_key_name }
|
21
|
+
end
|
22
|
+
|
23
|
+
def timestamp_column_names
|
24
|
+
@timestamp_column_names ||=
|
25
|
+
%w(created_at created_on updated_at updated_on) & @model_class.column_names
|
26
|
+
end
|
27
|
+
|
28
|
+
def inheritance_column_name
|
29
|
+
@inheritance_column_name ||= @model_class && @model_class.inheritance_column
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE: This class has to be defined in compact style in
|
4
|
+
# order for rendering context subclassing to work correctly.
|
5
|
+
class ActiveRecord::FixtureSet::RenderContext # :nodoc:
|
6
|
+
def self.create_subclass
|
7
|
+
Class.new(ActiveRecord::FixtureSet.context_class) do
|
8
|
+
def get_binding
|
9
|
+
binding()
|
10
|
+
end
|
11
|
+
|
12
|
+
def binary(path)
|
13
|
+
%(!!binary "#{Base64.strict_encode64(File.read(path))}")
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class FixtureSet
|
5
|
+
class TableRow # :nodoc:
|
6
|
+
class ReflectionProxy # :nodoc:
|
7
|
+
def initialize(association)
|
8
|
+
@association = association
|
9
|
+
end
|
10
|
+
|
11
|
+
def join_table
|
12
|
+
@association.join_table
|
13
|
+
end
|
14
|
+
|
15
|
+
def name
|
16
|
+
@association.name
|
17
|
+
end
|
18
|
+
|
19
|
+
def primary_key_type
|
20
|
+
@association.klass.type_for_attribute(@association.klass.primary_key).type
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class HasManyThroughProxy < ReflectionProxy # :nodoc:
|
25
|
+
def rhs_key
|
26
|
+
@association.foreign_key
|
27
|
+
end
|
28
|
+
|
29
|
+
def lhs_key
|
30
|
+
@association.through_reflection.foreign_key
|
31
|
+
end
|
32
|
+
|
33
|
+
def join_table
|
34
|
+
@association.through_reflection.table_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(fixture, table_rows:, label:, now:)
|
39
|
+
@table_rows = table_rows
|
40
|
+
@label = label
|
41
|
+
@now = now
|
42
|
+
@row = fixture.to_hash
|
43
|
+
fill_row_model_attributes
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_hash
|
47
|
+
@row
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def model_metadata
|
53
|
+
@table_rows.model_metadata
|
54
|
+
end
|
55
|
+
|
56
|
+
def model_class
|
57
|
+
@table_rows.model_class
|
58
|
+
end
|
59
|
+
|
60
|
+
def fill_row_model_attributes
|
61
|
+
return unless model_class
|
62
|
+
fill_timestamps
|
63
|
+
interpolate_label
|
64
|
+
generate_primary_key
|
65
|
+
resolve_enums
|
66
|
+
resolve_sti_reflections
|
67
|
+
end
|
68
|
+
|
69
|
+
def reflection_class
|
70
|
+
@reflection_class ||= if @row.include?(model_metadata.inheritance_column_name)
|
71
|
+
@row[model_metadata.inheritance_column_name].constantize rescue model_class
|
72
|
+
else
|
73
|
+
model_class
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def fill_timestamps
|
78
|
+
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
79
|
+
if model_class.record_timestamps
|
80
|
+
model_metadata.timestamp_column_names.each do |c_name|
|
81
|
+
@row[c_name] = @now unless @row.key?(c_name)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def interpolate_label
|
87
|
+
# interpolate the fixture label
|
88
|
+
@row.each do |key, value|
|
89
|
+
@row[key] = value.gsub("$LABEL", @label.to_s) if value.is_a?(String)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def generate_primary_key
|
94
|
+
# generate a primary key if necessary
|
95
|
+
if model_metadata.has_primary_key_column? && !@row.include?(model_metadata.primary_key_name)
|
96
|
+
@row[model_metadata.primary_key_name] = ActiveRecord::FixtureSet.identify(
|
97
|
+
@label, model_metadata.primary_key_type
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def resolve_enums
|
103
|
+
model_class.defined_enums.each do |name, values|
|
104
|
+
if @row.include?(name)
|
105
|
+
@row[name] = values.fetch(@row[name], @row[name])
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def resolve_sti_reflections
|
111
|
+
# If STI is used, find the correct subclass for association reflection
|
112
|
+
reflection_class._reflections.each_value do |association|
|
113
|
+
case association.macro
|
114
|
+
when :belongs_to
|
115
|
+
# Do not replace association name with association foreign key if they are named the same
|
116
|
+
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
117
|
+
|
118
|
+
if association.name.to_s != fk_name && value = @row.delete(association.name.to_s)
|
119
|
+
if association.polymorphic? && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
120
|
+
# support polymorphic belongs_to as "label (Type)"
|
121
|
+
@row[association.foreign_type] = $1
|
122
|
+
end
|
123
|
+
|
124
|
+
fk_type = reflection_class.type_for_attribute(fk_name).type
|
125
|
+
@row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
126
|
+
end
|
127
|
+
when :has_many
|
128
|
+
if association.options[:through]
|
129
|
+
add_join_records(HasManyThroughProxy.new(association))
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def add_join_records(association)
|
136
|
+
# This is the case when the join table has no fixtures file
|
137
|
+
if (targets = @row.delete(association.name.to_s))
|
138
|
+
table_name = association.join_table
|
139
|
+
column_type = association.primary_key_type
|
140
|
+
lhs_key = association.lhs_key
|
141
|
+
rhs_key = association.rhs_key
|
142
|
+
|
143
|
+
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
144
|
+
joins = targets.map do |target|
|
145
|
+
{ lhs_key => @row[model_metadata.primary_key_name],
|
146
|
+
rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
|
147
|
+
end
|
148
|
+
@table_rows.tables[table_name].concat(joins)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "active_record/fixture_set/table_row"
|
4
|
+
require "active_record/fixture_set/model_metadata"
|
5
|
+
|
6
|
+
module ActiveRecord
|
7
|
+
class FixtureSet
|
8
|
+
class TableRows # :nodoc:
|
9
|
+
def initialize(table_name, model_class:, fixtures:, config:)
|
10
|
+
@model_class = model_class
|
11
|
+
|
12
|
+
# track any join tables we need to insert later
|
13
|
+
@tables = Hash.new { |h, table| h[table] = [] }
|
14
|
+
|
15
|
+
# ensure this table is loaded before any HABTM associations
|
16
|
+
@tables[table_name] = nil
|
17
|
+
|
18
|
+
build_table_rows_from(table_name, fixtures, config)
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :tables, :model_class
|
22
|
+
|
23
|
+
def to_hash
|
24
|
+
@tables.transform_values { |rows| rows.map(&:to_hash) }
|
25
|
+
end
|
26
|
+
|
27
|
+
def model_metadata
|
28
|
+
@model_metadata ||= ModelMetadata.new(model_class)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def build_table_rows_from(table_name, fixtures, config)
|
34
|
+
now = config.default_timezone == :utc ? Time.now.utc : Time.now
|
35
|
+
|
36
|
+
@tables[table_name] = fixtures.map do |label, fixture|
|
37
|
+
TableRow.new(
|
38
|
+
fixture,
|
39
|
+
table_rows: self,
|
40
|
+
label: label,
|
41
|
+
now: now,
|
42
|
+
)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -1,10 +1,16 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
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"
|
8
14
|
|
9
15
|
module ActiveRecord
|
10
16
|
class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc:
|
@@ -65,17 +71,36 @@ module ActiveRecord
|
|
65
71
|
# By default, +test_helper.rb+ will load all of your fixtures into your test
|
66
72
|
# database, so this test will succeed.
|
67
73
|
#
|
68
|
-
# The testing environment will automatically load the
|
74
|
+
# The testing environment will automatically load all the fixtures into the database before each
|
69
75
|
# test. To ensure consistent data, the environment deletes the fixtures before running the load.
|
70
76
|
#
|
71
77
|
# In addition to being available in the database, the fixture's data may also be accessed by
|
72
|
-
# using a special dynamic method, which has the same name as the model
|
73
|
-
# name of the fixture to instantiate:
|
78
|
+
# using a special dynamic method, which has the same name as the model.
|
74
79
|
#
|
75
|
-
#
|
80
|
+
# Passing in a fixture name to this dynamic method returns the fixture matching this name:
|
81
|
+
#
|
82
|
+
# test "find one" do
|
76
83
|
# assert_equal "Ruby on Rails", web_sites(:rubyonrails).name
|
77
84
|
# end
|
78
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
|
+
#
|
79
104
|
# Alternatively, you may enable auto-instantiation of the fixture data. For instance, take the
|
80
105
|
# following tests:
|
81
106
|
#
|
@@ -87,8 +112,8 @@ module ActiveRecord
|
|
87
112
|
# assert_equal "Ruby on Rails", @rubyonrails.name
|
88
113
|
# end
|
89
114
|
#
|
90
|
-
# In order to use these methods to access fixtured data within your
|
91
|
-
# 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:
|
92
117
|
#
|
93
118
|
# - to fully enable instantiated fixtures (enable alternate methods #1 and #2 above)
|
94
119
|
# self.use_instantiated_fixtures = true
|
@@ -102,14 +127,14 @@ module ActiveRecord
|
|
102
127
|
#
|
103
128
|
# = Dynamic fixtures with ERB
|
104
129
|
#
|
105
|
-
#
|
130
|
+
# Sometimes you don't care about the content of the fixtures as much as you care about the volume.
|
106
131
|
# In these cases, you can mix ERB in with your YAML fixtures to create a bunch of fixtures for load
|
107
132
|
# testing, like:
|
108
133
|
#
|
109
134
|
# <% 1.upto(1000) do |i| %>
|
110
135
|
# fix_<%= i %>:
|
111
136
|
# id: <%= i %>
|
112
|
-
# name: guy_<%=
|
137
|
+
# name: guy_<%= i %>
|
113
138
|
# <% end %>
|
114
139
|
#
|
115
140
|
# This will create 1000 very simple fixtures.
|
@@ -123,49 +148,49 @@ module ActiveRecord
|
|
123
148
|
#
|
124
149
|
# Helper methods defined in a fixture will not be available in other fixtures, to prevent against
|
125
150
|
# unwanted inter-test dependencies. Methods used by multiple fixtures should be defined in a module
|
126
|
-
# that is included in
|
151
|
+
# that is included in ActiveRecord::FixtureSet.context_class.
|
127
152
|
#
|
128
|
-
# - define a helper method in
|
153
|
+
# - define a helper method in <tt>test_helper.rb</tt>
|
129
154
|
# module FixtureFileHelpers
|
130
155
|
# def file_sha(path)
|
131
156
|
# Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path)))
|
132
157
|
# end
|
133
158
|
# end
|
134
|
-
# ActiveRecord::FixtureSet.context_class.
|
159
|
+
# ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers
|
135
160
|
#
|
136
161
|
# - use the helper method in a fixture
|
137
162
|
# photo:
|
138
163
|
# name: kitten.png
|
139
164
|
# sha: <%= file_sha 'files/kitten.png' %>
|
140
165
|
#
|
141
|
-
# = Transactional
|
166
|
+
# = Transactional Tests
|
142
167
|
#
|
143
168
|
# Test cases can use begin+rollback to isolate their changes to the database instead of having to
|
144
169
|
# delete+insert for every test case.
|
145
170
|
#
|
146
171
|
# class FooTest < ActiveSupport::TestCase
|
147
|
-
# self.
|
172
|
+
# self.use_transactional_tests = true
|
148
173
|
#
|
149
174
|
# test "godzilla" do
|
150
|
-
#
|
175
|
+
# assert_not_empty Foo.all
|
151
176
|
# Foo.destroy_all
|
152
|
-
#
|
177
|
+
# assert_empty Foo.all
|
153
178
|
# end
|
154
179
|
#
|
155
180
|
# test "godzilla aftermath" do
|
156
|
-
#
|
181
|
+
# assert_not_empty Foo.all
|
157
182
|
# end
|
158
183
|
# end
|
159
184
|
#
|
160
|
-
# If you preload your test database with all fixture data (probably
|
161
|
-
# 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
|
162
187
|
# all the data's already there and every case rolls back its changes.
|
163
188
|
#
|
164
189
|
# In order to use instantiated fixtures with preloaded data, set +self.pre_loaded_fixtures+ to
|
165
190
|
# true. This will provide access to fixture data for every table that has been loaded through
|
166
191
|
# fixtures (depending on the value of +use_instantiated_fixtures+).
|
167
192
|
#
|
168
|
-
# When *not* to use transactional
|
193
|
+
# When *not* to use transactional tests:
|
169
194
|
#
|
170
195
|
# 1. You're testing whether a transaction works correctly. Nested transactions don't commit until
|
171
196
|
# all parent transactions commit, particularly, the fixtures transaction which is begun in setup
|
@@ -394,207 +419,227 @@ module ActiveRecord
|
|
394
419
|
# <<: *DEFAULTS
|
395
420
|
#
|
396
421
|
# Any fixture labeled "DEFAULTS" is safely ignored.
|
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.
|
397
436
|
class FixtureSet
|
398
437
|
#--
|
399
438
|
# An instance of FixtureSet is normally stored in a single YAML file and
|
400
439
|
# possibly in a folder with the same name.
|
401
440
|
#++
|
402
441
|
|
403
|
-
MAX_ID = 2
|
442
|
+
MAX_ID = 2**30 - 1
|
404
443
|
|
405
|
-
@@all_cached_fixtures = Hash.new { |h,k| h[k] = {} }
|
444
|
+
@@all_cached_fixtures = Hash.new { |h, k| h[k] = {} }
|
406
445
|
|
407
|
-
|
408
|
-
config.pluralize_table_names ?
|
409
|
-
fixture_set_name.singularize.camelize :
|
410
|
-
fixture_set_name.camelize
|
411
|
-
end
|
412
|
-
|
413
|
-
def self.default_fixture_table_name(fixture_set_name, config = ActiveRecord::Base) # :nodoc:
|
414
|
-
"#{ config.table_name_prefix }"\
|
415
|
-
"#{ fixture_set_name.tr('/', '_') }"\
|
416
|
-
"#{ config.table_name_suffix }".to_sym
|
417
|
-
end
|
446
|
+
cattr_accessor :all_loaded_fixtures, default: {}
|
418
447
|
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
def self.cache_for_connection(connection)
|
424
|
-
@@all_cached_fixtures[connection]
|
425
|
-
end
|
448
|
+
class ClassCache
|
449
|
+
def initialize(class_names, config)
|
450
|
+
@class_names = class_names.stringify_keys
|
451
|
+
@config = config
|
426
452
|
|
427
|
-
|
428
|
-
|
429
|
-
|
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
|
430
458
|
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
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
|
436
464
|
end
|
437
|
-
end
|
438
465
|
|
439
|
-
|
440
|
-
cache_for_connection(connection).update(fixtures_map)
|
441
|
-
end
|
466
|
+
private
|
442
467
|
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
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
|
450
474
|
end
|
451
475
|
end
|
452
|
-
end
|
453
|
-
end
|
454
476
|
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
end
|
477
|
+
def default_fixture_model(fs_name, config)
|
478
|
+
ActiveRecord::FixtureSet.default_fixture_model_name(fs_name, config)
|
479
|
+
end
|
459
480
|
end
|
460
481
|
|
461
|
-
|
462
|
-
|
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
|
487
|
+
end
|
463
488
|
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
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
|
468
494
|
|
469
|
-
|
470
|
-
|
495
|
+
def reset_cache
|
496
|
+
@@all_cached_fixtures.clear
|
471
497
|
end
|
472
498
|
|
473
|
-
def
|
474
|
-
|
475
|
-
klass = default_fixture_model(fs_name, @config).safe_constantize
|
476
|
-
insert_class(@class_names, fs_name, klass)
|
477
|
-
}
|
499
|
+
def cache_for_connection(connection)
|
500
|
+
@@all_cached_fixtures[connection]
|
478
501
|
end
|
479
502
|
|
480
|
-
|
503
|
+
def fixture_is_cached?(connection, table_name)
|
504
|
+
cache_for_connection(connection)[table_name]
|
505
|
+
end
|
481
506
|
|
482
|
-
def
|
483
|
-
|
484
|
-
|
485
|
-
class_names[name] = klass
|
507
|
+
def cached_fixtures(connection, keys_to_fetch = nil)
|
508
|
+
if keys_to_fetch
|
509
|
+
cache_for_connection(connection).values_at(*keys_to_fetch)
|
486
510
|
else
|
487
|
-
|
511
|
+
cache_for_connection(connection).values
|
488
512
|
end
|
489
513
|
end
|
490
514
|
|
491
|
-
def
|
492
|
-
|
515
|
+
def cache_fixtures(connection, fixtures_map)
|
516
|
+
cache_for_connection(connection).update(fixtures_map)
|
493
517
|
end
|
494
|
-
end
|
495
518
|
|
496
|
-
|
497
|
-
|
498
|
-
|
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
|
499
527
|
|
500
|
-
|
501
|
-
|
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
|
502
533
|
|
503
|
-
|
504
|
-
|
505
|
-
|
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
|
506
537
|
|
507
|
-
|
508
|
-
connection.
|
509
|
-
|
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
|
510
566
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
567
|
+
# Superclass for the evaluation contexts used by ERB fixtures.
|
568
|
+
def context_class
|
569
|
+
@context_class ||= Class.new
|
570
|
+
end
|
571
|
+
|
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,
|
517
581
|
klass,
|
518
|
-
::File.join(fixtures_directory,
|
582
|
+
::File.join(fixtures_directory, fixture_set_name)
|
583
|
+
)
|
519
584
|
end
|
585
|
+
update_all_loaded_fixtures(fixtures_map)
|
520
586
|
|
521
|
-
|
587
|
+
insert(fixture_sets, connection)
|
522
588
|
|
523
|
-
|
524
|
-
|
525
|
-
conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection
|
526
|
-
table_rows = fs.table_rows
|
589
|
+
fixtures_map
|
590
|
+
end
|
527
591
|
|
528
|
-
|
529
|
-
|
530
|
-
|
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
|
531
600
|
|
532
|
-
|
533
|
-
|
534
|
-
conn.insert_fixture(row, fixture_set_name)
|
535
|
-
end
|
536
|
-
end
|
601
|
+
fixture_sets_by_connection.each do |conn, set|
|
602
|
+
table_rows_for_connection = Hash.new { |h, k| h[k] = [] }
|
537
603
|
|
538
|
-
|
539
|
-
|
540
|
-
|
604
|
+
set.each do |fixture_set|
|
605
|
+
fixture_set.table_rows.each do |table, rows|
|
606
|
+
table_rows_for_connection[table].unshift(*rows)
|
541
607
|
end
|
542
608
|
end
|
543
|
-
end
|
544
609
|
|
545
|
-
|
546
|
-
end
|
547
|
-
end
|
548
|
-
cached_fixtures(connection, fixture_set_names)
|
549
|
-
end
|
610
|
+
conn.insert_fixtures_set(table_rows_for_connection, table_rows_for_connection.keys)
|
550
611
|
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
Zlib.crc32(label.to_s) % MAX_ID
|
558
|
-
end
|
559
|
-
end
|
560
|
-
|
561
|
-
# Superclass for the evaluation contexts used by ERB fixtures.
|
562
|
-
def self.context_class
|
563
|
-
@context_class ||= Class.new
|
564
|
-
end
|
612
|
+
# Cap primary key sequences to max(pk).
|
613
|
+
if conn.respond_to?(:reset_pk_sequence!)
|
614
|
+
set.each { |fs| conn.reset_pk_sequence!(fs.table_name) }
|
615
|
+
end
|
616
|
+
end
|
617
|
+
end
|
565
618
|
|
566
|
-
|
567
|
-
|
619
|
+
def update_all_loaded_fixtures(fixtures_map) # :nodoc:
|
620
|
+
all_loaded_fixtures.update(fixtures_map)
|
621
|
+
end
|
568
622
|
end
|
569
623
|
|
570
624
|
attr_reader :table_name, :name, :fixtures, :model_class, :config
|
571
625
|
|
572
|
-
def initialize(
|
626
|
+
def initialize(_, name, class_name, path, config = ActiveRecord::Base)
|
573
627
|
@name = name
|
574
628
|
@path = path
|
575
629
|
@config = config
|
576
|
-
@model_class = nil
|
577
630
|
|
578
|
-
|
579
|
-
@model_class = class_name
|
580
|
-
else
|
581
|
-
@model_class = class_name.safe_constantize if class_name
|
582
|
-
end
|
583
|
-
|
584
|
-
@connection = connection
|
631
|
+
self.model_class = class_name
|
585
632
|
|
586
|
-
@
|
587
|
-
model_class.table_name :
|
588
|
-
self.class.default_fixture_table_name(name, config) )
|
633
|
+
@fixtures = read_fixture_files(path)
|
589
634
|
|
590
|
-
@
|
635
|
+
@table_name = model_class&.table_name || self.class.default_fixture_table_name(name, config)
|
591
636
|
end
|
592
637
|
|
593
638
|
def [](x)
|
594
639
|
fixtures[x]
|
595
640
|
end
|
596
641
|
|
597
|
-
def []=(k,v)
|
642
|
+
def []=(k, v)
|
598
643
|
fixtures[k] = v
|
599
644
|
end
|
600
645
|
|
@@ -609,154 +654,38 @@ module ActiveRecord
|
|
609
654
|
# Returns a hash of rows to be inserted. The key is the table, the value is
|
610
655
|
# a list of rows to insert to that table.
|
611
656
|
def table_rows
|
612
|
-
now = config.default_timezone == :utc ? Time.now.utc : Time.now
|
613
|
-
now = now.to_s(:db)
|
614
|
-
|
615
657
|
# allow a standard key to be used for doing defaults in YAML
|
616
|
-
fixtures.delete(
|
617
|
-
|
618
|
-
# track any join tables we need to insert later
|
619
|
-
rows = Hash.new { |h,table| h[table] = [] }
|
620
|
-
|
621
|
-
rows[table_name] = fixtures.map do |label, fixture|
|
622
|
-
row = fixture.to_hash
|
623
|
-
|
624
|
-
if model_class
|
625
|
-
# fill in timestamp columns if they aren't specified and the model is set to record_timestamps
|
626
|
-
if model_class.record_timestamps
|
627
|
-
timestamp_column_names.each do |c_name|
|
628
|
-
row[c_name] = now unless row.key?(c_name)
|
629
|
-
end
|
630
|
-
end
|
631
|
-
|
632
|
-
# interpolate the fixture label
|
633
|
-
row.each do |key, value|
|
634
|
-
row[key] = value.gsub("$LABEL", label.to_s) if value.is_a?(String)
|
635
|
-
end
|
636
|
-
|
637
|
-
# generate a primary key if necessary
|
638
|
-
if has_primary_key_column? && !row.include?(primary_key_name)
|
639
|
-
row[primary_key_name] = ActiveRecord::FixtureSet.identify(label, primary_key_type)
|
640
|
-
end
|
641
|
-
|
642
|
-
# If STI is used, find the correct subclass for association reflection
|
643
|
-
reflection_class =
|
644
|
-
if row.include?(inheritance_column_name)
|
645
|
-
row[inheritance_column_name].constantize rescue model_class
|
646
|
-
else
|
647
|
-
model_class
|
648
|
-
end
|
649
|
-
|
650
|
-
reflection_class._reflections.each_value do |association|
|
651
|
-
case association.macro
|
652
|
-
when :belongs_to
|
653
|
-
# Do not replace association name with association foreign key if they are named the same
|
654
|
-
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
658
|
+
fixtures.delete("DEFAULTS")
|
655
659
|
|
656
|
-
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
662
|
-
fk_type = reflection_class.columns_hash[fk_name].type
|
663
|
-
row[fk_name] = ActiveRecord::FixtureSet.identify(value, fk_type)
|
664
|
-
end
|
665
|
-
when :has_many
|
666
|
-
if association.options[:through]
|
667
|
-
add_join_records(rows, row, HasManyThroughProxy.new(association))
|
668
|
-
end
|
669
|
-
end
|
670
|
-
end
|
671
|
-
end
|
672
|
-
|
673
|
-
row
|
674
|
-
end
|
675
|
-
rows
|
676
|
-
end
|
677
|
-
|
678
|
-
class ReflectionProxy # :nodoc:
|
679
|
-
def initialize(association)
|
680
|
-
@association = association
|
681
|
-
end
|
682
|
-
|
683
|
-
def join_table
|
684
|
-
@association.join_table
|
685
|
-
end
|
686
|
-
|
687
|
-
def name
|
688
|
-
@association.name
|
689
|
-
end
|
690
|
-
|
691
|
-
def primary_key_type
|
692
|
-
@association.klass.column_types[@association.klass.primary_key].type
|
693
|
-
end
|
694
|
-
end
|
695
|
-
|
696
|
-
class HasManyThroughProxy < ReflectionProxy # :nodoc:
|
697
|
-
def rhs_key
|
698
|
-
@association.foreign_key
|
699
|
-
end
|
700
|
-
|
701
|
-
def lhs_key
|
702
|
-
@association.through_reflection.foreign_key
|
703
|
-
end
|
704
|
-
|
705
|
-
def join_table
|
706
|
-
@association.through_reflection.table_name
|
707
|
-
end
|
660
|
+
TableRows.new(
|
661
|
+
table_name,
|
662
|
+
model_class: model_class,
|
663
|
+
fixtures: fixtures,
|
664
|
+
config: config,
|
665
|
+
).to_hash
|
708
666
|
end
|
709
667
|
|
710
668
|
private
|
711
|
-
def primary_key_name
|
712
|
-
@primary_key_name ||= model_class && model_class.primary_key
|
713
|
-
end
|
714
|
-
|
715
|
-
def primary_key_type
|
716
|
-
@primary_key_type ||= model_class && model_class.column_types[model_class.primary_key].type
|
717
|
-
end
|
718
669
|
|
719
|
-
def
|
720
|
-
|
721
|
-
|
722
|
-
|
723
|
-
|
724
|
-
lhs_key = association.lhs_key
|
725
|
-
rhs_key = association.rhs_key
|
726
|
-
|
727
|
-
targets = targets.is_a?(Array) ? targets : targets.split(/\s*,\s*/)
|
728
|
-
rows[table_name].concat targets.map { |target|
|
729
|
-
{ lhs_key => row[primary_key_name],
|
730
|
-
rhs_key => ActiveRecord::FixtureSet.identify(target, column_type) }
|
731
|
-
}
|
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
|
732
675
|
end
|
733
676
|
end
|
734
677
|
|
735
|
-
|
736
|
-
|
737
|
-
|
738
|
-
|
739
|
-
|
740
|
-
def timestamp_column_names
|
741
|
-
@timestamp_column_names ||=
|
742
|
-
%w(created_at created_on updated_at updated_on) & column_names
|
743
|
-
end
|
744
|
-
|
745
|
-
def inheritance_column_name
|
746
|
-
@inheritance_column_name ||= model_class && model_class.inheritance_column
|
747
|
-
end
|
748
|
-
|
749
|
-
def column_names
|
750
|
-
@column_names ||= @connection.columns(@table_name).collect { |c| c.name }
|
751
|
-
end
|
752
|
-
|
753
|
-
def read_fixture_files(path, model_class)
|
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)
|
754
682
|
yaml_files = Dir["#{path}/{**,*}/*.yml"].select { |f|
|
755
683
|
::File.file?(f)
|
756
684
|
} + [yaml_file_path(path)]
|
757
685
|
|
758
686
|
yaml_files.each_with_object({}) do |file, fixtures|
|
759
687
|
FixtureSet::File.open(file) do |fh|
|
688
|
+
self.model_class ||= fh.model_class if fh.model_class
|
760
689
|
fh.each do |fixture_name, row|
|
761
690
|
fixtures[fixture_name] = ActiveRecord::Fixture.new(row, model_class)
|
762
691
|
end
|
@@ -767,15 +696,8 @@ module ActiveRecord
|
|
767
696
|
def yaml_file_path(path)
|
768
697
|
"#{path}.yml"
|
769
698
|
end
|
770
|
-
|
771
699
|
end
|
772
700
|
|
773
|
-
#--
|
774
|
-
# Deprecate 'Fixtures' in favor of 'FixtureSet'.
|
775
|
-
#++
|
776
|
-
# :nodoc:
|
777
|
-
Fixtures = ActiveSupport::Deprecation::DeprecatedConstantProxy.new('ActiveRecord::Fixtures', 'ActiveRecord::FixtureSet')
|
778
|
-
|
779
701
|
class Fixture #:nodoc:
|
780
702
|
include Enumerable
|
781
703
|
|
@@ -807,202 +729,9 @@ module ActiveRecord
|
|
807
729
|
alias :to_hash :fixture
|
808
730
|
|
809
731
|
def find
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
end
|
814
|
-
else
|
815
|
-
raise FixtureClassNotFound, "No class attached to find."
|
816
|
-
end
|
817
|
-
end
|
818
|
-
end
|
819
|
-
end
|
820
|
-
|
821
|
-
module ActiveRecord
|
822
|
-
module TestFixtures
|
823
|
-
extend ActiveSupport::Concern
|
824
|
-
|
825
|
-
def before_setup
|
826
|
-
setup_fixtures
|
827
|
-
super
|
828
|
-
end
|
829
|
-
|
830
|
-
def after_teardown
|
831
|
-
super
|
832
|
-
teardown_fixtures
|
833
|
-
end
|
834
|
-
|
835
|
-
included do
|
836
|
-
class_attribute :fixture_path, :instance_writer => false
|
837
|
-
class_attribute :fixture_table_names
|
838
|
-
class_attribute :fixture_class_names
|
839
|
-
class_attribute :use_transactional_fixtures
|
840
|
-
class_attribute :use_instantiated_fixtures # true, false, or :no_instances
|
841
|
-
class_attribute :pre_loaded_fixtures
|
842
|
-
class_attribute :config
|
843
|
-
|
844
|
-
self.fixture_table_names = []
|
845
|
-
self.use_transactional_fixtures = true
|
846
|
-
self.use_instantiated_fixtures = false
|
847
|
-
self.pre_loaded_fixtures = false
|
848
|
-
self.config = ActiveRecord::Base
|
849
|
-
|
850
|
-
self.fixture_class_names = Hash.new do |h, fixture_set_name|
|
851
|
-
h[fixture_set_name] = ActiveRecord::FixtureSet.default_fixture_model_name(fixture_set_name, self.config)
|
852
|
-
end
|
853
|
-
end
|
854
|
-
|
855
|
-
module ClassMethods
|
856
|
-
# Sets the model class for a fixture when the class name cannot be inferred from the fixture name.
|
857
|
-
#
|
858
|
-
# Examples:
|
859
|
-
#
|
860
|
-
# set_fixture_class some_fixture: SomeModel,
|
861
|
-
# 'namespaced/fixture' => Another::Model
|
862
|
-
#
|
863
|
-
# The keys must be the fixture names, that coincide with the short paths to the fixture files.
|
864
|
-
def set_fixture_class(class_names = {})
|
865
|
-
self.fixture_class_names = self.fixture_class_names.merge(class_names.stringify_keys)
|
866
|
-
end
|
867
|
-
|
868
|
-
def fixtures(*fixture_set_names)
|
869
|
-
if fixture_set_names.first == :all
|
870
|
-
fixture_set_names = Dir["#{fixture_path}/{**,*}/*.{yml}"]
|
871
|
-
fixture_set_names.map! { |f| f[(fixture_path.to_s.size + 1)..-5] }
|
872
|
-
else
|
873
|
-
fixture_set_names = fixture_set_names.flatten.map { |n| n.to_s }
|
874
|
-
end
|
875
|
-
|
876
|
-
self.fixture_table_names |= fixture_set_names
|
877
|
-
setup_fixture_accessors(fixture_set_names)
|
878
|
-
end
|
879
|
-
|
880
|
-
def setup_fixture_accessors(fixture_set_names = nil)
|
881
|
-
fixture_set_names = Array(fixture_set_names || fixture_table_names)
|
882
|
-
methods = Module.new do
|
883
|
-
fixture_set_names.each do |fs_name|
|
884
|
-
fs_name = fs_name.to_s
|
885
|
-
accessor_name = fs_name.tr('/', '_').to_sym
|
886
|
-
|
887
|
-
define_method(accessor_name) do |*fixture_names|
|
888
|
-
force_reload = fixture_names.pop if fixture_names.last == true || fixture_names.last == :reload
|
889
|
-
|
890
|
-
@fixture_cache[fs_name] ||= {}
|
891
|
-
|
892
|
-
instances = fixture_names.map do |f_name|
|
893
|
-
f_name = f_name.to_s
|
894
|
-
@fixture_cache[fs_name].delete(f_name) if force_reload
|
895
|
-
|
896
|
-
if @loaded_fixtures[fs_name][f_name]
|
897
|
-
@fixture_cache[fs_name][f_name] ||= @loaded_fixtures[fs_name][f_name].find
|
898
|
-
else
|
899
|
-
raise StandardError, "No fixture named '#{f_name}' found for fixture set '#{fs_name}'"
|
900
|
-
end
|
901
|
-
end
|
902
|
-
|
903
|
-
instances.size == 1 ? instances.first : instances
|
904
|
-
end
|
905
|
-
private accessor_name
|
906
|
-
end
|
907
|
-
end
|
908
|
-
include methods
|
909
|
-
end
|
910
|
-
|
911
|
-
def uses_transaction(*methods)
|
912
|
-
@uses_transaction = [] unless defined?(@uses_transaction)
|
913
|
-
@uses_transaction.concat methods.map { |m| m.to_s }
|
914
|
-
end
|
915
|
-
|
916
|
-
def uses_transaction?(method)
|
917
|
-
@uses_transaction = [] unless defined?(@uses_transaction)
|
918
|
-
@uses_transaction.include?(method.to_s)
|
919
|
-
end
|
920
|
-
end
|
921
|
-
|
922
|
-
def run_in_transaction?
|
923
|
-
use_transactional_fixtures &&
|
924
|
-
!self.class.uses_transaction?(method_name)
|
925
|
-
end
|
926
|
-
|
927
|
-
def setup_fixtures(config = ActiveRecord::Base)
|
928
|
-
if pre_loaded_fixtures && !use_transactional_fixtures
|
929
|
-
raise RuntimeError, 'pre_loaded_fixtures requires use_transactional_fixtures'
|
930
|
-
end
|
931
|
-
|
932
|
-
@fixture_cache = {}
|
933
|
-
@fixture_connections = []
|
934
|
-
@@already_loaded_fixtures ||= {}
|
935
|
-
|
936
|
-
# Load fixtures once and begin transaction.
|
937
|
-
if run_in_transaction?
|
938
|
-
if @@already_loaded_fixtures[self.class]
|
939
|
-
@loaded_fixtures = @@already_loaded_fixtures[self.class]
|
940
|
-
else
|
941
|
-
@loaded_fixtures = load_fixtures(config)
|
942
|
-
@@already_loaded_fixtures[self.class] = @loaded_fixtures
|
943
|
-
end
|
944
|
-
@fixture_connections = enlist_fixture_connections
|
945
|
-
@fixture_connections.each do |connection|
|
946
|
-
connection.begin_transaction joinable: false
|
947
|
-
end
|
948
|
-
# Load fixtures for every test.
|
949
|
-
else
|
950
|
-
ActiveRecord::FixtureSet.reset_cache
|
951
|
-
@@already_loaded_fixtures[self.class] = nil
|
952
|
-
@loaded_fixtures = load_fixtures(config)
|
953
|
-
end
|
954
|
-
|
955
|
-
# Instantiate fixtures for every test if requested.
|
956
|
-
instantiate_fixtures if use_instantiated_fixtures
|
957
|
-
end
|
958
|
-
|
959
|
-
def teardown_fixtures
|
960
|
-
# Rollback changes if a transaction is active.
|
961
|
-
if run_in_transaction?
|
962
|
-
@fixture_connections.each do |connection|
|
963
|
-
connection.rollback_transaction if connection.transaction_open?
|
964
|
-
end
|
965
|
-
@fixture_connections.clear
|
966
|
-
else
|
967
|
-
ActiveRecord::FixtureSet.reset_cache
|
968
|
-
end
|
969
|
-
|
970
|
-
ActiveRecord::Base.clear_active_connections!
|
971
|
-
end
|
972
|
-
|
973
|
-
def enlist_fixture_connections
|
974
|
-
ActiveRecord::Base.connection_handler.connection_pool_list.map(&:connection)
|
975
|
-
end
|
976
|
-
|
977
|
-
private
|
978
|
-
def load_fixtures(config)
|
979
|
-
fixtures = ActiveRecord::FixtureSet.create_fixtures(fixture_path, fixture_table_names, fixture_class_names, config)
|
980
|
-
Hash[fixtures.map { |f| [f.name, f] }]
|
981
|
-
end
|
982
|
-
|
983
|
-
def instantiate_fixtures
|
984
|
-
if pre_loaded_fixtures
|
985
|
-
raise RuntimeError, 'Load fixtures before instantiating them.' if ActiveRecord::FixtureSet.all_loaded_fixtures.empty?
|
986
|
-
ActiveRecord::FixtureSet.instantiate_all_loaded_fixtures(self, load_instances?)
|
987
|
-
else
|
988
|
-
raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
|
989
|
-
@loaded_fixtures.each_value do |fixture_set|
|
990
|
-
ActiveRecord::FixtureSet.instantiate_fixtures(self, fixture_set, load_instances?)
|
991
|
-
end
|
992
|
-
end
|
993
|
-
end
|
994
|
-
|
995
|
-
def load_instances?
|
996
|
-
use_instantiated_fixtures != :no_instances
|
997
|
-
end
|
998
|
-
end
|
999
|
-
end
|
1000
|
-
|
1001
|
-
class ActiveRecord::FixtureSet::RenderContext # :nodoc:
|
1002
|
-
def self.create_subclass
|
1003
|
-
Class.new ActiveRecord::FixtureSet.context_class do
|
1004
|
-
def get_binding
|
1005
|
-
binding()
|
732
|
+
raise FixtureClassNotFound, "No class attached to find." unless model_class
|
733
|
+
model_class.unscoped do
|
734
|
+
model_class.find(fixture[model_class.primary_key])
|
1006
735
|
end
|
1007
736
|
end
|
1008
737
|
end
|