ibm_db 3.0.4-x86-mingw32 → 3.0.5-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 -1
- data/LICENSE +1 -1
- data/MANIFEST +14 -14
- data/README +225 -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 -11884
- 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 +3177 -3177
- data/lib/active_record/connection_adapters/ibmdb_adapter.rb +1 -1
- data/lib/active_record/vendor/db2-i5-zOS.yaml +328 -328
- data/lib/mswin32/ibm_db.rb +122 -122
- 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/active_record/connection_adapters/fake_adapter.rb +46 -46
- data/test/assets/example.log +1 -1
- data/test/assets/test.txt +1 -1
- data/test/cases/adapter_test.rb +276 -261
- data/test/cases/aggregations_test.rb +158 -158
- data/test/cases/ar_schema_test.rb +161 -161
- data/test/cases/associations/association_scope_test.rb +21 -21
- data/test/cases/associations/belongs_to_associations_test.rb +1029 -1029
- data/test/cases/associations/callbacks_test.rb +192 -192
- data/test/cases/associations/cascaded_eager_loading_test.rb +188 -188
- data/test/cases/associations/deprecated_counter_cache_on_has_many_through_test.rb +26 -26
- data/test/cases/associations/eager_load_includes_full_sti_class_test.rb +36 -36
- data/test/cases/associations/eager_load_nested_include_test.rb +128 -128
- data/test/cases/associations/eager_singularization_test.rb +148 -148
- data/test/cases/associations/eager_test.rb +1429 -1411
- data/test/cases/associations/extension_test.rb +82 -82
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +972 -932
- data/test/cases/associations/has_many_associations_test.rb +2182 -2162
- data/test/cases/associations/has_many_through_associations_test.rb +1204 -1204
- data/test/cases/associations/has_one_associations_test.rb +610 -610
- data/test/cases/associations/has_one_through_associations_test.rb +380 -380
- data/test/cases/associations/inner_join_association_test.rb +139 -139
- data/test/cases/associations/inverse_associations_test.rb +706 -693
- data/test/cases/associations/join_model_test.rb +754 -754
- data/test/cases/associations/nested_through_associations_test.rb +579 -579
- data/test/cases/associations/required_test.rb +82 -82
- data/test/cases/associations_test.rb +380 -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/serialization_test.rb +29 -29
- data/test/cases/attribute_methods_test.rb +952 -952
- data/test/cases/attribute_set_test.rb +210 -200
- data/test/cases/attribute_test.rb +180 -180
- data/test/cases/attributes_test.rb +136 -136
- data/test/cases/autosave_association_test.rb +1595 -1595
- data/test/cases/base_test.rb +1664 -1638
- data/test/cases/batches_test.rb +212 -212
- data/test/cases/binary_test.rb +52 -52
- data/test/cases/bind_parameter_test.rb +100 -100
- data/test/cases/calculations_test.rb +646 -646
- data/test/cases/callbacks_test.rb +543 -543
- data/test/cases/clone_test.rb +40 -40
- data/test/cases/coders/yaml_column_test.rb +63 -63
- data/test/cases/column_alias_test.rb +17 -17
- data/test/cases/column_definition_test.rb +123 -123
- data/test/cases/connection_adapters/adapter_leasing_test.rb +54 -54
- data/test/cases/connection_adapters/connection_handler_test.rb +53 -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 +293 -293
- data/test/cases/connection_adapters/mysql_type_lookup_test.rb +65 -65
- data/test/cases/connection_adapters/quoting_test.rb +13 -13
- data/test/cases/connection_adapters/schema_cache_test.rb +56 -56
- data/test/cases/connection_adapters/type_lookup_test.rb +110 -110
- data/test/cases/connection_management_test.rb +122 -122
- data/test/cases/connection_pool_test.rb +346 -346
- data/test/cases/connection_specification/resolver_test.rb +116 -116
- data/test/cases/core_test.rb +112 -112
- data/test/cases/counter_cache_test.rb +209 -209
- data/test/cases/custom_locking_test.rb +17 -17
- data/test/cases/database_statements_test.rb +19 -19
- data/test/cases/date_time_test.rb +61 -61
- data/test/cases/defaults_test.rb +223 -223
- data/test/cases/dirty_test.rb +785 -775
- data/test/cases/disconnected_test.rb +28 -28
- data/test/cases/dup_test.rb +157 -157
- data/test/cases/enum_test.rb +290 -290
- data/test/cases/explain_subscriber_test.rb +64 -64
- data/test/cases/explain_test.rb +76 -76
- data/test/cases/finder_respond_to_test.rb +60 -60
- data/test/cases/finder_test.rb +1169 -1166
- data/test/cases/fixture_set/file_test.rb +138 -138
- data/test/cases/fixtures_test.rb +908 -897
- data/test/cases/forbidden_attributes_protection_test.rb +99 -99
- data/test/cases/habtm_destroy_order_test.rb +61 -61
- data/test/cases/helper.rb +210 -210
- data/test/cases/hot_compatibility_test.rb +54 -54
- data/test/cases/i18n_test.rb +45 -45
- data/test/cases/inheritance_test.rb +375 -375
- data/test/cases/integration_test.rb +139 -139
- data/test/cases/invalid_connection_test.rb +22 -22
- data/test/cases/invalid_date_test.rb +32 -32
- data/test/cases/invertible_migration_test.rb +295 -295
- data/test/cases/json_serialization_test.rb +302 -302
- data/test/cases/locking_test.rb +477 -477
- data/test/cases/log_subscriber_test.rb +136 -136
- data/test/cases/migration/change_schema_test - Copy.rb +448 -448
- data/test/cases/migration/change_schema_test.rb +512 -472
- data/test/cases/migration/change_table_test.rb +224 -224
- data/test/cases/migration/column_attributes_test.rb +192 -192
- data/test/cases/migration/column_positioning_test.rb +56 -56
- data/test/cases/migration/columns_test.rb +304 -304
- data/test/cases/migration/command_recorder_test.rb +305 -305
- data/test/cases/migration/create_join_table_test.rb +148 -148
- data/test/cases/migration/foreign_key_test - Changed.rb +325 -325
- data/test/cases/migration/foreign_key_test.rb +328 -360
- data/test/cases/migration/helper.rb +39 -39
- data/test/cases/migration/index_test.rb +216 -216
- data/test/cases/migration/logger_test.rb +36 -36
- data/test/cases/migration/pending_migrations_test.rb +53 -53
- data/test/cases/migration/references_foreign_key_test.rb +169 -214
- data/test/cases/migration/references_index_test.rb +101 -101
- data/test/cases/migration/references_statements_test.rb +116 -116
- data/test/cases/migration/rename_table_test.rb +93 -93
- data/test/cases/migration/table_and_index_test.rb +24 -24
- data/test/cases/migration_test.rb +959 -959
- data/test/cases/migrator_test.rb +388 -388
- data/test/cases/mixin_test.rb +70 -70
- data/test/cases/modules_test.rb +173 -173
- data/test/cases/multiparameter_attributes_test.rb +350 -350
- data/test/cases/multiple_db_test.rb +115 -115
- data/test/cases/nested_attributes_test.rb +1070 -1057
- data/test/cases/nested_attributes_with_callbacks_test.rb +144 -144
- data/test/cases/persistence_test.rb +909 -909
- data/test/cases/pooled_connections_test.rb +81 -81
- data/test/cases/primary_keys_test.rb +237 -237
- data/test/cases/query_cache_test.rb +326 -326
- data/test/cases/quoting_test.rb +156 -156
- data/test/cases/readonly_test.rb +118 -118
- data/test/cases/reaper_test.rb +85 -85
- data/test/cases/reflection_test.rb +463 -454
- data/test/cases/relation/delegation_test.rb +68 -68
- data/test/cases/relation/merging_test.rb +161 -161
- data/test/cases/relation/mutation_test.rb +165 -165
- data/test/cases/relation/predicate_builder_test.rb +14 -14
- data/test/cases/relation/where_chain_test.rb +181 -181
- data/test/cases/relation/where_test.rb +300 -300
- data/test/cases/relation/where_test2.rb +36 -36
- data/test/cases/relation_test.rb +319 -297
- data/test/cases/relations_test.rb +1815 -1815
- data/test/cases/reload_models_test.rb +22 -22
- data/test/cases/result_test.rb +80 -80
- data/test/cases/sanitize_test.rb +83 -83
- data/test/cases/schema_dumper_test.rb +463 -463
- data/test/cases/scoping/default_scoping_test.rb +454 -454
- data/test/cases/scoping/named_scoping_test.rb +524 -524
- data/test/cases/scoping/relation_scoping_test.rb +357 -357
- data/test/cases/serialization_test.rb +104 -104
- data/test/cases/serialized_attribute_test.rb +277 -277
- data/test/cases/statement_cache_test.rb +98 -98
- data/test/cases/store_test.rb +194 -194
- data/test/cases/tasks/database_tasks_test.rb +398 -396
- data/test/cases/tasks/mysql_rake_test.rb +324 -311
- data/test/cases/tasks/postgresql_rake_test.rb +250 -245
- data/test/cases/tasks/sqlite_rake_test.rb +193 -193
- data/test/cases/test_case.rb +123 -123
- data/test/cases/timestamp_test.rb +467 -468
- data/test/cases/transaction_callbacks_test.rb +452 -452
- data/test/cases/transaction_isolation_test.rb +106 -106
- data/test/cases/transactions_test.rb +817 -817
- data/test/cases/type/decimal_test.rb +56 -51
- data/test/cases/type/integer_test.rb +121 -121
- data/test/cases/type/string_test.rb +36 -36
- data/test/cases/type/type_map_test.rb +177 -177
- data/test/cases/type/unsigned_integer_test.rb +18 -18
- data/test/cases/types_test.rb +141 -141
- data/test/cases/unconnected_test.rb +33 -33
- data/test/cases/validations/association_validation_test.rb +86 -86
- data/test/cases/validations/i18n_generate_message_validation_test.rb +84 -84
- data/test/cases/validations/i18n_validation_test.rb +90 -90
- data/test/cases/validations/length_validation_test.rb +47 -47
- data/test/cases/validations/presence_validation_test.rb +68 -68
- data/test/cases/validations/uniqueness_validation_test.rb +457 -434
- data/test/cases/validations_repair_helper.rb +23 -23
- data/test/cases/validations_test.rb +165 -165
- data/test/cases/view_test.rb +119 -113
- data/test/cases/xml_serialization_test.rb +457 -457
- data/test/cases/yaml_serialization_test.rb +126 -86
- data/test/config.rb +5 -5
- data/test/config.yml +154 -154
- data/test/connections/native_ibm_db/connection.rb +43 -43
- data/test/fixtures/accounts.yml +29 -29
- data/test/fixtures/admin/accounts.yml +2 -2
- data/test/fixtures/admin/randomly_named_a9.yml +7 -7
- data/test/fixtures/admin/randomly_named_b0.yml +7 -7
- data/test/fixtures/admin/users.yml +10 -10
- data/test/fixtures/author_addresses.yml +17 -17
- data/test/fixtures/author_favorites.yml +3 -3
- data/test/fixtures/authors.yml +23 -23
- data/test/fixtures/binaries.yml +133 -133
- data/test/fixtures/books.yml +11 -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/courses.yml +8 -8
- data/test/fixtures/customers.yml +25 -25
- data/test/fixtures/dashboards.yml +6 -6
- data/test/fixtures/developers.yml +21 -21
- 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/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/csv/accounts.csv +1 -1
- 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/organizations.yml +5 -5
- 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 +12 -12
- data/test/fixtures/posts.yml +80 -80
- data/test/fixtures/price_estimates.yml +7 -7
- data/test/fixtures/products.yml +4 -4
- data/test/fixtures/projects.yml +7 -7
- data/test/fixtures/randomly_named_a9.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/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/ibm_db_test.rb +24 -24
- 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 +8 -8
- data/test/migrations/missing/1_people_have_last_names.rb +8 -8
- data/test/migrations/missing/3_we_need_reminders.rb +11 -11
- data/test/migrations/missing/4_innocent_jointable.rb +11 -11
- data/test/migrations/rename/1_we_need_things.rb +10 -10
- data/test/migrations/rename/2_rename_things.rb +8 -8
- 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 +11 -11
- data/test/migrations/valid/3_innocent_jointable.rb +11 -11
- 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 +11 -11
- data/test/migrations/valid_with_subdirectories/sub1/3_innocent_jointable.rb +11 -11
- 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 +4 -4
- data/test/models/admin/account.rb +2 -2
- data/test/models/admin/randomly_named_c1.rb +3 -3
- data/test/models/admin/user.rb +40 -40
- data/test/models/aircraft.rb +4 -4
- data/test/models/arunit2_model.rb +3 -3
- data/test/models/author.rb +212 -212
- data/test/models/auto_id.rb +4 -4
- data/test/models/autoloadable/extra_firm.rb +2 -2
- data/test/models/binary.rb +1 -1
- data/test/models/bird.rb +12 -12
- data/test/models/book.rb +18 -18
- data/test/models/boolean.rb +2 -2
- data/test/models/bulb.rb +51 -51
- data/test/models/cake_designer.rb +3 -3
- data/test/models/car.rb +26 -26
- data/test/models/carrier.rb +2 -2
- data/test/models/categorization.rb +19 -19
- data/test/models/category.rb +35 -35
- data/test/models/chef.rb +7 -3
- data/test/models/citation.rb +3 -3
- data/test/models/club.rb +23 -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 +64 -64
- data/test/models/company.rb +228 -225
- 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/contract.rb +20 -20
- data/test/models/country.rb +7 -7
- data/test/models/course.rb +6 -6
- data/test/models/customer.rb +77 -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 +255 -252
- 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 +2 -2
- 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 +1 -1
- data/test/models/hotel.rb +9 -6
- 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 +41 -41
- data/test/models/member_detail.rb +7 -7
- data/test/models/member_type.rb +3 -3
- data/test/models/membership.rb +35 -35
- 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/molecule.rb +6 -6
- data/test/models/movie.rb +5 -5
- data/test/models/order.rb +4 -4
- data/test/models/organization.rb +14 -14
- data/test/models/owner.rb +34 -34
- data/test/models/parrot.rb +29 -29
- data/test/models/person.rb +143 -143
- data/test/models/personal_legacy_thing.rb +4 -4
- data/test/models/pet.rb +15 -15
- data/test/models/pirate.rb +92 -92
- data/test/models/possession.rb +3 -3
- data/test/models/post.rb +264 -264
- data/test/models/price_estimate.rb +4 -4
- data/test/models/professor.rb +5 -5
- data/test/models/project.rb +31 -29
- 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 +3 -3
- data/test/models/rating.rb +4 -4
- data/test/models/reader.rb +23 -23
- 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 +33 -33
- data/test/models/ship_part.rb +7 -7
- 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 +7 -7
- data/test/models/tagging.rb +13 -13
- data/test/models/task.rb +5 -5
- data/test/models/topic.rb +124 -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/tyre.rb +11 -11
- data/test/models/uuid_child.rb +3 -3
- 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 +58 -58
- data/test/schema/mysql_specific_schema.rb +70 -70
- data/test/schema/oracle_specific_schema.rb +43 -43
- data/test/schema/postgresql_specific_schema.rb +202 -202
- data/test/schema/schema.rb +952 -938
- data/test/schema/sqlite_specific_schema.rb +21 -21
- data/test/support/config.rb +43 -43
- data/test/support/connection.rb +22 -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
- metadata +2 -2
@@ -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, :author_addresses
|
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::HasManyThroughNestedAssociationsAreReadonly) 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
|
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, :author_addresses
|
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::HasManyThroughNestedAssociationsAreReadonly) 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
|