ibm_db 3.0.5-x86-mingw32 → 4.0.0-x86-mingw32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGES +4 -0
- data/LICENSE +1 -1
- data/MANIFEST +14 -14
- data/ParameterizedQueries README +6 -6
- data/README +208 -225
- data/ext/Makefile.nt32 +181 -181
- data/ext/Makefile.nt32.191 +212 -212
- data/ext/extconf.rb +291 -291
- data/ext/ibm_db.c +11887 -11887
- data/ext/ruby_ibm_db.h +241 -241
- data/ext/ruby_ibm_db_cli.c +866 -866
- data/ext/ruby_ibm_db_cli.h +500 -500
- data/init.rb +41 -41
- data/lib/IBM_DB.rb +27 -27
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +3452 -3177
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +5 -2
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
- data/lib/mswin32/ibm_db.rb +91 -123
- data/lib/mswin32/rb2x/i386/ibm_db.so +0 -0
- data/test/active_record/connection_adapters/fake_adapter.rb +49 -46
- data/test/assets/example.log +1 -1
- data/test/assets/test.txt +1 -1
- data/test/cases/adapter_test.rb +351 -276
- data/test/cases/adapters/mysql2/active_schema_test.rb +193 -0
- data/test/cases/adapters/mysql2/bind_parameter_test.rb +50 -0
- data/test/cases/adapters/mysql2/boolean_test.rb +100 -0
- data/test/cases/adapters/mysql2/case_sensitivity_test.rb +63 -0
- data/test/cases/adapters/mysql2/charset_collation_test.rb +54 -0
- data/test/cases/adapters/mysql2/connection_test.rb +210 -0
- data/test/cases/adapters/mysql2/datetime_precision_quoting_test.rb +45 -0
- data/test/cases/adapters/mysql2/enum_test.rb +26 -0
- data/test/cases/adapters/mysql2/explain_test.rb +21 -0
- data/test/cases/adapters/mysql2/json_test.rb +195 -0
- data/test/cases/adapters/mysql2/mysql2_adapter_test.rb +83 -0
- data/test/cases/adapters/mysql2/reserved_word_test.rb +152 -0
- data/test/cases/adapters/mysql2/schema_migrations_test.rb +59 -0
- data/test/cases/adapters/mysql2/schema_test.rb +126 -0
- data/test/cases/adapters/mysql2/sp_test.rb +36 -0
- data/test/cases/adapters/mysql2/sql_types_test.rb +14 -0
- data/test/cases/adapters/mysql2/table_options_test.rb +42 -0
- data/test/cases/adapters/mysql2/unsigned_type_test.rb +66 -0
- data/test/cases/adapters/postgresql/active_schema_test.rb +98 -0
- data/test/cases/adapters/postgresql/array_test.rb +339 -0
- data/test/cases/adapters/postgresql/bit_string_test.rb +82 -0
- data/test/cases/adapters/postgresql/bytea_test.rb +134 -0
- data/test/cases/adapters/postgresql/case_insensitive_test.rb +26 -0
- data/test/cases/adapters/postgresql/change_schema_test.rb +38 -0
- data/test/cases/adapters/postgresql/cidr_test.rb +25 -0
- data/test/cases/adapters/postgresql/citext_test.rb +78 -0
- data/test/cases/adapters/postgresql/collation_test.rb +53 -0
- data/test/cases/adapters/postgresql/composite_test.rb +132 -0
- data/test/cases/adapters/postgresql/connection_test.rb +257 -0
- data/test/cases/adapters/postgresql/datatype_test.rb +92 -0
- data/test/cases/adapters/postgresql/domain_test.rb +47 -0
- data/test/cases/adapters/postgresql/enum_test.rb +91 -0
- data/test/cases/adapters/postgresql/explain_test.rb +20 -0
- data/test/cases/adapters/postgresql/extension_migration_test.rb +63 -0
- data/test/cases/adapters/postgresql/full_text_test.rb +44 -0
- data/test/cases/adapters/postgresql/geometric_test.rb +378 -0
- data/test/cases/adapters/postgresql/hstore_test.rb +382 -0
- data/test/cases/adapters/postgresql/infinity_test.rb +69 -0
- data/test/cases/adapters/postgresql/integer_test.rb +25 -0
- data/test/cases/adapters/postgresql/json_test.rb +237 -0
- data/test/cases/adapters/postgresql/ltree_test.rb +53 -0
- data/test/cases/adapters/postgresql/money_test.rb +96 -0
- data/test/cases/adapters/postgresql/network_test.rb +94 -0
- data/test/cases/adapters/postgresql/numbers_test.rb +49 -0
- data/test/cases/adapters/postgresql/postgresql_adapter_test.rb +405 -0
- data/test/cases/adapters/postgresql/prepared_statements_test.rb +22 -0
- data/test/cases/adapters/postgresql/quoting_test.rb +44 -0
- data/test/cases/adapters/postgresql/range_test.rb +343 -0
- data/test/cases/adapters/postgresql/referential_integrity_test.rb +111 -0
- data/test/cases/adapters/postgresql/rename_table_test.rb +34 -0
- data/test/cases/adapters/postgresql/schema_authorization_test.rb +119 -0
- data/test/cases/adapters/postgresql/schema_test.rb +597 -0
- data/test/cases/adapters/postgresql/serial_test.rb +154 -0
- data/test/cases/adapters/postgresql/statement_pool_test.rb +41 -0
- data/test/cases/adapters/postgresql/timestamp_test.rb +90 -0
- data/test/cases/adapters/postgresql/type_lookup_test.rb +33 -0
- data/test/cases/adapters/postgresql/utils_test.rb +62 -0
- data/test/cases/adapters/postgresql/uuid_test.rb +294 -0
- data/test/cases/adapters/postgresql/xml_test.rb +54 -0
- data/test/cases/adapters/sqlite3/collation_test.rb +53 -0
- data/test/cases/adapters/sqlite3/copy_table_test.rb +98 -0
- data/test/cases/adapters/sqlite3/explain_test.rb +21 -0
- data/test/cases/adapters/sqlite3/quoting_test.rb +101 -0
- data/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +441 -0
- data/test/cases/adapters/sqlite3/sqlite3_create_folder_test.rb +24 -0
- data/test/cases/adapters/sqlite3/statement_pool_test.rb +20 -0
- data/test/cases/aggregations_test.rb +168 -158
- data/test/cases/ar_schema_test.rb +146 -161
- data/test/cases/associations/association_scope_test.rb +16 -21
- data/test/cases/associations/belongs_to_associations_test.rb +1141 -1029
- data/test/cases/associations/bidirectional_destroy_dependencies_test.rb +41 -0
- data/test/cases/associations/callbacks_test.rb +190 -192
- data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
- data/test/cases/associations/eager_load_nested_include_test.rb +126 -128
- data/test/cases/associations/eager_singularization_test.rb +148 -148
- data/test/cases/associations/eager_test.rb +1514 -1429
- data/test/cases/associations/extension_test.rb +87 -82
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +1004 -972
- data/test/cases/associations/has_many_associations_test.rb +2501 -2182
- data/test/cases/associations/has_many_through_associations_test.rb +1271 -1204
- data/test/cases/associations/has_one_associations_test.rb +707 -610
- data/test/cases/associations/has_one_through_associations_test.rb +383 -380
- data/test/cases/associations/inner_join_association_test.rb +139 -139
- data/test/cases/associations/inverse_associations_test.rb +733 -706
- data/test/cases/associations/join_model_test.rb +777 -754
- data/test/cases/associations/left_outer_join_association_test.rb +88 -0
- data/test/cases/associations/nested_through_associations_test.rb +579 -579
- data/test/cases/associations/required_test.rb +102 -82
- data/test/cases/associations_test.rb +385 -380
- data/test/cases/attribute_decorators_test.rb +125 -125
- data/test/cases/attribute_methods/read_test.rb +60 -60
- data/test/cases/attribute_methods_test.rb +1009 -952
- data/test/cases/attribute_set_test.rb +270 -210
- data/test/cases/attribute_test.rb +246 -180
- data/test/cases/attributes_test.rb +253 -136
- data/test/cases/autosave_association_test.rb +1708 -1595
- data/test/cases/base_test.rb +1713 -1664
- data/test/cases/batches_test.rb +489 -212
- data/test/cases/binary_test.rb +44 -52
- data/test/cases/bind_parameter_test.rb +110 -100
- data/test/cases/cache_key_test.rb +25 -0
- data/test/cases/calculations_test.rb +798 -646
- data/test/cases/callbacks_test.rb +636 -543
- data/test/cases/clone_test.rb +40 -40
- data/test/cases/coders/json_test.rb +15 -0
- data/test/cases/coders/yaml_column_test.rb +63 -63
- data/test/cases/collection_cache_key_test.rb +115 -0
- data/test/cases/column_alias_test.rb +17 -17
- data/test/cases/column_definition_test.rb +92 -123
- data/test/cases/comment_test.rb +143 -0
- data/test/cases/connection_adapters/adapter_leasing_test.rb +56 -54
- data/test/cases/connection_adapters/connection_handler_test.rb +160 -53
- data/test/cases/connection_adapters/connection_specification_test.rb +12 -12
- data/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +255 -293
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +69 -65
- data/test/cases/connection_adapters/quoting_test.rb +13 -13
- data/test/cases/connection_adapters/schema_cache_test.rb +61 -56
- data/test/cases/connection_adapters/type_lookup_test.rb +118 -110
- data/test/cases/connection_management_test.rb +112 -122
- data/test/cases/connection_pool_test.rb +521 -346
- data/test/cases/connection_specification/resolver_test.rb +131 -116
- data/test/cases/core_test.rb +112 -112
- data/test/cases/counter_cache_test.rb +214 -209
- data/test/cases/custom_locking_test.rb +17 -17
- data/test/cases/database_statements_test.rb +34 -19
- data/test/cases/{invalid_date_test.rb → date_test.rb} +44 -32
- data/test/cases/date_time_precision_test.rb +106 -0
- data/test/cases/date_time_test.rb +61 -61
- data/test/cases/defaults_test.rb +218 -223
- data/test/cases/dirty_test.rb +763 -785
- data/test/cases/disconnected_test.rb +30 -28
- data/test/cases/dup_test.rb +157 -157
- data/test/cases/enum_test.rb +444 -290
- data/test/cases/errors_test.rb +16 -0
- data/test/cases/explain_subscriber_test.rb +64 -64
- data/test/cases/explain_test.rb +87 -76
- data/test/cases/finder_respond_to_test.rb +60 -60
- data/test/cases/finder_test.rb +1294 -1169
- data/test/cases/fixture_set/file_test.rb +156 -138
- data/test/cases/fixtures_test.rb +988 -908
- data/test/cases/forbidden_attributes_protection_test.rb +165 -99
- data/test/cases/habtm_destroy_order_test.rb +61 -61
- data/test/cases/helper.rb +204 -210
- data/test/cases/hot_compatibility_test.rb +142 -54
- data/test/cases/i18n_test.rb +45 -45
- data/test/cases/inheritance_test.rb +606 -375
- data/test/cases/integration_test.rb +155 -139
- data/test/cases/invalid_connection_test.rb +24 -22
- data/test/cases/invertible_migration_test.rb +387 -295
- data/test/cases/json_serialization_test.rb +311 -302
- data/test/cases/locking_test.rb +493 -477
- data/test/cases/log_subscriber_test.rb +225 -136
- data/test/cases/migration/change_schema_test.rb +458 -512
- data/test/cases/migration/change_table_test.rb +256 -224
- data/test/cases/migration/column_attributes_test.rb +176 -192
- data/test/cases/migration/column_positioning_test.rb +56 -56
- data/test/cases/migration/columns_test.rb +310 -304
- data/test/cases/migration/command_recorder_test.rb +350 -305
- data/test/cases/migration/compatibility_test.rb +118 -0
- data/test/cases/migration/create_join_table_test.rb +157 -148
- data/test/cases/migration/foreign_key_test.rb +360 -328
- data/test/cases/migration/helper.rb +39 -39
- data/test/cases/migration/index_test.rb +218 -216
- data/test/cases/migration/logger_test.rb +36 -36
- data/test/cases/migration/pending_migrations_test.rb +52 -53
- data/test/cases/migration/references_foreign_key_test.rb +216 -169
- data/test/cases/migration/references_index_test.rb +101 -101
- data/test/cases/migration/references_statements_test.rb +136 -116
- data/test/cases/migration/rename_table_test.rb +93 -93
- data/test/cases/migration_test.rb +1157 -959
- data/test/cases/migrator_test.rb +470 -388
- data/test/cases/mixin_test.rb +68 -70
- data/test/cases/modules_test.rb +172 -173
- data/test/cases/multiparameter_attributes_test.rb +372 -350
- data/test/cases/multiple_db_test.rb +122 -115
- data/test/cases/nested_attributes_test.rb +1098 -1070
- data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
- data/test/cases/persistence_test.rb +1001 -909
- data/test/cases/pooled_connections_test.rb +81 -81
- data/test/cases/primary_keys_test.rb +376 -237
- data/test/cases/query_cache_test.rb +446 -326
- data/test/cases/quoting_test.rb +202 -156
- data/test/cases/readonly_test.rb +119 -118
- data/test/cases/reaper_test.rb +85 -85
- data/test/cases/reflection_test.rb +509 -463
- data/test/cases/relation/delegation_test.rb +63 -68
- data/test/cases/relation/merging_test.rb +157 -161
- data/test/cases/relation/mutation_test.rb +183 -165
- data/test/cases/relation/or_test.rb +92 -0
- data/test/cases/relation/predicate_builder_test.rb +16 -14
- data/test/cases/relation/record_fetch_warning_test.rb +40 -0
- data/test/cases/relation/where_chain_test.rb +105 -181
- data/test/cases/relation/where_clause_test.rb +182 -0
- data/test/cases/relation/where_test.rb +322 -300
- data/test/cases/relation_test.rb +328 -319
- data/test/cases/relations_test.rb +2026 -1815
- data/test/cases/reload_models_test.rb +22 -22
- data/test/cases/result_test.rb +90 -80
- data/test/cases/sanitize_test.rb +176 -83
- data/test/cases/schema_dumper_test.rb +457 -463
- data/test/cases/schema_loading_test.rb +52 -0
- data/test/cases/scoping/default_scoping_test.rb +528 -454
- data/test/cases/scoping/named_scoping_test.rb +561 -524
- data/test/cases/scoping/relation_scoping_test.rb +400 -357
- data/test/cases/secure_token_test.rb +32 -0
- data/test/cases/serialization_test.rb +104 -104
- data/test/cases/serialized_attribute_test.rb +364 -277
- data/test/cases/statement_cache_test.rb +136 -98
- data/test/cases/store_test.rb +195 -194
- data/test/cases/suppressor_test.rb +63 -0
- data/test/cases/tasks/database_tasks_test.rb +462 -398
- data/test/cases/tasks/mysql_rake_test.rb +345 -324
- data/test/cases/tasks/postgresql_rake_test.rb +304 -250
- data/test/cases/tasks/sqlite_rake_test.rb +220 -193
- data/test/cases/test_case.rb +131 -123
- data/test/cases/test_fixtures_test.rb +36 -0
- data/test/cases/time_precision_test.rb +102 -0
- data/test/cases/timestamp_test.rb +501 -467
- data/test/cases/touch_later_test.rb +121 -0
- data/test/cases/transaction_callbacks_test.rb +518 -452
- data/test/cases/transaction_isolation_test.rb +106 -106
- data/test/cases/transactions_test.rb +834 -817
- data/test/cases/type/adapter_specific_registry_test.rb +133 -0
- data/test/cases/type/date_time_test.rb +14 -0
- data/test/cases/type/integer_test.rb +27 -121
- data/test/cases/type/string_test.rb +22 -36
- data/test/cases/type/type_map_test.rb +177 -177
- data/test/cases/type_test.rb +39 -0
- data/test/cases/types_test.rb +24 -141
- data/test/cases/unconnected_test.rb +33 -33
- data/test/cases/validations/absence_validation_test.rb +73 -0
- data/test/cases/validations/association_validation_test.rb +97 -86
- data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
- data/test/cases/validations/i18n_validation_test.rb +86 -90
- data/test/cases/validations/length_validation_test.rb +79 -47
- data/test/cases/validations/presence_validation_test.rb +103 -68
- data/test/cases/validations/uniqueness_validation_test.rb +548 -457
- data/test/cases/validations_repair_helper.rb +19 -23
- data/test/cases/validations_test.rb +194 -165
- data/test/cases/view_test.rb +216 -119
- data/test/cases/yaml_serialization_test.rb +121 -126
- data/test/config.example.yml +97 -0
- data/test/config.rb +5 -5
- data/test/fixtures/accounts.yml +29 -29
- data/test/fixtures/admin/accounts.yml +2 -2
- data/test/fixtures/admin/users.yml +10 -10
- data/test/fixtures/author_addresses.original +11 -0
- data/test/fixtures/author_addresses.yml +17 -17
- data/test/fixtures/author_favorites.yml +3 -3
- data/test/fixtures/authors.original +17 -0
- data/test/fixtures/authors.yml +23 -23
- data/test/fixtures/bad_posts.yml +9 -0
- data/test/fixtures/binaries.yml +133 -133
- data/test/fixtures/books.yml +31 -11
- data/test/fixtures/bulbs.yml +5 -5
- data/test/fixtures/cars.yml +9 -9
- data/test/fixtures/categories.yml +19 -19
- data/test/fixtures/categories/special_categories.yml +9 -9
- data/test/fixtures/categories/subsubdir/arbitrary_filename.yml +4 -4
- data/test/fixtures/categories_ordered.yml +7 -7
- data/test/fixtures/categories_posts.yml +31 -31
- data/test/fixtures/categorizations.yml +23 -23
- data/test/fixtures/clubs.yml +8 -8
- data/test/fixtures/collections.yml +3 -3
- data/test/fixtures/colleges.yml +3 -3
- data/test/fixtures/comments.yml +65 -65
- data/test/fixtures/companies.yml +67 -67
- data/test/fixtures/computers.yml +10 -10
- data/test/fixtures/content.yml +3 -0
- data/test/fixtures/content_positions.yml +3 -0
- data/test/fixtures/courses.yml +8 -8
- data/test/fixtures/customers.yml +25 -25
- data/test/fixtures/dashboards.yml +6 -6
- data/test/fixtures/dead_parrots.yml +5 -0
- data/test/fixtures/developers.yml +22 -22
- data/test/fixtures/developers_projects.yml +16 -16
- data/test/fixtures/dog_lovers.yml +7 -7
- data/test/fixtures/dogs.yml +4 -4
- data/test/fixtures/doubloons.yml +3 -3
- data/test/fixtures/edges.yml +5 -5
- data/test/fixtures/entrants.yml +14 -14
- data/test/fixtures/essays.yml +6 -6
- data/test/fixtures/faces.yml +11 -11
- data/test/fixtures/fk_test_has_fk.yml +3 -3
- data/test/fixtures/fk_test_has_pk.yml +1 -1
- data/test/fixtures/friendships.yml +4 -4
- data/test/fixtures/funny_jokes.yml +10 -10
- data/test/fixtures/interests.yml +33 -33
- data/test/fixtures/items.yml +3 -3
- data/test/fixtures/jobs.yml +7 -7
- data/test/fixtures/legacy_things.yml +3 -3
- data/test/fixtures/live_parrots.yml +4 -0
- data/test/fixtures/mateys.yml +4 -4
- data/test/fixtures/member_details.yml +8 -8
- data/test/fixtures/member_types.yml +6 -6
- data/test/fixtures/members.yml +11 -11
- data/test/fixtures/memberships.yml +34 -34
- data/test/fixtures/men.yml +5 -5
- data/test/fixtures/minimalistics.yml +2 -2
- data/test/fixtures/minivans.yml +5 -5
- data/test/fixtures/mixed_case_monkeys.yml +6 -6
- data/test/fixtures/mixins.yml +29 -29
- data/test/fixtures/movies.yml +7 -7
- data/test/fixtures/naked/yml/accounts.yml +1 -1
- data/test/fixtures/naked/yml/companies.yml +1 -1
- data/test/fixtures/naked/yml/courses.yml +1 -1
- data/test/fixtures/naked/yml/parrots.yml +2 -0
- data/test/fixtures/naked/yml/trees.yml +3 -0
- data/test/fixtures/nodes.yml +29 -0
- data/test/fixtures/organizations.yml +5 -5
- data/test/fixtures/other_comments.yml +6 -0
- data/test/fixtures/other_dogs.yml +2 -0
- data/test/fixtures/other_posts.yml +7 -0
- data/test/fixtures/other_topics.yml +42 -42
- data/test/fixtures/owners.yml +9 -9
- data/test/fixtures/parrots.yml +27 -27
- data/test/fixtures/parrots_pirates.yml +7 -7
- data/test/fixtures/people.yml +24 -24
- data/test/fixtures/peoples_treasures.yml +3 -3
- data/test/fixtures/pets.yml +19 -19
- data/test/fixtures/pirates.yml +15 -12
- data/test/fixtures/posts.yml +80 -80
- data/test/fixtures/price_estimates.yml +16 -7
- data/test/fixtures/products.yml +4 -4
- data/test/fixtures/projects.yml +7 -7
- data/test/fixtures/ratings.yml +14 -14
- data/test/fixtures/readers.yml +11 -11
- data/test/fixtures/references.yml +17 -17
- data/test/fixtures/reserved_words/distinct.yml +5 -5
- data/test/fixtures/reserved_words/distinct_select.yml +11 -11
- data/test/fixtures/reserved_words/group.yml +14 -14
- data/test/fixtures/reserved_words/select.yml +8 -8
- data/test/fixtures/reserved_words/values.yml +7 -7
- data/test/fixtures/ships.yml +6 -6
- data/test/fixtures/speedometers.yml +8 -8
- data/test/fixtures/sponsors.yml +12 -12
- data/test/fixtures/string_key_objects.yml +7 -7
- data/test/fixtures/subscribers.yml +10 -10
- data/test/fixtures/subscriptions.yml +12 -12
- data/test/fixtures/taggings.yml +78 -78
- data/test/fixtures/tags.yml +11 -11
- data/test/fixtures/tasks.yml +7 -7
- data/test/fixtures/teapots.yml +3 -3
- data/test/fixtures/to_be_linked/accounts.yml +2 -2
- data/test/fixtures/to_be_linked/users.yml +10 -10
- data/test/fixtures/topics.yml +49 -49
- data/test/fixtures/toys.yml +14 -14
- data/test/fixtures/traffic_lights.yml +9 -9
- data/test/fixtures/treasures.yml +10 -10
- data/test/fixtures/trees.yml +3 -0
- data/test/fixtures/uuid_children.yml +3 -3
- data/test/fixtures/uuid_parents.yml +2 -2
- data/test/fixtures/variants.yml +4 -4
- data/test/fixtures/vegetables.yml +19 -19
- data/test/fixtures/vertices.yml +3 -3
- data/test/fixtures/warehouse_things.yml +2 -2
- data/test/fixtures/zines.yml +5 -5
- data/test/migrations/10_urban/9_add_expressions.rb +11 -11
- data/test/migrations/decimal/1_give_me_big_numbers.rb +15 -15
- data/test/migrations/magic/1_currencies_have_symbols.rb +12 -12
- data/test/migrations/missing/1000_people_have_middle_names.rb +9 -9
- data/test/migrations/missing/1_people_have_last_names.rb +9 -9
- data/test/migrations/missing/3_we_need_reminders.rb +12 -12
- data/test/migrations/missing/4_innocent_jointable.rb +12 -12
- data/test/migrations/rename/1_we_need_things.rb +11 -11
- data/test/migrations/rename/2_rename_things.rb +9 -9
- data/test/migrations/to_copy/1_people_have_hobbies.rb +9 -9
- data/test/migrations/to_copy/2_people_have_descriptions.rb +9 -9
- data/test/migrations/to_copy2/1_create_articles.rb +7 -7
- data/test/migrations/to_copy2/2_create_comments.rb +7 -7
- data/test/migrations/to_copy_with_name_collision/1_people_have_hobbies.rb +9 -9
- data/test/migrations/to_copy_with_timestamps/20090101010101_people_have_hobbies.rb +9 -9
- data/test/migrations/to_copy_with_timestamps/20090101010202_people_have_descriptions.rb +9 -9
- data/test/migrations/to_copy_with_timestamps2/20090101010101_create_articles.rb +7 -7
- data/test/migrations/to_copy_with_timestamps2/20090101010202_create_comments.rb +7 -7
- data/test/migrations/valid/1_valid_people_have_last_names.rb +9 -9
- data/test/migrations/valid/2_we_need_reminders.rb +12 -12
- data/test/migrations/valid/3_innocent_jointable.rb +12 -12
- data/test/migrations/valid_with_subdirectories/1_valid_people_have_last_names.rb +9 -9
- data/test/migrations/valid_with_subdirectories/sub/2_we_need_reminders.rb +12 -12
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +12 -12
- data/test/migrations/valid_with_timestamps/20100101010101_valid_with_timestamps_people_have_last_names.rb +9 -9
- data/test/migrations/valid_with_timestamps/20100201010101_valid_with_timestamps_we_need_reminders.rb +12 -12
- data/test/migrations/valid_with_timestamps/20100301010101_valid_with_timestamps_innocent_jointable.rb +12 -12
- data/test/migrations/version_check/20131219224947_migration_version_check.rb +8 -8
- data/test/models/admin.rb +5 -5
- data/test/models/admin/account.rb +3 -3
- data/test/models/admin/randomly_named_c1.rb +6 -2
- data/test/models/admin/user.rb +40 -40
- data/test/models/aircraft.rb +5 -4
- data/test/models/arunit2_model.rb +3 -3
- data/test/models/author.rb +209 -212
- data/test/models/auto_id.rb +4 -4
- data/test/models/autoloadable/extra_firm.rb +2 -2
- data/test/models/binary.rb +2 -2
- data/test/models/bird.rb +12 -12
- data/test/models/book.rb +23 -18
- data/test/models/boolean.rb +2 -2
- data/test/models/bulb.rb +52 -51
- data/test/models/cake_designer.rb +3 -3
- data/test/models/car.rb +29 -26
- data/test/models/carrier.rb +2 -2
- data/test/models/cat.rb +10 -0
- data/test/models/categorization.rb +19 -19
- data/test/models/category.rb +35 -35
- data/test/models/chef.rb +8 -7
- data/test/models/citation.rb +3 -3
- data/test/models/club.rb +25 -23
- data/test/models/college.rb +10 -10
- data/test/models/column.rb +3 -3
- data/test/models/column_name.rb +3 -3
- data/test/models/comment.rb +76 -64
- data/test/models/company.rb +230 -228
- data/test/models/company_in_module.rb +98 -98
- data/test/models/computer.rb +3 -3
- data/test/models/contact.rb +41 -41
- data/test/models/content.rb +40 -0
- data/test/models/contract.rb +20 -20
- data/test/models/country.rb +7 -7
- data/test/models/course.rb +6 -6
- data/test/models/customer.rb +83 -77
- data/test/models/customer_carrier.rb +14 -14
- data/test/models/dashboard.rb +3 -3
- data/test/models/default.rb +2 -2
- data/test/models/department.rb +4 -4
- data/test/models/developer.rb +274 -255
- data/test/models/dog.rb +5 -5
- data/test/models/dog_lover.rb +5 -5
- data/test/models/doubloon.rb +12 -12
- data/test/models/drink_designer.rb +3 -3
- data/test/models/edge.rb +5 -5
- data/test/models/electron.rb +5 -5
- data/test/models/engine.rb +4 -4
- data/test/models/entrant.rb +3 -3
- data/test/models/essay.rb +5 -5
- data/test/models/event.rb +3 -3
- data/test/models/eye.rb +37 -37
- data/test/models/face.rb +9 -9
- data/test/models/friendship.rb +6 -6
- data/test/models/guid.rb +2 -2
- data/test/models/guitar.rb +4 -0
- data/test/models/hotel.rb +11 -9
- data/test/models/image.rb +3 -3
- data/test/models/interest.rb +5 -5
- data/test/models/invoice.rb +4 -4
- data/test/models/item.rb +7 -7
- data/test/models/job.rb +7 -7
- data/test/models/joke.rb +7 -7
- data/test/models/keyboard.rb +3 -3
- data/test/models/legacy_thing.rb +3 -3
- data/test/models/lesson.rb +11 -11
- data/test/models/line_item.rb +3 -3
- data/test/models/liquid.rb +4 -4
- data/test/models/man.rb +11 -11
- data/test/models/matey.rb +4 -4
- data/test/models/member.rb +42 -41
- data/test/models/member_detail.rb +8 -7
- data/test/models/member_type.rb +3 -3
- data/test/models/membership.rb +35 -35
- data/test/models/mentor.rb +3 -0
- data/test/models/minimalistic.rb +2 -2
- data/test/models/minivan.rb +9 -9
- data/test/models/mixed_case_monkey.rb +3 -3
- data/test/models/mocktail_designer.rb +2 -0
- data/test/models/molecule.rb +6 -6
- data/test/models/movie.rb +5 -5
- data/test/models/node.rb +5 -0
- data/test/models/non_primary_key.rb +2 -0
- data/test/models/notification.rb +3 -0
- data/test/models/order.rb +4 -4
- data/test/models/organization.rb +14 -14
- data/test/models/other_dog.rb +5 -0
- data/test/models/owner.rb +37 -34
- data/test/models/parrot.rb +28 -29
- data/test/models/person.rb +142 -143
- data/test/models/personal_legacy_thing.rb +4 -4
- data/test/models/pet.rb +18 -15
- data/test/models/pet_treasure.rb +6 -0
- data/test/models/pirate.rb +92 -92
- data/test/models/possession.rb +3 -3
- data/test/models/post.rb +273 -264
- data/test/models/price_estimate.rb +4 -4
- data/test/models/professor.rb +5 -5
- data/test/models/project.rb +40 -31
- data/test/models/publisher.rb +2 -2
- data/test/models/publisher/article.rb +4 -4
- data/test/models/publisher/magazine.rb +3 -3
- data/test/models/randomly_named_c1.rb +1 -1
- data/test/models/rating.rb +4 -4
- data/test/models/reader.rb +23 -23
- data/test/models/recipe.rb +3 -0
- data/test/models/record.rb +2 -2
- data/test/models/reference.rb +22 -22
- data/test/models/reply.rb +61 -61
- data/test/models/ship.rb +39 -33
- data/test/models/ship_part.rb +8 -8
- data/test/models/shop.rb +17 -17
- data/test/models/shop_account.rb +6 -6
- data/test/models/speedometer.rb +6 -6
- data/test/models/sponsor.rb +7 -7
- data/test/models/string_key_object.rb +3 -3
- data/test/models/student.rb +4 -4
- data/test/models/subject.rb +16 -16
- data/test/models/subscriber.rb +8 -8
- data/test/models/subscription.rb +4 -4
- data/test/models/tag.rb +13 -7
- data/test/models/tagging.rb +13 -13
- data/test/models/task.rb +5 -5
- data/test/models/topic.rb +118 -124
- data/test/models/toy.rb +6 -6
- data/test/models/traffic_light.rb +4 -4
- data/test/models/treasure.rb +14 -14
- data/test/models/treaty.rb +7 -7
- data/test/models/tree.rb +3 -0
- data/test/models/tuning_peg.rb +4 -0
- data/test/models/tyre.rb +11 -11
- data/test/models/user.rb +14 -0
- data/test/models/uuid_child.rb +3 -3
- data/test/models/uuid_item.rb +6 -0
- data/test/models/uuid_parent.rb +3 -3
- data/test/models/vegetables.rb +24 -24
- data/test/models/vehicle.rb +6 -6
- data/test/models/vertex.rb +9 -9
- data/test/models/warehouse_thing.rb +5 -5
- data/test/models/wheel.rb +3 -3
- data/test/models/without_table.rb +3 -3
- data/test/models/zine.rb +3 -3
- data/test/schema/mysql2_specific_schema.rb +68 -58
- data/test/schema/oracle_specific_schema.rb +40 -43
- data/test/schema/postgresql_specific_schema.rb +114 -202
- data/test/schema/schema.rb +1057 -952
- data/test/schema/schema.rb.original +1057 -0
- data/test/schema/sqlite_specific_schema.rb +18 -22
- data/test/support/config.rb +43 -43
- data/test/support/connection.rb +23 -22
- data/test/support/connection_helper.rb +14 -14
- data/test/support/ddl_helper.rb +8 -8
- data/test/support/schema_dumping_helper.rb +20 -20
- data/test/support/yaml_compatibility_fixtures/rails_4_1.yml +22 -0
- data/test/support/yaml_compatibility_fixtures/rails_4_2_0.yml +182 -0
- metadata +129 -28
- data/lib/mswin32/rb19x/ibm_db.so +0 -0
- data/lib/mswin32/rb21x/i386/ibm_db.so +0 -0
- data/lib/mswin32/rb22x/i386/ibm_db.so +0 -0
- data/lib/mswin32/rb23x/i386/ibm_db.so +0 -0
- data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +0 -26
- data/test/cases/attribute_methods/serialization_test.rb +0 -29
- data/test/cases/migration/change_schema_test - Copy.rb +0 -448
- data/test/cases/migration/foreign_key_test - Changed.rb +0 -325
- data/test/cases/migration/table_and_index_test.rb +0 -24
- data/test/cases/relation/where_test2.rb +0 -36
- data/test/cases/type/decimal_test.rb +0 -56
- data/test/cases/type/unsigned_integer_test.rb +0 -18
- data/test/cases/xml_serialization_test.rb +0 -457
- data/test/connections/native_ibm_db/connection.rb +0 -44
- data/test/fixtures/naked/csv/accounts.csv +0 -1
- data/test/schema/i5/ibm_db_specific_schema.rb +0 -137
- data/test/schema/ids/ibm_db_specific_schema.rb +0 -140
- data/test/schema/luw/ibm_db_specific_schema.rb +0 -137
- data/test/schema/mysql_specific_schema.rb +0 -70
- data/test/schema/zOS/ibm_db_specific_schema.rb +0 -208
@@ -0,0 +1,88 @@
|
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/post'
|
3
|
+
require 'models/comment'
|
4
|
+
require 'models/author'
|
5
|
+
require 'models/essay'
|
6
|
+
require 'models/categorization'
|
7
|
+
require 'models/person'
|
8
|
+
|
9
|
+
class LeftOuterJoinAssociationTest < ActiveRecord::TestCase
|
10
|
+
fixtures :authors, :essays, :posts, :comments, :categorizations, :people
|
11
|
+
|
12
|
+
def test_construct_finder_sql_applies_aliases_tables_on_association_conditions
|
13
|
+
result = Author.left_outer_joins(:thinking_posts, :welcome_posts).to_a
|
14
|
+
assert_equal authors(:david), result.first
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_construct_finder_sql_does_not_table_name_collide_on_duplicate_associations
|
18
|
+
assert_nothing_raised do
|
19
|
+
queries = capture_sql do
|
20
|
+
Person.left_outer_joins(:agents => {:agents => :agents})
|
21
|
+
.left_outer_joins(:agents => {:agents => {:primary_contact => :agents}}).to_a
|
22
|
+
end
|
23
|
+
assert queries.any? { |sql| /agents_people_4/i =~ sql }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_left_outer_joins_count_is_same_as_size_of_loaded_results
|
28
|
+
assert_equal 17, Post.left_outer_joins(:comments).to_a.size
|
29
|
+
assert_equal 17, Post.left_outer_joins(:comments).count
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_left_joins_aliases_left_outer_joins
|
33
|
+
assert_equal Post.left_outer_joins(:comments).to_sql, Post.left_joins(:comments).to_sql
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_left_outer_joins_return_has_value_for_every_comment
|
37
|
+
all_post_ids = Post.pluck(:id)
|
38
|
+
assert_equal all_post_ids, all_post_ids & Post.left_outer_joins(:comments).pluck(:id)
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_left_outer_joins_actually_does_a_left_outer_join
|
42
|
+
queries = capture_sql { Author.left_outer_joins(:posts).to_a }
|
43
|
+
assert queries.any? { |sql| /LEFT OUTER JOIN/i =~ sql }
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_construct_finder_sql_ignores_empty_left_outer_joins_hash
|
47
|
+
queries = capture_sql { Author.left_outer_joins({}).to_a }
|
48
|
+
assert queries.none? { |sql| /LEFT OUTER JOIN/i =~ sql }
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_construct_finder_sql_ignores_empty_left_outer_joins_array
|
52
|
+
queries = capture_sql { Author.left_outer_joins([]).to_a }
|
53
|
+
assert queries.none? { |sql| /LEFT OUTER JOIN/i =~ sql }
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_left_outer_joins_forbids_to_use_string_as_argument
|
57
|
+
assert_raise(ArgumentError){ Author.left_outer_joins('LEFT OUTER JOIN "posts" ON "posts"."user_id" = "users"."id"').to_a }
|
58
|
+
end
|
59
|
+
|
60
|
+
def test_join_conditions_added_to_join_clause
|
61
|
+
queries = capture_sql { Author.left_outer_joins(:essays).to_a }
|
62
|
+
assert queries.any? { |sql| /writer_type.*?=.*?(Author|\?|\$1)/i =~ sql }
|
63
|
+
assert queries.none? { |sql| /WHERE/i =~ sql }
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_find_with_sti_join
|
67
|
+
scope = Post.left_outer_joins(:special_comments).where(:id => posts(:sti_comments).id)
|
68
|
+
|
69
|
+
# The join should match SpecialComment and its subclasses only
|
70
|
+
assert scope.where("comments.type" => "Comment").empty?
|
71
|
+
assert !scope.where("comments.type" => "SpecialComment").empty?
|
72
|
+
assert !scope.where("comments.type" => "SubSpecialComment").empty?
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_does_not_override_select
|
76
|
+
authors = Author.select("authors.name, #{%{(authors.author_address_id || ' ' || authors.author_address_extra_id) as addr_id}}").left_outer_joins(:posts)
|
77
|
+
assert authors.any?
|
78
|
+
assert authors.first.respond_to?(:addr_id)
|
79
|
+
end
|
80
|
+
|
81
|
+
test "the default scope of the target is applied when joining associations" do
|
82
|
+
author = Author.create! name: "Jon"
|
83
|
+
author.categorizations.create!
|
84
|
+
author.categorizations.create! special: true
|
85
|
+
|
86
|
+
assert_equal [author], Author.where(id: author).left_outer_joins(:special_categorizations)
|
87
|
+
end
|
88
|
+
end
|
@@ -1,579 +1,579 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/author'
|
3
|
-
require 'models/post'
|
4
|
-
require 'models/person'
|
5
|
-
require 'models/reference'
|
6
|
-
require 'models/job'
|
7
|
-
require 'models/reader'
|
8
|
-
require 'models/comment'
|
9
|
-
require 'models/tag'
|
10
|
-
require 'models/tagging'
|
11
|
-
require 'models/subscriber'
|
12
|
-
require 'models/book'
|
13
|
-
require 'models/subscription'
|
14
|
-
require 'models/rating'
|
15
|
-
require 'models/member'
|
16
|
-
require 'models/member_detail'
|
17
|
-
require 'models/member_type'
|
18
|
-
require 'models/sponsor'
|
19
|
-
require 'models/club'
|
20
|
-
require 'models/organization'
|
21
|
-
require 'models/category'
|
22
|
-
require 'models/categorization'
|
23
|
-
require 'models/membership'
|
24
|
-
require 'models/essay'
|
25
|
-
|
26
|
-
class NestedThroughAssociationsTest < ActiveRecord::TestCase
|
27
|
-
fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings,
|
28
|
-
:people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details,
|
29
|
-
:member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts,
|
30
|
-
:categorizations, :memberships, :essays
|
31
|
-
|
32
|
-
# Through associations can either use the has_many or has_one macros.
|
33
|
-
#
|
34
|
-
# has_many
|
35
|
-
# - Source reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many
|
36
|
-
# - Through reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many
|
37
|
-
#
|
38
|
-
# has_one
|
39
|
-
# - Source reflection can be has_one or belongs_to
|
40
|
-
# - Through reflection can be has_one or belongs_to
|
41
|
-
#
|
42
|
-
# Additionally, the source reflection and/or through reflection may be subject to
|
43
|
-
# polymorphism and/or STI.
|
44
|
-
#
|
45
|
-
# When testing these, we need to make sure it works via loading the association directly, or
|
46
|
-
# joining the association, or including the association. We also need to ensure that associations
|
47
|
-
# are readonly where relevant.
|
48
|
-
|
49
|
-
# has_many through
|
50
|
-
# Source: has_many through
|
51
|
-
# Through: has_many
|
52
|
-
def test_has_many_through_has_many_with_has_many_through_source_reflection
|
53
|
-
general = tags(:general)
|
54
|
-
assert_equal [general, general], authors(:david).tags
|
55
|
-
end
|
56
|
-
|
57
|
-
def test_has_many_through_has_many_with_has_many_through_source_reflection_preload
|
58
|
-
authors = assert_queries(5) { Author.includes(:tags).to_a }
|
59
|
-
general = tags(:general)
|
60
|
-
|
61
|
-
assert_no_queries do
|
62
|
-
assert_equal [general, general], authors.first.tags
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_has_many_through_has_many_with_has_many_through_source_reflection_preload_via_joins
|
67
|
-
assert_includes_and_joins_equal(
|
68
|
-
Author.where('tags.id' => tags(:general).id),
|
69
|
-
[authors(:david)], :tags
|
70
|
-
)
|
71
|
-
|
72
|
-
# This ensures that the polymorphism of taggings is being observed correctly
|
73
|
-
authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel')
|
74
|
-
assert authors.empty?
|
75
|
-
end
|
76
|
-
|
77
|
-
# has_many through
|
78
|
-
# Source: has_many
|
79
|
-
# Through: has_many through
|
80
|
-
def test_has_many_through_has_many_through_with_has_many_source_reflection
|
81
|
-
luke, david = subscribers(:first), subscribers(:second)
|
82
|
-
assert_equal [luke, david, david], authors(:david).subscribers.order('subscribers.nick')
|
83
|
-
end
|
84
|
-
|
85
|
-
def test_has_many_through_has_many_through_with_has_many_source_reflection_preload
|
86
|
-
luke, david = subscribers(:first), subscribers(:second)
|
87
|
-
authors = assert_queries(4) { Author.includes(:subscribers).to_a }
|
88
|
-
assert_no_queries do
|
89
|
-
assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick)
|
90
|
-
end
|
91
|
-
end
|
92
|
-
|
93
|
-
def test_has_many_through_has_many_through_with_has_many_source_reflection_preload_via_joins
|
94
|
-
# All authors with subscribers where one of the subscribers' nick is 'alterself'
|
95
|
-
assert_includes_and_joins_equal(
|
96
|
-
Author.where('subscribers.nick' => 'alterself'),
|
97
|
-
[authors(:david)], :subscribers
|
98
|
-
)
|
99
|
-
end
|
100
|
-
|
101
|
-
# has_many through
|
102
|
-
# Source: has_one through
|
103
|
-
# Through: has_one
|
104
|
-
def test_has_many_through_has_one_with_has_one_through_source_reflection
|
105
|
-
assert_equal [member_types(:founding)], members(:groucho).nested_member_types
|
106
|
-
end
|
107
|
-
|
108
|
-
def test_has_many_through_has_one_with_has_one_through_source_reflection_preload
|
109
|
-
members = assert_queries(4) { Member.includes(:nested_member_types).to_a }
|
110
|
-
founding = member_types(:founding)
|
111
|
-
assert_no_queries do
|
112
|
-
assert_equal [founding], members.first.nested_member_types
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_has_many_through_has_one_with_has_one_through_source_reflection_preload_via_joins
|
117
|
-
assert_includes_and_joins_equal(
|
118
|
-
Member.where('member_types.id' => member_types(:founding).id),
|
119
|
-
[members(:groucho)], :nested_member_types
|
120
|
-
)
|
121
|
-
end
|
122
|
-
|
123
|
-
# has_many through
|
124
|
-
# Source: has_one
|
125
|
-
# Through: has_one through
|
126
|
-
def test_has_many_through_has_one_through_with_has_one_source_reflection
|
127
|
-
assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members(:groucho).nested_sponsors
|
128
|
-
end
|
129
|
-
|
130
|
-
def test_has_many_through_has_one_through_with_has_one_source_reflection_preload
|
131
|
-
members = assert_queries(4) { Member.includes(:nested_sponsors).to_a }
|
132
|
-
mustache = sponsors(:moustache_club_sponsor_for_groucho)
|
133
|
-
assert_no_queries(ignore_none: false) do
|
134
|
-
assert_equal [mustache], members.first.nested_sponsors
|
135
|
-
end
|
136
|
-
end
|
137
|
-
|
138
|
-
def test_has_many_through_has_one_through_with_has_one_source_reflection_preload_via_joins
|
139
|
-
assert_includes_and_joins_equal(
|
140
|
-
Member.where('sponsors.id' => sponsors(:moustache_club_sponsor_for_groucho).id),
|
141
|
-
[members(:groucho)], :nested_sponsors
|
142
|
-
)
|
143
|
-
end
|
144
|
-
|
145
|
-
# has_many through
|
146
|
-
# Source: has_many through
|
147
|
-
# Through: has_one
|
148
|
-
def test_has_many_through_has_one_with_has_many_through_source_reflection
|
149
|
-
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
150
|
-
|
151
|
-
assert_equal [groucho_details, other_details],
|
152
|
-
members(:groucho).organization_member_details.order('member_details.id')
|
153
|
-
end
|
154
|
-
|
155
|
-
def test_has_many_through_has_one_with_has_many_through_source_reflection_preload
|
156
|
-
ActiveRecord::Base.connection.table_alias_length # preheat cache
|
157
|
-
members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) }
|
158
|
-
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
159
|
-
|
160
|
-
assert_no_queries do
|
161
|
-
assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id)
|
162
|
-
end
|
163
|
-
end
|
164
|
-
|
165
|
-
def test_has_many_through_has_one_with_has_many_through_source_reflection_preload_via_joins
|
166
|
-
assert_includes_and_joins_equal(
|
167
|
-
Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'),
|
168
|
-
[members(:groucho), members(:some_other_guy)], :organization_member_details
|
169
|
-
)
|
170
|
-
|
171
|
-
members = Member.joins(:organization_member_details).
|
172
|
-
where('member_details.id' => 9)
|
173
|
-
assert members.empty?
|
174
|
-
end
|
175
|
-
|
176
|
-
# has_many through
|
177
|
-
# Source: has_many
|
178
|
-
# Through: has_one through
|
179
|
-
def test_has_many_through_has_one_through_with_has_many_source_reflection
|
180
|
-
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
181
|
-
|
182
|
-
assert_equal [groucho_details, other_details],
|
183
|
-
members(:groucho).organization_member_details_2.order('member_details.id')
|
184
|
-
end
|
185
|
-
|
186
|
-
def test_has_many_through_has_one_through_with_has_many_source_reflection_preload
|
187
|
-
members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) }
|
188
|
-
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
189
|
-
|
190
|
-
# postgresql test if randomly executed then executes "SHOW max_identifier_length". Hence
|
191
|
-
# the need to ignore certain predefined sqls that deal with system calls.
|
192
|
-
assert_no_queries(ignore_none: false) do
|
193
|
-
assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id)
|
194
|
-
end
|
195
|
-
end
|
196
|
-
|
197
|
-
def test_has_many_through_has_one_through_with_has_many_source_reflection_preload_via_joins
|
198
|
-
assert_includes_and_joins_equal(
|
199
|
-
Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'),
|
200
|
-
[members(:groucho), members(:some_other_guy)], :organization_member_details_2
|
201
|
-
)
|
202
|
-
|
203
|
-
members = Member.joins(:organization_member_details_2).
|
204
|
-
where('member_details.id' => 9)
|
205
|
-
assert members.empty?
|
206
|
-
end
|
207
|
-
|
208
|
-
# has_many through
|
209
|
-
# Source: has_and_belongs_to_many
|
210
|
-
# Through: has_many
|
211
|
-
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection
|
212
|
-
general, cooking = categories(:general), categories(:cooking)
|
213
|
-
|
214
|
-
assert_equal [general, cooking], authors(:bob).post_categories.order('categories.id')
|
215
|
-
end
|
216
|
-
|
217
|
-
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection_preload
|
218
|
-
authors = assert_queries(4) { Author.includes(:post_categories).to_a.sort_by(&:id) }
|
219
|
-
general, cooking = categories(:general), categories(:cooking)
|
220
|
-
|
221
|
-
assert_no_queries do
|
222
|
-
assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection_preload_via_joins
|
227
|
-
# preload table schemas
|
228
|
-
Author.joins(:post_categories).first
|
229
|
-
|
230
|
-
assert_includes_and_joins_equal(
|
231
|
-
Author.where('categories.id' => categories(:cooking).id),
|
232
|
-
[authors(:bob)], :post_categories
|
233
|
-
)
|
234
|
-
end
|
235
|
-
|
236
|
-
# has_many through
|
237
|
-
# Source: has_many
|
238
|
-
# Through: has_and_belongs_to_many
|
239
|
-
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection
|
240
|
-
greetings, more = comments(:greetings), comments(:more_greetings)
|
241
|
-
|
242
|
-
assert_equal [greetings, more], categories(:technology).post_comments.order('comments.id')
|
243
|
-
end
|
244
|
-
|
245
|
-
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload
|
246
|
-
Category.includes(:post_comments).to_a # preheat cache
|
247
|
-
categories = assert_queries(4) { Category.includes(:post_comments).to_a.sort_by(&:id) }
|
248
|
-
greetings, more = comments(:greetings), comments(:more_greetings)
|
249
|
-
|
250
|
-
assert_no_queries do
|
251
|
-
assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id)
|
252
|
-
end
|
253
|
-
end
|
254
|
-
|
255
|
-
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload_via_joins
|
256
|
-
# preload table schemas
|
257
|
-
Category.joins(:post_comments).first
|
258
|
-
|
259
|
-
assert_includes_and_joins_equal(
|
260
|
-
Category.where('comments.id' => comments(:more_greetings).id).order('categories.id'),
|
261
|
-
[categories(:general), categories(:technology)], :post_comments
|
262
|
-
)
|
263
|
-
end
|
264
|
-
|
265
|
-
# has_many through
|
266
|
-
# Source: has_many through a habtm
|
267
|
-
# Through: has_many through
|
268
|
-
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection
|
269
|
-
greetings, more = comments(:greetings), comments(:more_greetings)
|
270
|
-
|
271
|
-
assert_equal [greetings, more], authors(:bob).category_post_comments.order('comments.id')
|
272
|
-
end
|
273
|
-
|
274
|
-
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload
|
275
|
-
authors = assert_queries(6) { Author.includes(:category_post_comments).to_a.sort_by(&:id) }
|
276
|
-
greetings, more = comments(:greetings), comments(:more_greetings)
|
277
|
-
|
278
|
-
assert_no_queries do
|
279
|
-
assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id)
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload_via_joins
|
284
|
-
# preload table schemas
|
285
|
-
Author.joins(:category_post_comments).first
|
286
|
-
|
287
|
-
assert_includes_and_joins_equal(
|
288
|
-
Author.where('comments.id' => comments(:does_it_hurt).id).order('authors.id'),
|
289
|
-
[authors(:david), authors(:mary)], :category_post_comments
|
290
|
-
)
|
291
|
-
end
|
292
|
-
|
293
|
-
# has_many through
|
294
|
-
# Source: belongs_to
|
295
|
-
# Through: has_many through
|
296
|
-
def test_has_many_through_has_many_through_with_belongs_to_source_reflection
|
297
|
-
assert_equal [tags(:general), tags(:general)], authors(:david).tagging_tags
|
298
|
-
end
|
299
|
-
|
300
|
-
def test_has_many_through_has_many_through_with_belongs_to_source_reflection_preload
|
301
|
-
authors = assert_queries(5) { Author.includes(:tagging_tags).to_a }
|
302
|
-
general = tags(:general)
|
303
|
-
|
304
|
-
assert_no_queries do
|
305
|
-
assert_equal [general, general], authors.first.tagging_tags
|
306
|
-
end
|
307
|
-
end
|
308
|
-
|
309
|
-
def test_has_many_through_has_many_through_with_belongs_to_source_reflection_preload_via_joins
|
310
|
-
assert_includes_and_joins_equal(
|
311
|
-
Author.where('tags.id' => tags(:general).id),
|
312
|
-
[authors(:david)], :tagging_tags
|
313
|
-
)
|
314
|
-
end
|
315
|
-
|
316
|
-
# has_many through
|
317
|
-
# Source: has_many through
|
318
|
-
# Through: belongs_to
|
319
|
-
def test_has_many_through_belongs_to_with_has_many_through_source_reflection
|
320
|
-
welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general)
|
321
|
-
|
322
|
-
assert_equal [welcome_general, thinking_general],
|
323
|
-
categorizations(:david_welcome_general).post_taggings.order('taggings.id')
|
324
|
-
end
|
325
|
-
|
326
|
-
def test_has_many_through_belongs_to_with_has_many_through_source_reflection_preload
|
327
|
-
categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) }
|
328
|
-
welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general)
|
329
|
-
|
330
|
-
assert_no_queries do
|
331
|
-
assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id)
|
332
|
-
end
|
333
|
-
end
|
334
|
-
|
335
|
-
def test_has_many_through_belongs_to_with_has_many_through_source_reflection_preload_via_joins
|
336
|
-
assert_includes_and_joins_equal(
|
337
|
-
Categorization.where('taggings.id' => taggings(:welcome_general).id).order('taggings.id'),
|
338
|
-
[categorizations(:david_welcome_general)], :post_taggings
|
339
|
-
)
|
340
|
-
end
|
341
|
-
|
342
|
-
# has_one through
|
343
|
-
# Source: has_one through
|
344
|
-
# Through: has_one
|
345
|
-
def test_has_one_through_has_one_with_has_one_through_source_reflection
|
346
|
-
assert_equal member_types(:founding), members(:groucho).nested_member_type
|
347
|
-
end
|
348
|
-
|
349
|
-
def test_has_one_through_has_one_with_has_one_through_source_reflection_preload
|
350
|
-
members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) }
|
351
|
-
founding = member_types(:founding)
|
352
|
-
|
353
|
-
assert_no_queries do
|
354
|
-
assert_equal founding, members.first.nested_member_type
|
355
|
-
end
|
356
|
-
end
|
357
|
-
|
358
|
-
def test_has_one_through_has_one_with_has_one_through_source_reflection_preload_via_joins
|
359
|
-
assert_includes_and_joins_equal(
|
360
|
-
Member.where('member_types.id' => member_types(:founding).id),
|
361
|
-
[members(:groucho)], :nested_member_type
|
362
|
-
)
|
363
|
-
end
|
364
|
-
|
365
|
-
# has_one through
|
366
|
-
# Source: belongs_to
|
367
|
-
# Through: has_one through
|
368
|
-
def test_has_one_through_has_one_through_with_belongs_to_source_reflection
|
369
|
-
assert_equal categories(:general), members(:groucho).club_category
|
370
|
-
end
|
371
|
-
|
372
|
-
def test_joins_and_includes_from_through_models_not_included_in_association
|
373
|
-
prev_default_scope = Club.default_scopes
|
374
|
-
|
375
|
-
[:includes, :preload, :joins, :eager_load].each do |q|
|
376
|
-
Club.default_scopes = [proc { Club.send(q, :category) }]
|
377
|
-
assert_equal categories(:general), members(:groucho).reload.club_category
|
378
|
-
end
|
379
|
-
ensure
|
380
|
-
Club.default_scopes = prev_default_scope
|
381
|
-
end
|
382
|
-
|
383
|
-
def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload
|
384
|
-
members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) }
|
385
|
-
general = categories(:general)
|
386
|
-
|
387
|
-
assert_no_queries do
|
388
|
-
assert_equal general, members.first.club_category
|
389
|
-
end
|
390
|
-
end
|
391
|
-
|
392
|
-
def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload_via_joins
|
393
|
-
assert_includes_and_joins_equal(
|
394
|
-
Member.where('categories.id' => categories(:technology).id),
|
395
|
-
[members(:blarpy_winkup)], :club_category
|
396
|
-
)
|
397
|
-
end
|
398
|
-
|
399
|
-
def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection
|
400
|
-
author = authors(:david)
|
401
|
-
assert_equal [tags(:general)], author.distinct_tags
|
402
|
-
end
|
403
|
-
|
404
|
-
def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection
|
405
|
-
author = authors(:david)
|
406
|
-
assert_equal [subscribers(:first), subscribers(:second)],
|
407
|
-
author.distinct_subscribers.order('subscribers.nick')
|
408
|
-
end
|
409
|
-
|
410
|
-
def test_nested_has_many_through_with_a_table_referenced_multiple_times
|
411
|
-
author = authors(:bob)
|
412
|
-
assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)],
|
413
|
-
author.similar_posts.sort_by(&:id)
|
414
|
-
|
415
|
-
# Mary and Bob both have posts in misc, but they are the only ones.
|
416
|
-
authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id)
|
417
|
-
assert_equal [authors(:mary), authors(:bob)], authors.distinct.sort_by(&:id)
|
418
|
-
|
419
|
-
# Check the polymorphism of taggings is being observed correctly (in both joins)
|
420
|
-
authors = Author.joins(:similar_posts).where('taggings.taggable_type' => 'FakeModel')
|
421
|
-
assert authors.empty?
|
422
|
-
authors = Author.joins(:similar_posts).where('taggings_authors_join.taggable_type' => 'FakeModel')
|
423
|
-
assert authors.empty?
|
424
|
-
end
|
425
|
-
|
426
|
-
def test_has_many_through_with_foreign_key_option_on_through_reflection
|
427
|
-
assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts.order('posts.id')
|
428
|
-
assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors
|
429
|
-
|
430
|
-
references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id)
|
431
|
-
assert_equal [references(:david_unicyclist)], references
|
432
|
-
end
|
433
|
-
|
434
|
-
def test_has_many_through_with_foreign_key_option_on_source_reflection
|
435
|
-
assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents.order('people.id')
|
436
|
-
|
437
|
-
jobs = Job.joins(:agents)
|
438
|
-
assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs
|
439
|
-
end
|
440
|
-
|
441
|
-
def test_has_many_through_with_sti_on_through_reflection
|
442
|
-
ratings = posts(:sti_comments).special_comments_ratings.sort_by(&:id)
|
443
|
-
assert_equal [ratings(:special_comment_rating), ratings(:sub_special_comment_rating)], ratings
|
444
|
-
|
445
|
-
# Ensure STI is respected in the join
|
446
|
-
scope = Post.joins(:special_comments_ratings).where(:id => posts(:sti_comments).id)
|
447
|
-
assert scope.where("comments.type" => "Comment").empty?
|
448
|
-
assert !scope.where("comments.type" => "SpecialComment").empty?
|
449
|
-
assert !scope.where("comments.type" => "SubSpecialComment").empty?
|
450
|
-
end
|
451
|
-
|
452
|
-
def test_has_many_through_with_sti_on_nested_through_reflection
|
453
|
-
taggings = posts(:sti_comments).special_comments_ratings_taggings
|
454
|
-
assert_equal [taggings(:special_comment_rating)], taggings
|
455
|
-
|
456
|
-
scope = Post.joins(:special_comments_ratings_taggings).where(:id => posts(:sti_comments).id)
|
457
|
-
assert scope.where("comments.type" => "Comment").empty?
|
458
|
-
assert !scope.where("comments.type" => "SpecialComment").empty?
|
459
|
-
end
|
460
|
-
|
461
|
-
def test_nested_has_many_through_writers_should_raise_error
|
462
|
-
david = authors(:david)
|
463
|
-
subscriber = subscribers(:first)
|
464
|
-
|
465
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
466
|
-
david.subscribers = [subscriber]
|
467
|
-
end
|
468
|
-
|
469
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
470
|
-
david.subscriber_ids = [subscriber.id]
|
471
|
-
end
|
472
|
-
|
473
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
474
|
-
david.subscribers << subscriber
|
475
|
-
end
|
476
|
-
|
477
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
478
|
-
david.subscribers.delete(subscriber)
|
479
|
-
end
|
480
|
-
|
481
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
482
|
-
david.subscribers.clear
|
483
|
-
end
|
484
|
-
|
485
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
486
|
-
david.subscribers.build
|
487
|
-
end
|
488
|
-
|
489
|
-
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
490
|
-
david.subscribers.create
|
491
|
-
end
|
492
|
-
end
|
493
|
-
|
494
|
-
def test_nested_has_one_through_writers_should_raise_error
|
495
|
-
groucho = members(:groucho)
|
496
|
-
founding = member_types(:founding)
|
497
|
-
|
498
|
-
assert_raises(ActiveRecord::
|
499
|
-
groucho.nested_member_type = founding
|
500
|
-
end
|
501
|
-
end
|
502
|
-
|
503
|
-
def test_nested_has_many_through_with_conditions_on_through_associations
|
504
|
-
assert_equal [tags(:blue)], authors(:bob).misc_post_first_blue_tags
|
505
|
-
end
|
506
|
-
|
507
|
-
def test_nested_has_many_through_with_conditions_on_through_associations_preload
|
508
|
-
assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty?
|
509
|
-
|
510
|
-
authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) }
|
511
|
-
blue = tags(:blue)
|
512
|
-
|
513
|
-
assert_no_queries do
|
514
|
-
assert_equal [blue], authors[2].misc_post_first_blue_tags
|
515
|
-
end
|
516
|
-
end
|
517
|
-
|
518
|
-
def test_nested_has_many_through_with_conditions_on_through_associations_preload_via_joins
|
519
|
-
# Pointless condition to force single-query loading
|
520
|
-
assert_includes_and_joins_equal(
|
521
|
-
Author.where('tags.id = tags.id').references(:tags),
|
522
|
-
[authors(:bob)], :misc_post_first_blue_tags
|
523
|
-
)
|
524
|
-
end
|
525
|
-
|
526
|
-
def test_nested_has_many_through_with_conditions_on_source_associations
|
527
|
-
assert_equal [tags(:blue)], authors(:bob).misc_post_first_blue_tags_2
|
528
|
-
end
|
529
|
-
|
530
|
-
def test_nested_has_many_through_with_conditions_on_source_associations_preload
|
531
|
-
authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) }
|
532
|
-
blue = tags(:blue)
|
533
|
-
|
534
|
-
assert_no_queries do
|
535
|
-
assert_equal [blue], authors[2].misc_post_first_blue_tags_2
|
536
|
-
end
|
537
|
-
end
|
538
|
-
|
539
|
-
def test_nested_has_many_through_with_conditions_on_source_associations_preload_via_joins
|
540
|
-
# Pointless condition to force single-query loading
|
541
|
-
assert_includes_and_joins_equal(
|
542
|
-
Author.where('tags.id = tags.id').references(:tags),
|
543
|
-
[authors(:bob)], :misc_post_first_blue_tags_2
|
544
|
-
)
|
545
|
-
end
|
546
|
-
|
547
|
-
def test_nested_has_many_through_with_foreign_key_option_on_the_source_reflection_through_reflection
|
548
|
-
assert_equal [categories(:general)], organizations(:nsa).author_essay_categories
|
549
|
-
|
550
|
-
organizations = Organization.joins(:author_essay_categories).
|
551
|
-
where('categories.id' => categories(:general).id)
|
552
|
-
assert_equal [organizations(:nsa)], organizations
|
553
|
-
|
554
|
-
assert_equal categories(:general), organizations(:nsa).author_owned_essay_category
|
555
|
-
|
556
|
-
organizations = Organization.joins(:author_owned_essay_category).
|
557
|
-
where('categories.id' => categories(:general).id)
|
558
|
-
assert_equal [organizations(:nsa)], organizations
|
559
|
-
end
|
560
|
-
|
561
|
-
def test_nested_has_many_through_should_not_be_autosaved
|
562
|
-
c = Categorization.new
|
563
|
-
c.author = authors(:david)
|
564
|
-
c.post_taggings.to_a
|
565
|
-
assert !c.post_taggings.empty?
|
566
|
-
c.save
|
567
|
-
assert !c.post_taggings.empty?
|
568
|
-
end
|
569
|
-
|
570
|
-
private
|
571
|
-
|
572
|
-
def assert_includes_and_joins_equal(query, expected, association)
|
573
|
-
actual = assert_queries(1) { query.joins(association).to_a.uniq }
|
574
|
-
assert_equal expected, actual
|
575
|
-
|
576
|
-
actual = assert_queries(1) { query.includes(association).to_a.uniq }
|
577
|
-
assert_equal expected, actual
|
578
|
-
end
|
579
|
-
end
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/author'
|
3
|
+
require 'models/post'
|
4
|
+
require 'models/person'
|
5
|
+
require 'models/reference'
|
6
|
+
require 'models/job'
|
7
|
+
require 'models/reader'
|
8
|
+
require 'models/comment'
|
9
|
+
require 'models/tag'
|
10
|
+
require 'models/tagging'
|
11
|
+
require 'models/subscriber'
|
12
|
+
require 'models/book'
|
13
|
+
require 'models/subscription'
|
14
|
+
require 'models/rating'
|
15
|
+
require 'models/member'
|
16
|
+
require 'models/member_detail'
|
17
|
+
require 'models/member_type'
|
18
|
+
require 'models/sponsor'
|
19
|
+
require 'models/club'
|
20
|
+
require 'models/organization'
|
21
|
+
require 'models/category'
|
22
|
+
require 'models/categorization'
|
23
|
+
require 'models/membership'
|
24
|
+
require 'models/essay'
|
25
|
+
|
26
|
+
class NestedThroughAssociationsTest < ActiveRecord::TestCase
|
27
|
+
fixtures :authors, :books, :posts, :subscriptions, :subscribers, :tags, :taggings,
|
28
|
+
:people, :readers, :references, :jobs, :ratings, :comments, :members, :member_details,
|
29
|
+
:member_types, :sponsors, :clubs, :organizations, :categories, :categories_posts,
|
30
|
+
:categorizations, :memberships, :essays
|
31
|
+
|
32
|
+
# Through associations can either use the has_many or has_one macros.
|
33
|
+
#
|
34
|
+
# has_many
|
35
|
+
# - Source reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many
|
36
|
+
# - Through reflection can be has_many, has_one, belongs_to or has_and_belongs_to_many
|
37
|
+
#
|
38
|
+
# has_one
|
39
|
+
# - Source reflection can be has_one or belongs_to
|
40
|
+
# - Through reflection can be has_one or belongs_to
|
41
|
+
#
|
42
|
+
# Additionally, the source reflection and/or through reflection may be subject to
|
43
|
+
# polymorphism and/or STI.
|
44
|
+
#
|
45
|
+
# When testing these, we need to make sure it works via loading the association directly, or
|
46
|
+
# joining the association, or including the association. We also need to ensure that associations
|
47
|
+
# are readonly where relevant.
|
48
|
+
|
49
|
+
# has_many through
|
50
|
+
# Source: has_many through
|
51
|
+
# Through: has_many
|
52
|
+
def test_has_many_through_has_many_with_has_many_through_source_reflection
|
53
|
+
general = tags(:general)
|
54
|
+
assert_equal [general, general], authors(:david).tags
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_has_many_through_has_many_with_has_many_through_source_reflection_preload
|
58
|
+
authors = assert_queries(5) { Author.includes(:tags).to_a }
|
59
|
+
general = tags(:general)
|
60
|
+
|
61
|
+
assert_no_queries do
|
62
|
+
assert_equal [general, general], authors.first.tags
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_has_many_through_has_many_with_has_many_through_source_reflection_preload_via_joins
|
67
|
+
assert_includes_and_joins_equal(
|
68
|
+
Author.where('tags.id' => tags(:general).id),
|
69
|
+
[authors(:david)], :tags
|
70
|
+
)
|
71
|
+
|
72
|
+
# This ensures that the polymorphism of taggings is being observed correctly
|
73
|
+
authors = Author.joins(:tags).where('taggings.taggable_type' => 'FakeModel')
|
74
|
+
assert authors.empty?
|
75
|
+
end
|
76
|
+
|
77
|
+
# has_many through
|
78
|
+
# Source: has_many
|
79
|
+
# Through: has_many through
|
80
|
+
def test_has_many_through_has_many_through_with_has_many_source_reflection
|
81
|
+
luke, david = subscribers(:first), subscribers(:second)
|
82
|
+
assert_equal [luke, david, david], authors(:david).subscribers.order('subscribers.nick')
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_has_many_through_has_many_through_with_has_many_source_reflection_preload
|
86
|
+
luke, david = subscribers(:first), subscribers(:second)
|
87
|
+
authors = assert_queries(4) { Author.includes(:subscribers).to_a }
|
88
|
+
assert_no_queries do
|
89
|
+
assert_equal [luke, david, david], authors.first.subscribers.sort_by(&:nick)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_has_many_through_has_many_through_with_has_many_source_reflection_preload_via_joins
|
94
|
+
# All authors with subscribers where one of the subscribers' nick is 'alterself'
|
95
|
+
assert_includes_and_joins_equal(
|
96
|
+
Author.where('subscribers.nick' => 'alterself'),
|
97
|
+
[authors(:david)], :subscribers
|
98
|
+
)
|
99
|
+
end
|
100
|
+
|
101
|
+
# has_many through
|
102
|
+
# Source: has_one through
|
103
|
+
# Through: has_one
|
104
|
+
def test_has_many_through_has_one_with_has_one_through_source_reflection
|
105
|
+
assert_equal [member_types(:founding)], members(:groucho).nested_member_types
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_has_many_through_has_one_with_has_one_through_source_reflection_preload
|
109
|
+
members = assert_queries(4) { Member.includes(:nested_member_types).to_a }
|
110
|
+
founding = member_types(:founding)
|
111
|
+
assert_no_queries do
|
112
|
+
assert_equal [founding], members.first.nested_member_types
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_has_many_through_has_one_with_has_one_through_source_reflection_preload_via_joins
|
117
|
+
assert_includes_and_joins_equal(
|
118
|
+
Member.where('member_types.id' => member_types(:founding).id),
|
119
|
+
[members(:groucho)], :nested_member_types
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
# has_many through
|
124
|
+
# Source: has_one
|
125
|
+
# Through: has_one through
|
126
|
+
def test_has_many_through_has_one_through_with_has_one_source_reflection
|
127
|
+
assert_equal [sponsors(:moustache_club_sponsor_for_groucho)], members(:groucho).nested_sponsors
|
128
|
+
end
|
129
|
+
|
130
|
+
def test_has_many_through_has_one_through_with_has_one_source_reflection_preload
|
131
|
+
members = assert_queries(4) { Member.includes(:nested_sponsors).to_a }
|
132
|
+
mustache = sponsors(:moustache_club_sponsor_for_groucho)
|
133
|
+
assert_no_queries(ignore_none: false) do
|
134
|
+
assert_equal [mustache], members.first.nested_sponsors
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def test_has_many_through_has_one_through_with_has_one_source_reflection_preload_via_joins
|
139
|
+
assert_includes_and_joins_equal(
|
140
|
+
Member.where('sponsors.id' => sponsors(:moustache_club_sponsor_for_groucho).id),
|
141
|
+
[members(:groucho)], :nested_sponsors
|
142
|
+
)
|
143
|
+
end
|
144
|
+
|
145
|
+
# has_many through
|
146
|
+
# Source: has_many through
|
147
|
+
# Through: has_one
|
148
|
+
def test_has_many_through_has_one_with_has_many_through_source_reflection
|
149
|
+
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
150
|
+
|
151
|
+
assert_equal [groucho_details, other_details],
|
152
|
+
members(:groucho).organization_member_details.order('member_details.id')
|
153
|
+
end
|
154
|
+
|
155
|
+
def test_has_many_through_has_one_with_has_many_through_source_reflection_preload
|
156
|
+
ActiveRecord::Base.connection.table_alias_length # preheat cache
|
157
|
+
members = assert_queries(4) { Member.includes(:organization_member_details).to_a.sort_by(&:id) }
|
158
|
+
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
159
|
+
|
160
|
+
assert_no_queries do
|
161
|
+
assert_equal [groucho_details, other_details], members.first.organization_member_details.sort_by(&:id)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def test_has_many_through_has_one_with_has_many_through_source_reflection_preload_via_joins
|
166
|
+
assert_includes_and_joins_equal(
|
167
|
+
Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'),
|
168
|
+
[members(:groucho), members(:some_other_guy)], :organization_member_details
|
169
|
+
)
|
170
|
+
|
171
|
+
members = Member.joins(:organization_member_details).
|
172
|
+
where('member_details.id' => 9)
|
173
|
+
assert members.empty?
|
174
|
+
end
|
175
|
+
|
176
|
+
# has_many through
|
177
|
+
# Source: has_many
|
178
|
+
# Through: has_one through
|
179
|
+
def test_has_many_through_has_one_through_with_has_many_source_reflection
|
180
|
+
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
181
|
+
|
182
|
+
assert_equal [groucho_details, other_details],
|
183
|
+
members(:groucho).organization_member_details_2.order('member_details.id')
|
184
|
+
end
|
185
|
+
|
186
|
+
def test_has_many_through_has_one_through_with_has_many_source_reflection_preload
|
187
|
+
members = assert_queries(4) { Member.includes(:organization_member_details_2).to_a.sort_by(&:id) }
|
188
|
+
groucho_details, other_details = member_details(:groucho), member_details(:some_other_guy)
|
189
|
+
|
190
|
+
# postgresql test if randomly executed then executes "SHOW max_identifier_length". Hence
|
191
|
+
# the need to ignore certain predefined sqls that deal with system calls.
|
192
|
+
assert_no_queries(ignore_none: false) do
|
193
|
+
assert_equal [groucho_details, other_details], members.first.organization_member_details_2.sort_by(&:id)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def test_has_many_through_has_one_through_with_has_many_source_reflection_preload_via_joins
|
198
|
+
assert_includes_and_joins_equal(
|
199
|
+
Member.where('member_details.id' => member_details(:groucho).id).order('member_details.id'),
|
200
|
+
[members(:groucho), members(:some_other_guy)], :organization_member_details_2
|
201
|
+
)
|
202
|
+
|
203
|
+
members = Member.joins(:organization_member_details_2).
|
204
|
+
where('member_details.id' => 9)
|
205
|
+
assert members.empty?
|
206
|
+
end
|
207
|
+
|
208
|
+
# has_many through
|
209
|
+
# Source: has_and_belongs_to_many
|
210
|
+
# Through: has_many
|
211
|
+
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection
|
212
|
+
general, cooking = categories(:general), categories(:cooking)
|
213
|
+
|
214
|
+
assert_equal [general, cooking], authors(:bob).post_categories.order('categories.id')
|
215
|
+
end
|
216
|
+
|
217
|
+
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection_preload
|
218
|
+
authors = assert_queries(4) { Author.includes(:post_categories).to_a.sort_by(&:id) }
|
219
|
+
general, cooking = categories(:general), categories(:cooking)
|
220
|
+
|
221
|
+
assert_no_queries do
|
222
|
+
assert_equal [general, cooking], authors[2].post_categories.sort_by(&:id)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def test_has_many_through_has_many_with_has_and_belongs_to_many_source_reflection_preload_via_joins
|
227
|
+
# preload table schemas
|
228
|
+
Author.joins(:post_categories).first
|
229
|
+
|
230
|
+
assert_includes_and_joins_equal(
|
231
|
+
Author.where('categories.id' => categories(:cooking).id),
|
232
|
+
[authors(:bob)], :post_categories
|
233
|
+
)
|
234
|
+
end
|
235
|
+
|
236
|
+
# has_many through
|
237
|
+
# Source: has_many
|
238
|
+
# Through: has_and_belongs_to_many
|
239
|
+
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection
|
240
|
+
greetings, more = comments(:greetings), comments(:more_greetings)
|
241
|
+
|
242
|
+
assert_equal [greetings, more], categories(:technology).post_comments.order('comments.id')
|
243
|
+
end
|
244
|
+
|
245
|
+
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload
|
246
|
+
Category.includes(:post_comments).to_a # preheat cache
|
247
|
+
categories = assert_queries(4) { Category.includes(:post_comments).to_a.sort_by(&:id) }
|
248
|
+
greetings, more = comments(:greetings), comments(:more_greetings)
|
249
|
+
|
250
|
+
assert_no_queries do
|
251
|
+
assert_equal [greetings, more], categories[1].post_comments.sort_by(&:id)
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_has_many_through_has_and_belongs_to_many_with_has_many_source_reflection_preload_via_joins
|
256
|
+
# preload table schemas
|
257
|
+
Category.joins(:post_comments).first
|
258
|
+
|
259
|
+
assert_includes_and_joins_equal(
|
260
|
+
Category.where('comments.id' => comments(:more_greetings).id).order('categories.id'),
|
261
|
+
[categories(:general), categories(:technology)], :post_comments
|
262
|
+
)
|
263
|
+
end
|
264
|
+
|
265
|
+
# has_many through
|
266
|
+
# Source: has_many through a habtm
|
267
|
+
# Through: has_many through
|
268
|
+
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection
|
269
|
+
greetings, more = comments(:greetings), comments(:more_greetings)
|
270
|
+
|
271
|
+
assert_equal [greetings, more], authors(:bob).category_post_comments.order('comments.id')
|
272
|
+
end
|
273
|
+
|
274
|
+
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload
|
275
|
+
authors = assert_queries(6) { Author.includes(:category_post_comments).to_a.sort_by(&:id) }
|
276
|
+
greetings, more = comments(:greetings), comments(:more_greetings)
|
277
|
+
|
278
|
+
assert_no_queries do
|
279
|
+
assert_equal [greetings, more], authors[2].category_post_comments.sort_by(&:id)
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def test_has_many_through_has_many_with_has_many_through_habtm_source_reflection_preload_via_joins
|
284
|
+
# preload table schemas
|
285
|
+
Author.joins(:category_post_comments).first
|
286
|
+
|
287
|
+
assert_includes_and_joins_equal(
|
288
|
+
Author.where('comments.id' => comments(:does_it_hurt).id).order('authors.id'),
|
289
|
+
[authors(:david), authors(:mary)], :category_post_comments
|
290
|
+
)
|
291
|
+
end
|
292
|
+
|
293
|
+
# has_many through
|
294
|
+
# Source: belongs_to
|
295
|
+
# Through: has_many through
|
296
|
+
def test_has_many_through_has_many_through_with_belongs_to_source_reflection
|
297
|
+
assert_equal [tags(:general), tags(:general)], authors(:david).tagging_tags
|
298
|
+
end
|
299
|
+
|
300
|
+
def test_has_many_through_has_many_through_with_belongs_to_source_reflection_preload
|
301
|
+
authors = assert_queries(5) { Author.includes(:tagging_tags).to_a }
|
302
|
+
general = tags(:general)
|
303
|
+
|
304
|
+
assert_no_queries do
|
305
|
+
assert_equal [general, general], authors.first.tagging_tags
|
306
|
+
end
|
307
|
+
end
|
308
|
+
|
309
|
+
def test_has_many_through_has_many_through_with_belongs_to_source_reflection_preload_via_joins
|
310
|
+
assert_includes_and_joins_equal(
|
311
|
+
Author.where('tags.id' => tags(:general).id),
|
312
|
+
[authors(:david)], :tagging_tags
|
313
|
+
)
|
314
|
+
end
|
315
|
+
|
316
|
+
# has_many through
|
317
|
+
# Source: has_many through
|
318
|
+
# Through: belongs_to
|
319
|
+
def test_has_many_through_belongs_to_with_has_many_through_source_reflection
|
320
|
+
welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general)
|
321
|
+
|
322
|
+
assert_equal [welcome_general, thinking_general],
|
323
|
+
categorizations(:david_welcome_general).post_taggings.order('taggings.id')
|
324
|
+
end
|
325
|
+
|
326
|
+
def test_has_many_through_belongs_to_with_has_many_through_source_reflection_preload
|
327
|
+
categorizations = assert_queries(4) { Categorization.includes(:post_taggings).to_a.sort_by(&:id) }
|
328
|
+
welcome_general, thinking_general = taggings(:welcome_general), taggings(:thinking_general)
|
329
|
+
|
330
|
+
assert_no_queries do
|
331
|
+
assert_equal [welcome_general, thinking_general], categorizations.first.post_taggings.sort_by(&:id)
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_has_many_through_belongs_to_with_has_many_through_source_reflection_preload_via_joins
|
336
|
+
assert_includes_and_joins_equal(
|
337
|
+
Categorization.where('taggings.id' => taggings(:welcome_general).id).order('taggings.id'),
|
338
|
+
[categorizations(:david_welcome_general)], :post_taggings
|
339
|
+
)
|
340
|
+
end
|
341
|
+
|
342
|
+
# has_one through
|
343
|
+
# Source: has_one through
|
344
|
+
# Through: has_one
|
345
|
+
def test_has_one_through_has_one_with_has_one_through_source_reflection
|
346
|
+
assert_equal member_types(:founding), members(:groucho).nested_member_type
|
347
|
+
end
|
348
|
+
|
349
|
+
def test_has_one_through_has_one_with_has_one_through_source_reflection_preload
|
350
|
+
members = assert_queries(4) { Member.includes(:nested_member_type).to_a.sort_by(&:id) }
|
351
|
+
founding = member_types(:founding)
|
352
|
+
|
353
|
+
assert_no_queries do
|
354
|
+
assert_equal founding, members.first.nested_member_type
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_has_one_through_has_one_with_has_one_through_source_reflection_preload_via_joins
|
359
|
+
assert_includes_and_joins_equal(
|
360
|
+
Member.where('member_types.id' => member_types(:founding).id),
|
361
|
+
[members(:groucho)], :nested_member_type
|
362
|
+
)
|
363
|
+
end
|
364
|
+
|
365
|
+
# has_one through
|
366
|
+
# Source: belongs_to
|
367
|
+
# Through: has_one through
|
368
|
+
def test_has_one_through_has_one_through_with_belongs_to_source_reflection
|
369
|
+
assert_equal categories(:general), members(:groucho).club_category
|
370
|
+
end
|
371
|
+
|
372
|
+
def test_joins_and_includes_from_through_models_not_included_in_association
|
373
|
+
prev_default_scope = Club.default_scopes
|
374
|
+
|
375
|
+
[:includes, :preload, :joins, :eager_load].each do |q|
|
376
|
+
Club.default_scopes = [proc { Club.send(q, :category) }]
|
377
|
+
assert_equal categories(:general), members(:groucho).reload.club_category
|
378
|
+
end
|
379
|
+
ensure
|
380
|
+
Club.default_scopes = prev_default_scope
|
381
|
+
end
|
382
|
+
|
383
|
+
def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload
|
384
|
+
members = assert_queries(4) { Member.includes(:club_category).to_a.sort_by(&:id) }
|
385
|
+
general = categories(:general)
|
386
|
+
|
387
|
+
assert_no_queries do
|
388
|
+
assert_equal general, members.first.club_category
|
389
|
+
end
|
390
|
+
end
|
391
|
+
|
392
|
+
def test_has_one_through_has_one_through_with_belongs_to_source_reflection_preload_via_joins
|
393
|
+
assert_includes_and_joins_equal(
|
394
|
+
Member.where('categories.id' => categories(:technology).id),
|
395
|
+
[members(:blarpy_winkup)], :club_category
|
396
|
+
)
|
397
|
+
end
|
398
|
+
|
399
|
+
def test_distinct_has_many_through_a_has_many_through_association_on_source_reflection
|
400
|
+
author = authors(:david)
|
401
|
+
assert_equal [tags(:general)], author.distinct_tags
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_distinct_has_many_through_a_has_many_through_association_on_through_reflection
|
405
|
+
author = authors(:david)
|
406
|
+
assert_equal [subscribers(:first), subscribers(:second)],
|
407
|
+
author.distinct_subscribers.order('subscribers.nick')
|
408
|
+
end
|
409
|
+
|
410
|
+
def test_nested_has_many_through_with_a_table_referenced_multiple_times
|
411
|
+
author = authors(:bob)
|
412
|
+
assert_equal [posts(:misc_by_bob), posts(:misc_by_mary), posts(:other_by_bob), posts(:other_by_mary)],
|
413
|
+
author.similar_posts.sort_by(&:id)
|
414
|
+
|
415
|
+
# Mary and Bob both have posts in misc, but they are the only ones.
|
416
|
+
authors = Author.joins(:similar_posts).where('posts.id' => posts(:misc_by_bob).id)
|
417
|
+
assert_equal [authors(:mary), authors(:bob)], authors.distinct.sort_by(&:id)
|
418
|
+
|
419
|
+
# Check the polymorphism of taggings is being observed correctly (in both joins)
|
420
|
+
authors = Author.joins(:similar_posts).where('taggings.taggable_type' => 'FakeModel')
|
421
|
+
assert authors.empty?
|
422
|
+
authors = Author.joins(:similar_posts).where('taggings_authors_join.taggable_type' => 'FakeModel')
|
423
|
+
assert authors.empty?
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_has_many_through_with_foreign_key_option_on_through_reflection
|
427
|
+
assert_equal [posts(:welcome), posts(:authorless)], people(:david).agents_posts.order('posts.id')
|
428
|
+
assert_equal [authors(:david)], references(:david_unicyclist).agents_posts_authors
|
429
|
+
|
430
|
+
references = Reference.joins(:agents_posts_authors).where('authors.id' => authors(:david).id)
|
431
|
+
assert_equal [references(:david_unicyclist)], references
|
432
|
+
end
|
433
|
+
|
434
|
+
def test_has_many_through_with_foreign_key_option_on_source_reflection
|
435
|
+
assert_equal [people(:michael), people(:susan)], jobs(:unicyclist).agents.order('people.id')
|
436
|
+
|
437
|
+
jobs = Job.joins(:agents)
|
438
|
+
assert_equal [jobs(:unicyclist), jobs(:unicyclist)], jobs
|
439
|
+
end
|
440
|
+
|
441
|
+
def test_has_many_through_with_sti_on_through_reflection
|
442
|
+
ratings = posts(:sti_comments).special_comments_ratings.sort_by(&:id)
|
443
|
+
assert_equal [ratings(:special_comment_rating), ratings(:sub_special_comment_rating)], ratings
|
444
|
+
|
445
|
+
# Ensure STI is respected in the join
|
446
|
+
scope = Post.joins(:special_comments_ratings).where(:id => posts(:sti_comments).id)
|
447
|
+
assert scope.where("comments.type" => "Comment").empty?
|
448
|
+
assert !scope.where("comments.type" => "SpecialComment").empty?
|
449
|
+
assert !scope.where("comments.type" => "SubSpecialComment").empty?
|
450
|
+
end
|
451
|
+
|
452
|
+
def test_has_many_through_with_sti_on_nested_through_reflection
|
453
|
+
taggings = posts(:sti_comments).special_comments_ratings_taggings
|
454
|
+
assert_equal [taggings(:special_comment_rating)], taggings
|
455
|
+
|
456
|
+
scope = Post.joins(:special_comments_ratings_taggings).where(:id => posts(:sti_comments).id)
|
457
|
+
assert scope.where("comments.type" => "Comment").empty?
|
458
|
+
assert !scope.where("comments.type" => "SpecialComment").empty?
|
459
|
+
end
|
460
|
+
|
461
|
+
def test_nested_has_many_through_writers_should_raise_error
|
462
|
+
david = authors(:david)
|
463
|
+
subscriber = subscribers(:first)
|
464
|
+
|
465
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
466
|
+
david.subscribers = [subscriber]
|
467
|
+
end
|
468
|
+
|
469
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
470
|
+
david.subscriber_ids = [subscriber.id]
|
471
|
+
end
|
472
|
+
|
473
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
474
|
+
david.subscribers << subscriber
|
475
|
+
end
|
476
|
+
|
477
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
478
|
+
david.subscribers.delete(subscriber)
|
479
|
+
end
|
480
|
+
|
481
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
482
|
+
david.subscribers.clear
|
483
|
+
end
|
484
|
+
|
485
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
486
|
+
david.subscribers.build
|
487
|
+
end
|
488
|
+
|
489
|
+
assert_raises(ActiveRecord::HasManyThroughNestedAssociationsAreReadonly) do
|
490
|
+
david.subscribers.create
|
491
|
+
end
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_nested_has_one_through_writers_should_raise_error
|
495
|
+
groucho = members(:groucho)
|
496
|
+
founding = member_types(:founding)
|
497
|
+
|
498
|
+
assert_raises(ActiveRecord::HasOneThroughNestedAssociationsAreReadonly) do
|
499
|
+
groucho.nested_member_type = founding
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
def test_nested_has_many_through_with_conditions_on_through_associations
|
504
|
+
assert_equal [tags(:blue)], authors(:bob).misc_post_first_blue_tags
|
505
|
+
end
|
506
|
+
|
507
|
+
def test_nested_has_many_through_with_conditions_on_through_associations_preload
|
508
|
+
assert Author.where('tags.id' => 100).joins(:misc_post_first_blue_tags).empty?
|
509
|
+
|
510
|
+
authors = assert_queries(3) { Author.includes(:misc_post_first_blue_tags).to_a.sort_by(&:id) }
|
511
|
+
blue = tags(:blue)
|
512
|
+
|
513
|
+
assert_no_queries do
|
514
|
+
assert_equal [blue], authors[2].misc_post_first_blue_tags
|
515
|
+
end
|
516
|
+
end
|
517
|
+
|
518
|
+
def test_nested_has_many_through_with_conditions_on_through_associations_preload_via_joins
|
519
|
+
# Pointless condition to force single-query loading
|
520
|
+
assert_includes_and_joins_equal(
|
521
|
+
Author.where('tags.id = tags.id').references(:tags),
|
522
|
+
[authors(:bob)], :misc_post_first_blue_tags
|
523
|
+
)
|
524
|
+
end
|
525
|
+
|
526
|
+
def test_nested_has_many_through_with_conditions_on_source_associations
|
527
|
+
assert_equal [tags(:blue)], authors(:bob).misc_post_first_blue_tags_2
|
528
|
+
end
|
529
|
+
|
530
|
+
def test_nested_has_many_through_with_conditions_on_source_associations_preload
|
531
|
+
authors = assert_queries(4) { Author.includes(:misc_post_first_blue_tags_2).to_a.sort_by(&:id) }
|
532
|
+
blue = tags(:blue)
|
533
|
+
|
534
|
+
assert_no_queries do
|
535
|
+
assert_equal [blue], authors[2].misc_post_first_blue_tags_2
|
536
|
+
end
|
537
|
+
end
|
538
|
+
|
539
|
+
def test_nested_has_many_through_with_conditions_on_source_associations_preload_via_joins
|
540
|
+
# Pointless condition to force single-query loading
|
541
|
+
assert_includes_and_joins_equal(
|
542
|
+
Author.where('tags.id = tags.id').references(:tags),
|
543
|
+
[authors(:bob)], :misc_post_first_blue_tags_2
|
544
|
+
)
|
545
|
+
end
|
546
|
+
|
547
|
+
def test_nested_has_many_through_with_foreign_key_option_on_the_source_reflection_through_reflection
|
548
|
+
assert_equal [categories(:general)], organizations(:nsa).author_essay_categories
|
549
|
+
|
550
|
+
organizations = Organization.joins(:author_essay_categories).
|
551
|
+
where('categories.id' => categories(:general).id)
|
552
|
+
assert_equal [organizations(:nsa)], organizations
|
553
|
+
|
554
|
+
assert_equal categories(:general), organizations(:nsa).author_owned_essay_category
|
555
|
+
|
556
|
+
organizations = Organization.joins(:author_owned_essay_category).
|
557
|
+
where('categories.id' => categories(:general).id)
|
558
|
+
assert_equal [organizations(:nsa)], organizations
|
559
|
+
end
|
560
|
+
|
561
|
+
def test_nested_has_many_through_should_not_be_autosaved
|
562
|
+
c = Categorization.new
|
563
|
+
c.author = authors(:david)
|
564
|
+
c.post_taggings.to_a
|
565
|
+
assert !c.post_taggings.empty?
|
566
|
+
c.save
|
567
|
+
assert !c.post_taggings.empty?
|
568
|
+
end
|
569
|
+
|
570
|
+
private
|
571
|
+
|
572
|
+
def assert_includes_and_joins_equal(query, expected, association)
|
573
|
+
actual = assert_queries(1) { query.joins(association).to_a.uniq }
|
574
|
+
assert_equal expected, actual
|
575
|
+
|
576
|
+
actual = assert_queries(1) { query.includes(association).to_a.uniq }
|
577
|
+
assert_equal expected, actual
|
578
|
+
end
|
579
|
+
end
|