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,2162 +1,2182 @@
|
|
1
|
-
require "cases/helper"
|
2
|
-
require 'models/developer'
|
3
|
-
require 'models/computer'
|
4
|
-
require 'models/project'
|
5
|
-
require 'models/company'
|
6
|
-
require 'models/contract'
|
7
|
-
require 'models/topic'
|
8
|
-
require 'models/reply'
|
9
|
-
require 'models/category'
|
10
|
-
require 'models/image'
|
11
|
-
require 'models/post'
|
12
|
-
require 'models/author'
|
13
|
-
require 'models/essay'
|
14
|
-
require 'models/comment'
|
15
|
-
require 'models/person'
|
16
|
-
require 'models/reader'
|
17
|
-
require 'models/tagging'
|
18
|
-
require 'models/tag'
|
19
|
-
require 'models/invoice'
|
20
|
-
require 'models/line_item'
|
21
|
-
require 'models/car'
|
22
|
-
require 'models/bulb'
|
23
|
-
require 'models/engine'
|
24
|
-
require 'models/categorization'
|
25
|
-
require 'models/minivan'
|
26
|
-
require 'models/speedometer'
|
27
|
-
require 'models/reference'
|
28
|
-
require 'models/job'
|
29
|
-
require 'models/college'
|
30
|
-
require 'models/student'
|
31
|
-
require 'models/pirate'
|
32
|
-
require 'models/ship'
|
33
|
-
require 'models/treasure'
|
34
|
-
require 'models/parrot'
|
35
|
-
require 'models/tyre'
|
36
|
-
require 'models/subscriber'
|
37
|
-
require 'models/subscription'
|
38
|
-
require 'models/zine'
|
39
|
-
require 'models/interest'
|
40
|
-
|
41
|
-
class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
|
42
|
-
fixtures :authors, :posts, :comments, :author_addresses
|
43
|
-
|
44
|
-
def test_should_generate_valid_sql
|
45
|
-
author = authors(:david)
|
46
|
-
# this can fail on adapters which require ORDER BY expressions to be included in the SELECT expression
|
47
|
-
# if the reorder clauses are not correctly handled
|
48
|
-
assert author.posts_with_comments_sorted_by_comment_id.where('comments.id > 0').reorder('posts.comments_count DESC', 'posts.tags_count DESC').last
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
|
53
|
-
fixtures :authors, :essays, :subscribers, :subscriptions, :people
|
54
|
-
|
55
|
-
def test_custom_primary_key_on_new_record_should_fetch_with_query
|
56
|
-
subscriber = Subscriber.new(nick: 'webster132')
|
57
|
-
assert !subscriber.subscriptions.loaded?
|
58
|
-
|
59
|
-
assert_queries 1 do
|
60
|
-
assert_equal 2, subscriber.subscriptions.size
|
61
|
-
end
|
62
|
-
|
63
|
-
assert_equal subscriber.subscriptions, Subscription.where(subscriber_id: 'webster132')
|
64
|
-
end
|
65
|
-
|
66
|
-
def test_association_primary_key_on_new_record_should_fetch_with_query
|
67
|
-
author = Author.new(:name => "David")
|
68
|
-
assert !author.essays.loaded?
|
69
|
-
|
70
|
-
assert_queries 1 do
|
71
|
-
assert_equal 1, author.essays.size
|
72
|
-
end
|
73
|
-
|
74
|
-
assert_equal author.essays, Essay.where(writer_id: "David")
|
75
|
-
end
|
76
|
-
|
77
|
-
def test_has_many_custom_primary_key
|
78
|
-
david = authors(:david)
|
79
|
-
assert_equal david.essays, Essay.where(writer_id: "David")
|
80
|
-
end
|
81
|
-
|
82
|
-
def test_has_many_assignment_with_custom_primary_key
|
83
|
-
david = people(:david)
|
84
|
-
|
85
|
-
assert_equal ["A Modest Proposal"], david.essays.map(&:name)
|
86
|
-
david.essays = [Essay.create!(name: "Remote Work" )]
|
87
|
-
assert_equal ["Remote Work"], david.essays.map(&:name)
|
88
|
-
end
|
89
|
-
|
90
|
-
def test_blank_custom_primary_key_on_new_record_should_not_run_queries
|
91
|
-
author = Author.new
|
92
|
-
assert !author.essays.loaded?
|
93
|
-
|
94
|
-
assert_queries 0 do
|
95
|
-
assert_equal 0, author.essays.size
|
96
|
-
end
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
class HasManyAssociationsTest < ActiveRecord::TestCase
|
101
|
-
fixtures :accounts, :categories, :companies, :developers, :projects,
|
102
|
-
:developers_projects, :topics, :authors, :comments,
|
103
|
-
:posts, :readers, :taggings, :cars, :jobs, :tags,
|
104
|
-
:categorizations, :zines, :interests
|
105
|
-
|
106
|
-
def setup
|
107
|
-
Client.destroyed_client_ids.clear
|
108
|
-
end
|
109
|
-
|
110
|
-
def test_sti_subselect_count
|
111
|
-
tag = Tag.first
|
112
|
-
len = Post.tagged_with(tag.id).limit(10).size
|
113
|
-
assert_operator len, :>, 0
|
114
|
-
end
|
115
|
-
|
116
|
-
def test_anonymous_has_many
|
117
|
-
developer = Class.new(ActiveRecord::Base) {
|
118
|
-
self.table_name = 'developers'
|
119
|
-
dev = self
|
120
|
-
|
121
|
-
developer_project = Class.new(ActiveRecord::Base) {
|
122
|
-
self.table_name = 'developers_projects'
|
123
|
-
belongs_to :developer, :anonymous_class => dev
|
124
|
-
}
|
125
|
-
has_many :developer_projects, :anonymous_class => developer_project, :foreign_key => 'developer_id'
|
126
|
-
}
|
127
|
-
dev = developer.first
|
128
|
-
named = Developer.find(dev.id)
|
129
|
-
assert_operator dev.developer_projects.count, :>, 0
|
130
|
-
assert_equal named.projects.map(&:id).sort,
|
131
|
-
dev.developer_projects.map(&:project_id).sort
|
132
|
-
end
|
133
|
-
|
134
|
-
def test_default_scope_on_relations_is_not_cached
|
135
|
-
counter = 0
|
136
|
-
posts = Class.new(ActiveRecord::Base) {
|
137
|
-
self.table_name = 'posts'
|
138
|
-
self.inheritance_column = 'not_there'
|
139
|
-
post = self
|
140
|
-
|
141
|
-
comments = Class.new(ActiveRecord::Base) {
|
142
|
-
self.table_name = 'comments'
|
143
|
-
self.inheritance_column = 'not_there'
|
144
|
-
belongs_to :post, :anonymous_class => post
|
145
|
-
default_scope -> {
|
146
|
-
counter += 1
|
147
|
-
where("id = :inc", :inc => counter)
|
148
|
-
}
|
149
|
-
}
|
150
|
-
has_many :comments, :anonymous_class => comments, :foreign_key => 'post_id'
|
151
|
-
}
|
152
|
-
assert_equal 0, counter
|
153
|
-
post = posts.first
|
154
|
-
assert_equal 0, counter
|
155
|
-
sql = capture_sql { post.comments.to_a }
|
156
|
-
post.comments.reset
|
157
|
-
assert_not_equal sql, capture_sql { post.comments.to_a }
|
158
|
-
end
|
159
|
-
|
160
|
-
def test_has_many_build_with_options
|
161
|
-
college = College.create(name: 'UFMT')
|
162
|
-
Student.create(active: true, college_id: college.id, name: 'Sarah')
|
163
|
-
|
164
|
-
assert_equal college.students, Student.where(active: true, college_id: college.id)
|
165
|
-
end
|
166
|
-
|
167
|
-
def test_create_from_association_should_respect_default_scope
|
168
|
-
car = Car.create(:name => 'honda')
|
169
|
-
assert_equal 'honda', car.name
|
170
|
-
|
171
|
-
bulb = Bulb.create
|
172
|
-
assert_equal 'defaulty', bulb.name
|
173
|
-
|
174
|
-
bulb = car.bulbs.build
|
175
|
-
assert_equal 'defaulty', bulb.name
|
176
|
-
|
177
|
-
bulb = car.bulbs.create
|
178
|
-
assert_equal 'defaulty', bulb.name
|
179
|
-
|
180
|
-
bulb = car.bulbs.create(:name => 'exotic')
|
181
|
-
assert_equal 'exotic', bulb.name
|
182
|
-
end
|
183
|
-
|
184
|
-
def test_build_from_association_should_respect_scope
|
185
|
-
author = Author.new
|
186
|
-
|
187
|
-
post = author.thinking_posts.build
|
188
|
-
assert_equal 'So I was thinking', post.title
|
189
|
-
end
|
190
|
-
|
191
|
-
def test_create_from_association_with_nil_values_should_work
|
192
|
-
car = Car.create(:name => 'honda')
|
193
|
-
|
194
|
-
bulb = car.bulbs.new(nil)
|
195
|
-
assert_equal 'defaulty', bulb.name
|
196
|
-
|
197
|
-
bulb = car.bulbs.build(nil)
|
198
|
-
assert_equal 'defaulty', bulb.name
|
199
|
-
|
200
|
-
bulb = car.bulbs.create(nil)
|
201
|
-
assert_equal 'defaulty', bulb.name
|
202
|
-
end
|
203
|
-
|
204
|
-
def test_do_not_call_callbacks_for_delete_all
|
205
|
-
car = Car.create(:name => 'honda')
|
206
|
-
car.funky_bulbs.create!
|
207
|
-
assert_nothing_raised { car.reload.funky_bulbs.delete_all }
|
208
|
-
assert_equal 0, Bulb.count, "bulbs should have been deleted using :delete_all strategy"
|
209
|
-
end
|
210
|
-
|
211
|
-
def test_delete_all_on_association_is_the_same_as_not_loaded
|
212
|
-
author = authors :david
|
213
|
-
author.thinking_posts.create!(:body => "test")
|
214
|
-
author.reload
|
215
|
-
expected_sql = capture_sql { author.thinking_posts.delete_all }
|
216
|
-
|
217
|
-
author.thinking_posts.create!(:body => "test")
|
218
|
-
author.reload
|
219
|
-
author.thinking_posts.inspect
|
220
|
-
loaded_sql = capture_sql { author.thinking_posts.delete_all }
|
221
|
-
assert_equal(expected_sql, loaded_sql)
|
222
|
-
end
|
223
|
-
|
224
|
-
def test_delete_all_on_association_with_nil_dependency_is_the_same_as_not_loaded
|
225
|
-
author = authors :david
|
226
|
-
author.posts.create!(:title => "test", :body => "body")
|
227
|
-
author.reload
|
228
|
-
expected_sql = capture_sql { author.posts.delete_all }
|
229
|
-
|
230
|
-
author.posts.create!(:title => "test", :body => "body")
|
231
|
-
author.reload
|
232
|
-
author.posts.to_a
|
233
|
-
loaded_sql = capture_sql { author.posts.delete_all }
|
234
|
-
assert_equal(expected_sql, loaded_sql)
|
235
|
-
end
|
236
|
-
|
237
|
-
def test_building_the_associated_object_with_implicit_sti_base_class
|
238
|
-
firm = DependentFirm.new
|
239
|
-
company = firm.companies.build
|
240
|
-
assert_kind_of Company, company, "Expected #{company.class} to be a Company"
|
241
|
-
end
|
242
|
-
|
243
|
-
def test_building_the_associated_object_with_explicit_sti_base_class
|
244
|
-
firm = DependentFirm.new
|
245
|
-
company = firm.companies.build(:type => "Company")
|
246
|
-
assert_kind_of Company, company, "Expected #{company.class} to be a Company"
|
247
|
-
end
|
248
|
-
|
249
|
-
def test_building_the_associated_object_with_sti_subclass
|
250
|
-
firm = DependentFirm.new
|
251
|
-
company = firm.companies.build(:type => "Client")
|
252
|
-
assert_kind_of Client, company, "Expected #{company.class} to be a Client"
|
253
|
-
end
|
254
|
-
|
255
|
-
def test_building_the_associated_object_with_an_invalid_type
|
256
|
-
firm = DependentFirm.new
|
257
|
-
assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Invalid") }
|
258
|
-
end
|
259
|
-
|
260
|
-
def test_building_the_associated_object_with_an_unrelated_type
|
261
|
-
firm = DependentFirm.new
|
262
|
-
assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Account") }
|
263
|
-
end
|
264
|
-
|
265
|
-
test "building the association with an array" do
|
266
|
-
speedometer = Speedometer.new(speedometer_id: "a")
|
267
|
-
data = [{name: "first"}, {name: "second"}]
|
268
|
-
speedometer.minivans.build(data)
|
269
|
-
|
270
|
-
assert_equal 2, speedometer.minivans.size
|
271
|
-
assert speedometer.save
|
272
|
-
assert_equal ["first", "second"], speedometer.reload.minivans.map(&:name)
|
273
|
-
end
|
274
|
-
|
275
|
-
def test_association_keys_bypass_attribute_protection
|
276
|
-
car = Car.create(:name => 'honda')
|
277
|
-
|
278
|
-
bulb = car.bulbs.new
|
279
|
-
assert_equal car.id, bulb.car_id
|
280
|
-
|
281
|
-
bulb = car.bulbs.new :car_id => car.id + 1
|
282
|
-
assert_equal car.id, bulb.car_id
|
283
|
-
|
284
|
-
bulb = car.bulbs.build
|
285
|
-
assert_equal car.id, bulb.car_id
|
286
|
-
|
287
|
-
bulb = car.bulbs.build :car_id => car.id + 1
|
288
|
-
assert_equal car.id, bulb.car_id
|
289
|
-
|
290
|
-
bulb = car.bulbs.create
|
291
|
-
assert_equal car.id, bulb.car_id
|
292
|
-
|
293
|
-
bulb = car.bulbs.create :car_id => car.id + 1
|
294
|
-
assert_equal car.id, bulb.car_id
|
295
|
-
end
|
296
|
-
|
297
|
-
def test_association_protect_foreign_key
|
298
|
-
invoice = Invoice.create
|
299
|
-
|
300
|
-
line_item = invoice.line_items.new
|
301
|
-
assert_equal invoice.id, line_item.invoice_id
|
302
|
-
|
303
|
-
line_item = invoice.line_items.new :invoice_id => invoice.id + 1
|
304
|
-
assert_equal invoice.id, line_item.invoice_id
|
305
|
-
|
306
|
-
line_item = invoice.line_items.build
|
307
|
-
assert_equal invoice.id, line_item.invoice_id
|
308
|
-
|
309
|
-
line_item = invoice.line_items.build :invoice_id => invoice.id + 1
|
310
|
-
assert_equal invoice.id, line_item.invoice_id
|
311
|
-
|
312
|
-
line_item = invoice.line_items.create
|
313
|
-
assert_equal invoice.id, line_item.invoice_id
|
314
|
-
|
315
|
-
line_item = invoice.line_items.create :invoice_id => invoice.id + 1
|
316
|
-
assert_equal invoice.id, line_item.invoice_id
|
317
|
-
end
|
318
|
-
|
319
|
-
# When creating objects on the association, we must not do it within a scope (even though it
|
320
|
-
# would be convenient), because this would cause that scope to be applied to any callbacks etc.
|
321
|
-
def test_build_and_create_should_not_happen_within_scope
|
322
|
-
car = cars(:honda)
|
323
|
-
scoped_count = car.foo_bulbs.where_values.count
|
324
|
-
|
325
|
-
bulb = car.foo_bulbs.build
|
326
|
-
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
|
327
|
-
|
328
|
-
bulb = car.foo_bulbs.create
|
329
|
-
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
|
330
|
-
|
331
|
-
bulb = car.foo_bulbs.create!
|
332
|
-
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
|
333
|
-
end
|
334
|
-
|
335
|
-
def test_no_sql_should_be_fired_if_association_already_loaded
|
336
|
-
Car.create(:name => 'honda')
|
337
|
-
bulbs = Car.first.bulbs
|
338
|
-
bulbs.to_a # to load all instances of bulbs
|
339
|
-
|
340
|
-
assert_no_queries do
|
341
|
-
bulbs.first()
|
342
|
-
bulbs.first({})
|
343
|
-
end
|
344
|
-
|
345
|
-
assert_no_queries do
|
346
|
-
bulbs.second()
|
347
|
-
bulbs.second({})
|
348
|
-
end
|
349
|
-
|
350
|
-
assert_no_queries do
|
351
|
-
bulbs.third()
|
352
|
-
bulbs.third({})
|
353
|
-
end
|
354
|
-
|
355
|
-
assert_no_queries do
|
356
|
-
bulbs.fourth()
|
357
|
-
bulbs.fourth({})
|
358
|
-
end
|
359
|
-
|
360
|
-
assert_no_queries do
|
361
|
-
bulbs.fifth()
|
362
|
-
bulbs.fifth({})
|
363
|
-
end
|
364
|
-
|
365
|
-
assert_no_queries do
|
366
|
-
bulbs.forty_two()
|
367
|
-
bulbs.forty_two({})
|
368
|
-
end
|
369
|
-
|
370
|
-
assert_no_queries do
|
371
|
-
bulbs.last()
|
372
|
-
bulbs.last({})
|
373
|
-
end
|
374
|
-
end
|
375
|
-
|
376
|
-
def test_create_resets_cached_counters
|
377
|
-
person = Person.create!(:first_name => 'tenderlove')
|
378
|
-
post = Post.first
|
379
|
-
|
380
|
-
assert_equal [], person.readers
|
381
|
-
assert_nil person.readers.find_by_post_id(post.id)
|
382
|
-
|
383
|
-
person.readers.create(:post_id => post.id)
|
384
|
-
|
385
|
-
assert_equal 1, person.readers.count
|
386
|
-
assert_equal 1, person.readers.length
|
387
|
-
assert_equal post, person.readers.first.post
|
388
|
-
assert_equal person, person.readers.first.person
|
389
|
-
end
|
390
|
-
|
391
|
-
def force_signal37_to_load_all_clients_of_firm
|
392
|
-
companies(:first_firm).clients_of_firm.each {|f| }
|
393
|
-
end
|
394
|
-
|
395
|
-
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
|
396
|
-
def test_counting_with_counter_sql
|
397
|
-
assert_equal 3, Firm.all.merge!(:order => "id").first.clients.count
|
398
|
-
end
|
399
|
-
|
400
|
-
def test_counting
|
401
|
-
assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count
|
402
|
-
end
|
403
|
-
|
404
|
-
def test_counting_with_single_hash
|
405
|
-
assert_equal 1, Firm.all.merge!(:order => "id").first.plain_clients.where(:name => "Microsoft").count
|
406
|
-
end
|
407
|
-
|
408
|
-
def test_counting_with_column_name_and_hash
|
409
|
-
assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
|
410
|
-
end
|
411
|
-
|
412
|
-
def test_counting_with_association_limit
|
413
|
-
firm = companies(:first_firm)
|
414
|
-
assert_equal firm.limited_clients.length, firm.limited_clients.size
|
415
|
-
assert_equal firm.limited_clients.length, firm.limited_clients.count
|
416
|
-
end
|
417
|
-
|
418
|
-
def test_finding
|
419
|
-
assert_equal 3, Firm.all.merge!(:order => "id").first.clients.length
|
420
|
-
end
|
421
|
-
|
422
|
-
def test_finding_array_compatibility
|
423
|
-
assert_equal 3, Firm.order(:id).find{|f| f.id > 0}.clients.length
|
424
|
-
end
|
425
|
-
|
426
|
-
def test_find_many_with_merged_options
|
427
|
-
assert_equal 1, companies(:first_firm).limited_clients.size
|
428
|
-
assert_equal 1, companies(:first_firm).limited_clients.to_a.size
|
429
|
-
assert_equal 3, companies(:first_firm).limited_clients.limit(nil).to_a.size
|
430
|
-
end
|
431
|
-
|
432
|
-
def test_find_should_append_to_association_order
|
433
|
-
ordered_clients = companies(:first_firm).clients_sorted_desc.order('companies.id')
|
434
|
-
assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
|
435
|
-
end
|
436
|
-
|
437
|
-
def test_dynamic_find_should_respect_association_order
|
438
|
-
assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
|
439
|
-
assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
|
440
|
-
end
|
441
|
-
|
442
|
-
def test_taking
|
443
|
-
posts(:other_by_bob).destroy
|
444
|
-
assert_equal posts(:misc_by_bob), authors(:bob).posts.take
|
445
|
-
assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
|
446
|
-
authors(:bob).posts.to_a
|
447
|
-
assert_equal posts(:misc_by_bob), authors(:bob).posts.take
|
448
|
-
assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
|
449
|
-
end
|
450
|
-
|
451
|
-
def test_taking_not_found
|
452
|
-
authors(:bob).posts.delete_all
|
453
|
-
assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
|
454
|
-
authors(:bob).posts.to_a
|
455
|
-
assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
|
456
|
-
end
|
457
|
-
|
458
|
-
def test_taking_with_a_number
|
459
|
-
# taking from unloaded Relation
|
460
|
-
bob = Author.find(authors(:bob).id)
|
461
|
-
assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
|
462
|
-
bob = Author.find(authors(:bob).id)
|
463
|
-
assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
|
464
|
-
|
465
|
-
# taking from loaded Relation
|
466
|
-
bob.posts.to_a
|
467
|
-
assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
|
468
|
-
assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
|
469
|
-
end
|
470
|
-
|
471
|
-
def test_taking_with_inverse_of
|
472
|
-
interests(:woodsmanship).destroy
|
473
|
-
interests(:survival).destroy
|
474
|
-
|
475
|
-
zine = zines(:going_out)
|
476
|
-
interest = zine.interests.take
|
477
|
-
assert_equal interests(:hunting), interest
|
478
|
-
assert_same zine, interest.zine
|
479
|
-
end
|
480
|
-
|
481
|
-
def test_cant_save_has_many_readonly_association
|
482
|
-
authors(:david).readonly_comments.each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
|
483
|
-
authors(:david).readonly_comments.each { |c| assert c.readonly? }
|
484
|
-
end
|
485
|
-
|
486
|
-
def test_finding_default_orders
|
487
|
-
assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients.first.name
|
488
|
-
end
|
489
|
-
|
490
|
-
def test_finding_with_different_class_name_and_order
|
491
|
-
assert_equal "Apex", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
|
492
|
-
end
|
493
|
-
|
494
|
-
def test_finding_with_foreign_key
|
495
|
-
assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_of_firm.first.name
|
496
|
-
end
|
497
|
-
|
498
|
-
def test_finding_with_condition
|
499
|
-
assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms.first.name
|
500
|
-
end
|
501
|
-
|
502
|
-
def test_finding_with_condition_hash
|
503
|
-
assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
|
504
|
-
end
|
505
|
-
|
506
|
-
def test_finding_using_primary_key
|
507
|
-
assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients_using_primary_key.first.name
|
508
|
-
end
|
509
|
-
|
510
|
-
def test_update_all_on_association_accessed_before_save
|
511
|
-
firm = Firm.new(name: 'Firm')
|
512
|
-
firm.clients << Client.first
|
513
|
-
firm.save!
|
514
|
-
assert_equal firm.clients.count, firm.clients.update_all(description: 'Great!')
|
515
|
-
end
|
516
|
-
|
517
|
-
def test_belongs_to_sanity
|
518
|
-
c = Client.new
|
519
|
-
assert_nil c.firm, "belongs_to failed sanity check on new object"
|
520
|
-
end
|
521
|
-
|
522
|
-
def test_find_ids
|
523
|
-
firm = Firm.all.merge!(:order => "id").first
|
524
|
-
|
525
|
-
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
|
526
|
-
|
527
|
-
client = firm.clients.find(2)
|
528
|
-
assert_kind_of Client, client
|
529
|
-
|
530
|
-
client_ary = firm.clients.find([2])
|
531
|
-
assert_kind_of Array, client_ary
|
532
|
-
assert_equal client, client_ary.first
|
533
|
-
|
534
|
-
client_ary = firm.clients.find(2, 3)
|
535
|
-
assert_kind_of Array, client_ary
|
536
|
-
assert_equal 2, client_ary.size
|
537
|
-
assert_equal client, client_ary.first
|
538
|
-
|
539
|
-
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
|
540
|
-
end
|
541
|
-
|
542
|
-
def test_find_ids_and_inverse_of
|
543
|
-
force_signal37_to_load_all_clients_of_firm
|
544
|
-
|
545
|
-
firm = companies(:first_firm)
|
546
|
-
client = firm.clients_of_firm.find(3)
|
547
|
-
assert_kind_of Client, client
|
548
|
-
|
549
|
-
client_ary = firm.clients_of_firm.find([3])
|
550
|
-
assert_kind_of Array, client_ary
|
551
|
-
assert_equal client, client_ary.first
|
552
|
-
end
|
553
|
-
|
554
|
-
def test_find_all
|
555
|
-
firm = Firm.all.merge!(:order => "id").first
|
556
|
-
assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
|
557
|
-
assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
|
558
|
-
end
|
559
|
-
|
560
|
-
def test_find_each
|
561
|
-
firm = companies(:first_firm)
|
562
|
-
|
563
|
-
assert ! firm.clients.loaded?
|
564
|
-
|
565
|
-
assert_queries(4) do
|
566
|
-
firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
|
567
|
-
end
|
568
|
-
|
569
|
-
assert ! firm.clients.loaded?
|
570
|
-
end
|
571
|
-
|
572
|
-
def test_find_each_with_conditions
|
573
|
-
firm = companies(:first_firm)
|
574
|
-
|
575
|
-
assert_queries(2) do
|
576
|
-
firm.clients.where(name: 'Microsoft').find_each(batch_size: 1) do |c|
|
577
|
-
assert_equal firm.id, c.firm_id
|
578
|
-
assert_equal "Microsoft", c.name
|
579
|
-
end
|
580
|
-
end
|
581
|
-
|
582
|
-
assert ! firm.clients.loaded?
|
583
|
-
end
|
584
|
-
|
585
|
-
def test_find_in_batches
|
586
|
-
firm = companies(:first_firm)
|
587
|
-
|
588
|
-
assert ! firm.clients.loaded?
|
589
|
-
|
590
|
-
assert_queries(2) do
|
591
|
-
firm.clients.find_in_batches(:batch_size => 2) do |clients|
|
592
|
-
clients.each {|c| assert_equal firm.id, c.firm_id }
|
593
|
-
end
|
594
|
-
end
|
595
|
-
|
596
|
-
assert ! firm.clients.loaded?
|
597
|
-
end
|
598
|
-
|
599
|
-
def test_find_all_sanitized
|
600
|
-
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
|
601
|
-
firm = Firm.all.merge!(:order => "id").first
|
602
|
-
summit = firm.clients.where("name = 'Summit'").to_a
|
603
|
-
assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
|
604
|
-
assert_equal summit, firm.clients.where("name = :name", { :name => "Summit" }).to_a
|
605
|
-
end
|
606
|
-
|
607
|
-
def test_find_first
|
608
|
-
firm = Firm.all.merge!(:order => "id").first
|
609
|
-
client2 = Client.find(2)
|
610
|
-
assert_equal firm.clients.first, firm.clients.order("id").first
|
611
|
-
assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first
|
612
|
-
end
|
613
|
-
|
614
|
-
def test_find_first_sanitized
|
615
|
-
firm = Firm.all.merge!(:order => "id").first
|
616
|
-
client2 = Client.find(2)
|
617
|
-
assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
|
618
|
-
assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
|
619
|
-
end
|
620
|
-
|
621
|
-
def test_find_all_with_include_and_conditions
|
622
|
-
assert_nothing_raised do
|
623
|
-
Developer.all.merge!(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).to_a
|
624
|
-
end
|
625
|
-
end
|
626
|
-
|
627
|
-
def test_find_in_collection
|
628
|
-
assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
|
629
|
-
assert_raise(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
|
630
|
-
end
|
631
|
-
|
632
|
-
def test_find_grouped
|
633
|
-
all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
|
634
|
-
grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
|
635
|
-
assert_equal 3, all_clients_of_firm1.size
|
636
|
-
assert_equal 1, grouped_clients_of_firm1.size
|
637
|
-
end
|
638
|
-
|
639
|
-
def test_find_scoped_grouped
|
640
|
-
assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.size
|
641
|
-
assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.length
|
642
|
-
assert_equal 3, companies(:first_firm).clients_grouped_by_name.size
|
643
|
-
assert_equal 3, companies(:first_firm).clients_grouped_by_name.length
|
644
|
-
end
|
645
|
-
|
646
|
-
def test_find_scoped_grouped_having
|
647
|
-
assert_equal 1, authors(:david).popular_grouped_posts.length
|
648
|
-
assert_equal 0, authors(:mary).popular_grouped_posts.length
|
649
|
-
end
|
650
|
-
|
651
|
-
def test_default_select
|
652
|
-
assert_equal Comment.column_names.sort, posts(:welcome).comments.first.attributes.keys.sort
|
653
|
-
end
|
654
|
-
|
655
|
-
def test_select_query_method
|
656
|
-
assert_equal ['id', 'body'], posts(:welcome).comments.select(:id, :body).first.attributes.keys
|
657
|
-
end
|
658
|
-
|
659
|
-
def test_select_with_block
|
660
|
-
assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
|
661
|
-
end
|
662
|
-
|
663
|
-
def test_select_without_foreign_key
|
664
|
-
assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit
|
665
|
-
end
|
666
|
-
|
667
|
-
def test_adding
|
668
|
-
force_signal37_to_load_all_clients_of_firm
|
669
|
-
natural = Client.new("name" => "Natural Company")
|
670
|
-
companies(:first_firm).clients_of_firm << natural
|
671
|
-
assert_equal 3, companies(:first_firm).clients_of_firm.size # checking via the collection
|
672
|
-
assert_equal 3, companies(:first_firm).clients_of_firm(true).size # checking using the db
|
673
|
-
assert_equal natural, companies(:first_firm).clients_of_firm.last
|
674
|
-
end
|
675
|
-
|
676
|
-
def test_adding_using_create
|
677
|
-
first_firm = companies(:first_firm)
|
678
|
-
assert_equal 3, first_firm.plain_clients.size
|
679
|
-
first_firm.plain_clients.create(:name => "Natural Company")
|
680
|
-
assert_equal 4, first_firm.plain_clients.length
|
681
|
-
assert_equal 4, first_firm.plain_clients.size
|
682
|
-
end
|
683
|
-
|
684
|
-
def test_create_with_bang_on_has_many_when_parent_is_new_raises
|
685
|
-
error = assert_raise(ActiveRecord::RecordNotSaved) do
|
686
|
-
firm = Firm.new
|
687
|
-
firm.plain_clients.create! :name=>"Whoever"
|
688
|
-
end
|
689
|
-
|
690
|
-
assert_equal "You cannot call create unless the parent is saved", error.message
|
691
|
-
end
|
692
|
-
|
693
|
-
def test_regular_create_on_has_many_when_parent_is_new_raises
|
694
|
-
error = assert_raise(ActiveRecord::RecordNotSaved) do
|
695
|
-
firm = Firm.new
|
696
|
-
firm.plain_clients.create :name=>"Whoever"
|
697
|
-
end
|
698
|
-
|
699
|
-
assert_equal "You cannot call create unless the parent is saved", error.message
|
700
|
-
end
|
701
|
-
|
702
|
-
def test_create_with_bang_on_has_many_raises_when_record_not_saved
|
703
|
-
assert_raise(ActiveRecord::RecordInvalid) do
|
704
|
-
firm = Firm.all.merge!(:order => "id").first
|
705
|
-
firm.plain_clients.create!
|
706
|
-
end
|
707
|
-
end
|
708
|
-
|
709
|
-
def test_create_with_bang_on_habtm_when_parent_is_new_raises
|
710
|
-
error = assert_raise(ActiveRecord::RecordNotSaved) do
|
711
|
-
Developer.new("name" => "Aredridel").projects.create!
|
712
|
-
end
|
713
|
-
|
714
|
-
assert_equal "You cannot call create unless the parent is saved", error.message
|
715
|
-
end
|
716
|
-
|
717
|
-
def test_adding_a_mismatch_class
|
718
|
-
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
|
719
|
-
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
|
720
|
-
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
|
721
|
-
end
|
722
|
-
|
723
|
-
def test_adding_a_collection
|
724
|
-
force_signal37_to_load_all_clients_of_firm
|
725
|
-
companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
|
726
|
-
assert_equal 4, companies(:first_firm).clients_of_firm.size
|
727
|
-
assert_equal 4, companies(:first_firm).clients_of_firm(true).size
|
728
|
-
end
|
729
|
-
|
730
|
-
def test_transactions_when_adding_to_persisted
|
731
|
-
good = Client.new(:name => "Good")
|
732
|
-
bad = Client.new(:name => "Bad", :raise_on_save => true)
|
733
|
-
|
734
|
-
begin
|
735
|
-
companies(:first_firm).clients_of_firm.concat(good, bad)
|
736
|
-
rescue Client::RaisedOnSave
|
737
|
-
end
|
738
|
-
|
739
|
-
assert !companies(:first_firm).clients_of_firm(true).include?(good)
|
740
|
-
end
|
741
|
-
|
742
|
-
def test_transactions_when_adding_to_new_record
|
743
|
-
assert_no_queries(ignore_none: false) do
|
744
|
-
firm = Firm.new
|
745
|
-
firm.clients_of_firm.concat(Client.new("name" => "Natural Company"))
|
746
|
-
end
|
747
|
-
end
|
748
|
-
|
749
|
-
def test_inverse_on_before_validate
|
750
|
-
firm = companies(:first_firm)
|
751
|
-
assert_queries(1) do
|
752
|
-
firm.clients_of_firm << Client.new("name" => "Natural Company")
|
753
|
-
end
|
754
|
-
end
|
755
|
-
|
756
|
-
def test_new_aliased_to_build
|
757
|
-
company = companies(:first_firm)
|
758
|
-
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.new("name" => "Another Client") }
|
759
|
-
assert !company.clients_of_firm.loaded?
|
760
|
-
|
761
|
-
assert_equal "Another Client", new_client.name
|
762
|
-
assert !new_client.persisted?
|
763
|
-
assert_equal new_client, company.clients_of_firm.last
|
764
|
-
end
|
765
|
-
|
766
|
-
def test_build
|
767
|
-
company = companies(:first_firm)
|
768
|
-
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
|
769
|
-
assert !company.clients_of_firm.loaded?
|
770
|
-
|
771
|
-
assert_equal "Another Client", new_client.name
|
772
|
-
assert !new_client.persisted?
|
773
|
-
assert_equal new_client, company.clients_of_firm.last
|
774
|
-
end
|
775
|
-
|
776
|
-
def test_collection_size_after_building
|
777
|
-
company = companies(:first_firm) # company already has one client
|
778
|
-
company.clients_of_firm.build("name" => "Another Client")
|
779
|
-
company.clients_of_firm.build("name" => "Yet Another Client")
|
780
|
-
assert_equal 4, company.clients_of_firm.size
|
781
|
-
end
|
782
|
-
|
783
|
-
def test_collection_not_empty_after_building
|
784
|
-
company = companies(:first_firm)
|
785
|
-
assert_predicate company.contracts, :empty?
|
786
|
-
company.contracts.build
|
787
|
-
assert_not_predicate company.contracts, :empty?
|
788
|
-
end
|
789
|
-
|
790
|
-
def test_collection_size_twice_for_regressions
|
791
|
-
post = posts(:thinking)
|
792
|
-
assert_equal 0, post.readers.size
|
793
|
-
# This test needs a post that has no readers, we assert it to ensure it holds,
|
794
|
-
# but need to reload the post because the very call to #size hides the bug.
|
795
|
-
post.reload
|
796
|
-
post.readers.build
|
797
|
-
size1 = post.readers.size
|
798
|
-
size2 = post.readers.size
|
799
|
-
assert_equal size1, size2
|
800
|
-
end
|
801
|
-
|
802
|
-
def test_build_many
|
803
|
-
company = companies(:first_firm)
|
804
|
-
new_clients = assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
|
805
|
-
assert_equal 2, new_clients.size
|
806
|
-
end
|
807
|
-
|
808
|
-
def test_build_followed_by_save_does_not_load_target
|
809
|
-
companies(:first_firm).clients_of_firm.build("name" => "Another Client")
|
810
|
-
assert companies(:first_firm).save
|
811
|
-
assert !companies(:first_firm).clients_of_firm.loaded?
|
812
|
-
end
|
813
|
-
|
814
|
-
def test_build_without_loading_association
|
815
|
-
first_topic = topics(:first)
|
816
|
-
Reply.column_names
|
817
|
-
|
818
|
-
assert_equal 1, first_topic.replies.length
|
819
|
-
|
820
|
-
assert_no_queries do
|
821
|
-
first_topic.replies.build(:title => "Not saved", :content => "Superstars")
|
822
|
-
assert_equal 2, first_topic.replies.size
|
823
|
-
end
|
824
|
-
|
825
|
-
assert_equal 2, first_topic.replies.to_ary.size
|
826
|
-
end
|
827
|
-
|
828
|
-
def test_build_via_block
|
829
|
-
company = companies(:first_firm)
|
830
|
-
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
|
831
|
-
assert !company.clients_of_firm.loaded?
|
832
|
-
|
833
|
-
assert_equal "Another Client", new_client.name
|
834
|
-
assert !new_client.persisted?
|
835
|
-
assert_equal new_client, company.clients_of_firm.last
|
836
|
-
end
|
837
|
-
|
838
|
-
def test_build_many_via_block
|
839
|
-
company = companies(:first_firm)
|
840
|
-
new_clients = assert_no_queries(ignore_none: false) do
|
841
|
-
company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
|
842
|
-
client.name = "changed"
|
843
|
-
end
|
844
|
-
end
|
845
|
-
|
846
|
-
assert_equal 2, new_clients.size
|
847
|
-
assert_equal "changed", new_clients.first.name
|
848
|
-
assert_equal "changed", new_clients.last.name
|
849
|
-
end
|
850
|
-
|
851
|
-
def test_create_without_loading_association
|
852
|
-
first_firm = companies(:first_firm)
|
853
|
-
Firm.column_names
|
854
|
-
Client.column_names
|
855
|
-
|
856
|
-
assert_equal 2, first_firm.clients_of_firm.size
|
857
|
-
first_firm.clients_of_firm.reset
|
858
|
-
|
859
|
-
assert_queries(1) do
|
860
|
-
first_firm.clients_of_firm.create(:name => "Superstars")
|
861
|
-
end
|
862
|
-
|
863
|
-
assert_equal 3, first_firm.clients_of_firm.size
|
864
|
-
end
|
865
|
-
|
866
|
-
def test_create
|
867
|
-
force_signal37_to_load_all_clients_of_firm
|
868
|
-
new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
869
|
-
assert new_client.persisted?
|
870
|
-
assert_equal new_client, companies(:first_firm).clients_of_firm.last
|
871
|
-
assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
|
872
|
-
end
|
873
|
-
|
874
|
-
def test_create_many
|
875
|
-
companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
|
876
|
-
assert_equal 4, companies(:first_firm).clients_of_firm(true).size
|
877
|
-
end
|
878
|
-
|
879
|
-
def test_create_followed_by_save_does_not_load_target
|
880
|
-
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
881
|
-
assert companies(:first_firm).save
|
882
|
-
assert !companies(:first_firm).clients_of_firm.loaded?
|
883
|
-
end
|
884
|
-
|
885
|
-
def test_deleting
|
886
|
-
force_signal37_to_load_all_clients_of_firm
|
887
|
-
companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
|
888
|
-
assert_equal 1, companies(:first_firm).clients_of_firm.size
|
889
|
-
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
890
|
-
end
|
891
|
-
|
892
|
-
def test_deleting_before_save
|
893
|
-
new_firm = Firm.new("name" => "A New Firm, Inc.")
|
894
|
-
new_client = new_firm.clients_of_firm.build("name" => "Another Client")
|
895
|
-
assert_equal 1, new_firm.clients_of_firm.size
|
896
|
-
new_firm.clients_of_firm.delete(new_client)
|
897
|
-
assert_equal 0, new_firm.clients_of_firm.size
|
898
|
-
end
|
899
|
-
|
900
|
-
def test_has_many_without_counter_cache_option
|
901
|
-
# Ship has a conventionally named `treasures_count` column, but the counter_cache
|
902
|
-
# option is not given on the association.
|
903
|
-
ship = Ship.create(name: 'Countless', treasures_count: 10)
|
904
|
-
|
905
|
-
assert_not ship.treasures.instance_variable_get('@association').send(:has_cached_counter?)
|
906
|
-
|
907
|
-
# Count should come from sql count() of treasures rather than treasures_count attribute
|
908
|
-
assert_equal ship.treasures.size, 0
|
909
|
-
|
910
|
-
assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
|
911
|
-
ship.treasures.create(name: 'Gold')
|
912
|
-
end
|
913
|
-
|
914
|
-
assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
|
915
|
-
ship.treasures.destroy_all
|
916
|
-
end
|
917
|
-
end
|
918
|
-
|
919
|
-
def test_deleting_updates_counter_cache
|
920
|
-
topic = Topic.order("id ASC").first
|
921
|
-
assert_equal topic.replies.to_a.size, topic.replies_count
|
922
|
-
|
923
|
-
topic.replies.delete(topic.replies.first)
|
924
|
-
topic.reload
|
925
|
-
assert_equal topic.replies.to_a.size, topic.replies_count
|
926
|
-
end
|
927
|
-
|
928
|
-
def test_counter_cache_updates_in_memory_after_concat
|
929
|
-
topic = Topic.create title: "Zoom-zoom-zoom"
|
930
|
-
|
931
|
-
topic.replies << Reply.create(title: "re: zoom", content: "speedy quick!")
|
932
|
-
assert_equal 1, topic.replies_count
|
933
|
-
assert_equal 1, topic.replies.size
|
934
|
-
assert_equal 1, topic.reload.replies.size
|
935
|
-
end
|
936
|
-
|
937
|
-
def test_counter_cache_updates_in_memory_after_create
|
938
|
-
topic = Topic.create title: "Zoom-zoom-zoom"
|
939
|
-
|
940
|
-
topic.replies.create!(title: "re: zoom", content: "speedy quick!")
|
941
|
-
assert_equal 1, topic.replies_count
|
942
|
-
assert_equal 1, topic.replies.size
|
943
|
-
assert_equal 1, topic.reload.replies.size
|
944
|
-
end
|
945
|
-
|
946
|
-
def test_counter_cache_updates_in_memory_after_create_with_array
|
947
|
-
topic = Topic.create title: "Zoom-zoom-zoom"
|
948
|
-
|
949
|
-
topic.replies.create!([
|
950
|
-
{ title: "re: zoom", content: "speedy quick!" },
|
951
|
-
{ title: "re: zoom 2", content: "OMG lol!" },
|
952
|
-
])
|
953
|
-
assert_equal 2, topic.replies_count
|
954
|
-
assert_equal 2, topic.replies.size
|
955
|
-
assert_equal 2, topic.reload.replies.size
|
956
|
-
end
|
957
|
-
|
958
|
-
def test_pushing_association_updates_counter_cache
|
959
|
-
topic = Topic.order("id ASC").first
|
960
|
-
reply = Reply.create!
|
961
|
-
|
962
|
-
assert_difference "topic.reload.replies_count", 1 do
|
963
|
-
topic.replies << reply
|
964
|
-
end
|
965
|
-
end
|
966
|
-
|
967
|
-
def test_deleting_updates_counter_cache_without_dependent_option
|
968
|
-
post = posts(:welcome)
|
969
|
-
|
970
|
-
assert_difference "post.reload.tags_count", -1 do
|
971
|
-
post.taggings.delete(post.taggings.first)
|
972
|
-
end
|
973
|
-
end
|
974
|
-
|
975
|
-
def test_deleting_updates_counter_cache_with_dependent_delete_all
|
976
|
-
post = posts(:welcome)
|
977
|
-
post.update_columns(taggings_with_delete_all_count: post.tags_count)
|
978
|
-
|
979
|
-
assert_difference "post.reload.taggings_with_delete_all_count", -1 do
|
980
|
-
post.taggings_with_delete_all.delete(post.taggings_with_delete_all.first)
|
981
|
-
end
|
982
|
-
end
|
983
|
-
|
984
|
-
def test_deleting_updates_counter_cache_with_dependent_destroy
|
985
|
-
post = posts(:welcome)
|
986
|
-
post.update_columns(taggings_with_destroy_count: post.tags_count)
|
987
|
-
|
988
|
-
assert_difference "post.reload.taggings_with_destroy_count", -1 do
|
989
|
-
post.taggings_with_destroy.delete(post.taggings_with_destroy.first)
|
990
|
-
end
|
991
|
-
end
|
992
|
-
|
993
|
-
def test_calling_empty_with_counter_cache
|
994
|
-
post = posts(:welcome)
|
995
|
-
assert_queries(0) do
|
996
|
-
assert_not post.comments.empty?
|
997
|
-
end
|
998
|
-
end
|
999
|
-
|
1000
|
-
def test_custom_named_counter_cache
|
1001
|
-
topic = topics(:first)
|
1002
|
-
|
1003
|
-
assert_difference "topic.reload.replies_count", -1 do
|
1004
|
-
topic.approved_replies.clear
|
1005
|
-
end
|
1006
|
-
end
|
1007
|
-
|
1008
|
-
def test_calling_update_attributes_on_id_changes_the_counter_cache
|
1009
|
-
topic = Topic.order("id ASC").first
|
1010
|
-
original_count = topic.replies.to_a.size
|
1011
|
-
assert_equal original_count, topic.replies_count
|
1012
|
-
|
1013
|
-
first_reply = topic.replies.first
|
1014
|
-
first_reply.update_attributes(:parent_id => nil)
|
1015
|
-
assert_equal original_count - 1, topic.reload.replies_count
|
1016
|
-
|
1017
|
-
first_reply.update_attributes(:parent_id => topic.id)
|
1018
|
-
assert_equal original_count, topic.reload.replies_count
|
1019
|
-
end
|
1020
|
-
|
1021
|
-
def test_calling_update_attributes_changing_ids_doesnt_change_counter_cache
|
1022
|
-
topic1 = Topic.find(1)
|
1023
|
-
topic2 = Topic.find(3)
|
1024
|
-
original_count1 = topic1.replies.to_a.size
|
1025
|
-
original_count2 = topic2.replies.to_a.size
|
1026
|
-
|
1027
|
-
reply1 = topic1.replies.first
|
1028
|
-
reply2 = topic2.replies.first
|
1029
|
-
|
1030
|
-
reply1.update_attributes(:parent_id => topic2.id)
|
1031
|
-
assert_equal original_count1 - 1, topic1.reload.replies_count
|
1032
|
-
assert_equal original_count2 + 1, topic2.reload.replies_count
|
1033
|
-
|
1034
|
-
reply2.update_attributes(:parent_id => topic1.id)
|
1035
|
-
assert_equal original_count1, topic1.reload.replies_count
|
1036
|
-
assert_equal original_count2, topic2.reload.replies_count
|
1037
|
-
end
|
1038
|
-
|
1039
|
-
def test_deleting_a_collection
|
1040
|
-
force_signal37_to_load_all_clients_of_firm
|
1041
|
-
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
1042
|
-
assert_equal 3, companies(:first_firm).clients_of_firm.size
|
1043
|
-
companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1], companies(:first_firm).clients_of_firm[2]])
|
1044
|
-
assert_equal 0, companies(:first_firm).clients_of_firm.size
|
1045
|
-
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
|
1046
|
-
end
|
1047
|
-
|
1048
|
-
def test_delete_all
|
1049
|
-
force_signal37_to_load_all_clients_of_firm
|
1050
|
-
companies(:first_firm).dependent_clients_of_firm.create("name" => "Another Client")
|
1051
|
-
clients = companies(:first_firm).dependent_clients_of_firm.to_a
|
1052
|
-
assert_equal 3, clients.count
|
1053
|
-
|
1054
|
-
assert_difference "Client.count", -(clients.count) do
|
1055
|
-
companies(:first_firm).dependent_clients_of_firm.delete_all
|
1056
|
-
end
|
1057
|
-
end
|
1058
|
-
|
1059
|
-
def test_delete_all_with_not_yet_loaded_association_collection
|
1060
|
-
force_signal37_to_load_all_clients_of_firm
|
1061
|
-
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
1062
|
-
assert_equal 3, companies(:first_firm).clients_of_firm.size
|
1063
|
-
companies(:first_firm).clients_of_firm.reset
|
1064
|
-
companies(:first_firm).clients_of_firm.delete_all
|
1065
|
-
assert_equal 0, companies(:first_firm).clients_of_firm.size
|
1066
|
-
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
|
1067
|
-
end
|
1068
|
-
|
1069
|
-
def test_transaction_when_deleting_persisted
|
1070
|
-
good = Client.new(:name => "Good")
|
1071
|
-
bad = Client.new(:name => "Bad", :raise_on_destroy => true)
|
1072
|
-
|
1073
|
-
companies(:first_firm).clients_of_firm = [good, bad]
|
1074
|
-
|
1075
|
-
begin
|
1076
|
-
companies(:first_firm).clients_of_firm.destroy(good, bad)
|
1077
|
-
rescue Client::RaisedOnDestroy
|
1078
|
-
end
|
1079
|
-
|
1080
|
-
assert_equal [good, bad], companies(:first_firm).clients_of_firm(true)
|
1081
|
-
end
|
1082
|
-
|
1083
|
-
def test_transaction_when_deleting_new_record
|
1084
|
-
assert_no_queries(ignore_none: false) do
|
1085
|
-
firm = Firm.new
|
1086
|
-
client = Client.new("name" => "New Client")
|
1087
|
-
firm.clients_of_firm << client
|
1088
|
-
firm.clients_of_firm.destroy(client)
|
1089
|
-
end
|
1090
|
-
end
|
1091
|
-
|
1092
|
-
def test_clearing_an_association_collection
|
1093
|
-
firm = companies(:first_firm)
|
1094
|
-
client_id = firm.clients_of_firm.first.id
|
1095
|
-
assert_equal 2, firm.clients_of_firm.size
|
1096
|
-
|
1097
|
-
firm.clients_of_firm.clear
|
1098
|
-
|
1099
|
-
assert_equal 0, firm.clients_of_firm.size
|
1100
|
-
assert_equal 0, firm.clients_of_firm(true).size
|
1101
|
-
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1102
|
-
|
1103
|
-
# Should not be destroyed since the association is not dependent.
|
1104
|
-
assert_nothing_raised do
|
1105
|
-
assert_nil Client.find(client_id).firm
|
1106
|
-
end
|
1107
|
-
end
|
1108
|
-
|
1109
|
-
def test_clearing_updates_counter_cache
|
1110
|
-
topic = Topic.first
|
1111
|
-
|
1112
|
-
assert_difference 'topic.reload.replies_count', -1 do
|
1113
|
-
topic.replies.clear
|
1114
|
-
end
|
1115
|
-
end
|
1116
|
-
|
1117
|
-
def test_clearing_updates_counter_cache_when_inverse_counter_cache_is_a_symbol_with_dependent_destroy
|
1118
|
-
car = Car.first
|
1119
|
-
car.engines.create!
|
1120
|
-
|
1121
|
-
assert_difference 'car.reload.engines_count', -1 do
|
1122
|
-
car.engines.clear
|
1123
|
-
end
|
1124
|
-
end
|
1125
|
-
|
1126
|
-
def test_clearing_a_dependent_association_collection
|
1127
|
-
firm = companies(:first_firm)
|
1128
|
-
client_id = firm.dependent_clients_of_firm.first.id
|
1129
|
-
assert_equal 2, firm.dependent_clients_of_firm.size
|
1130
|
-
assert_equal 1, Client.find_by_id(client_id).client_of
|
1131
|
-
|
1132
|
-
# :delete_all is called on each client since the dependent options is :destroy
|
1133
|
-
firm.dependent_clients_of_firm.clear
|
1134
|
-
|
1135
|
-
assert_equal 0, firm.dependent_clients_of_firm.size
|
1136
|
-
assert_equal 0, firm.dependent_clients_of_firm(true).size
|
1137
|
-
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1138
|
-
|
1139
|
-
# Should be destroyed since the association is dependent.
|
1140
|
-
assert_nil Client.find_by_id(client_id)
|
1141
|
-
end
|
1142
|
-
|
1143
|
-
def test_delete_all_with_option_delete_all
|
1144
|
-
firm = companies(:first_firm)
|
1145
|
-
client_id = firm.dependent_clients_of_firm.first.id
|
1146
|
-
firm.dependent_clients_of_firm.delete_all(:delete_all)
|
1147
|
-
assert_nil Client.find_by_id(client_id)
|
1148
|
-
end
|
1149
|
-
|
1150
|
-
def test_delete_all_accepts_limited_parameters
|
1151
|
-
firm = companies(:first_firm)
|
1152
|
-
assert_raise(ArgumentError) do
|
1153
|
-
firm.dependent_clients_of_firm.delete_all(:destroy)
|
1154
|
-
end
|
1155
|
-
end
|
1156
|
-
|
1157
|
-
def test_clearing_an_exclusively_dependent_association_collection
|
1158
|
-
firm = companies(:first_firm)
|
1159
|
-
client_id = firm.exclusively_dependent_clients_of_firm.first.id
|
1160
|
-
assert_equal 2, firm.exclusively_dependent_clients_of_firm.size
|
1161
|
-
|
1162
|
-
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1163
|
-
|
1164
|
-
# :exclusively_dependent means each client is deleted directly from
|
1165
|
-
# the database without looping through them calling destroy.
|
1166
|
-
firm.exclusively_dependent_clients_of_firm.clear
|
1167
|
-
|
1168
|
-
assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
|
1169
|
-
assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
|
1170
|
-
# no destroy-filters should have been called
|
1171
|
-
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1172
|
-
|
1173
|
-
# Should be destroyed since the association is exclusively dependent.
|
1174
|
-
assert_nil Client.find_by_id(client_id)
|
1175
|
-
end
|
1176
|
-
|
1177
|
-
def test_dependent_association_respects_optional_conditions_on_delete
|
1178
|
-
firm = companies(:odegy)
|
1179
|
-
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
1180
|
-
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
1181
|
-
# only one of two clients is included in the association due to the :conditions key
|
1182
|
-
assert_equal 2, Client.where(client_of: firm.id).size
|
1183
|
-
assert_equal 1, firm.dependent_conditional_clients_of_firm.size
|
1184
|
-
firm.destroy
|
1185
|
-
# only the correctly associated client should have been deleted
|
1186
|
-
assert_equal 1, Client.where(client_of: firm.id).size
|
1187
|
-
end
|
1188
|
-
|
1189
|
-
def test_dependent_association_respects_optional_sanitized_conditions_on_delete
|
1190
|
-
firm = companies(:odegy)
|
1191
|
-
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
1192
|
-
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
1193
|
-
# only one of two clients is included in the association due to the :conditions key
|
1194
|
-
assert_equal 2, Client.where(client_of: firm.id).size
|
1195
|
-
assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
|
1196
|
-
firm.destroy
|
1197
|
-
# only the correctly associated client should have been deleted
|
1198
|
-
assert_equal 1, Client.where(client_of: firm.id).size
|
1199
|
-
end
|
1200
|
-
|
1201
|
-
def test_dependent_association_respects_optional_hash_conditions_on_delete
|
1202
|
-
firm = companies(:odegy)
|
1203
|
-
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
1204
|
-
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
1205
|
-
# only one of two clients is included in the association due to the :conditions key
|
1206
|
-
assert_equal 2, Client.where(client_of: firm.id).size
|
1207
|
-
assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
|
1208
|
-
firm.destroy
|
1209
|
-
# only the correctly associated client should have been deleted
|
1210
|
-
assert_equal 1, Client.where(client_of: firm.id).size
|
1211
|
-
end
|
1212
|
-
|
1213
|
-
def test_delete_all_association_with_primary_key_deletes_correct_records
|
1214
|
-
firm = Firm.first
|
1215
|
-
# break the vanilla firm_id foreign key
|
1216
|
-
assert_equal 3, firm.clients.count
|
1217
|
-
firm.clients.first.update_columns(firm_id: nil)
|
1218
|
-
assert_equal 2, firm.clients(true).count
|
1219
|
-
assert_equal 2, firm.clients_using_primary_key_with_delete_all.count
|
1220
|
-
old_record = firm.clients_using_primary_key_with_delete_all.first
|
1221
|
-
firm = Firm.first
|
1222
|
-
firm.destroy
|
1223
|
-
assert_nil Client.find_by_id(old_record.id)
|
1224
|
-
end
|
1225
|
-
|
1226
|
-
def test_creation_respects_hash_condition
|
1227
|
-
ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
|
1228
|
-
|
1229
|
-
assert ms_client.save
|
1230
|
-
assert_equal 'Microsoft', ms_client.name
|
1231
|
-
|
1232
|
-
another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
|
1233
|
-
|
1234
|
-
assert another_ms_client.persisted?
|
1235
|
-
assert_equal 'Microsoft', another_ms_client.name
|
1236
|
-
end
|
1237
|
-
|
1238
|
-
def test_clearing_without_initial_access
|
1239
|
-
firm = companies(:first_firm)
|
1240
|
-
|
1241
|
-
firm.clients_of_firm.clear
|
1242
|
-
|
1243
|
-
assert_equal 0, firm.clients_of_firm.size
|
1244
|
-
assert_equal 0, firm.clients_of_firm(true).size
|
1245
|
-
end
|
1246
|
-
|
1247
|
-
def test_deleting_a_item_which_is_not_in_the_collection
|
1248
|
-
force_signal37_to_load_all_clients_of_firm
|
1249
|
-
summit = Client.find_by_name('Summit')
|
1250
|
-
companies(:first_firm).clients_of_firm.delete(summit)
|
1251
|
-
assert_equal 2, companies(:first_firm).clients_of_firm.size
|
1252
|
-
assert_equal 2, companies(:first_firm).clients_of_firm(true).size
|
1253
|
-
assert_equal 2, summit.client_of
|
1254
|
-
end
|
1255
|
-
|
1256
|
-
def test_deleting_by_fixnum_id
|
1257
|
-
david = Developer.find(1)
|
1258
|
-
|
1259
|
-
assert_difference 'david.projects.count', -1 do
|
1260
|
-
assert_equal 1, david.projects.delete(1).size
|
1261
|
-
end
|
1262
|
-
|
1263
|
-
assert_equal 1, david.projects.size
|
1264
|
-
end
|
1265
|
-
|
1266
|
-
def test_deleting_by_string_id
|
1267
|
-
david = Developer.find(1)
|
1268
|
-
|
1269
|
-
assert_difference 'david.projects.count', -1 do
|
1270
|
-
assert_equal 1, david.projects.delete('1').size
|
1271
|
-
end
|
1272
|
-
|
1273
|
-
assert_equal 1, david.projects.size
|
1274
|
-
end
|
1275
|
-
|
1276
|
-
def test_deleting_self_type_mismatch
|
1277
|
-
david = Developer.find(1)
|
1278
|
-
david.projects.reload
|
1279
|
-
assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
|
1280
|
-
end
|
1281
|
-
|
1282
|
-
def test_destroying
|
1283
|
-
force_signal37_to_load_all_clients_of_firm
|
1284
|
-
|
1285
|
-
assert_difference "Client.count", -1 do
|
1286
|
-
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
|
1287
|
-
end
|
1288
|
-
|
1289
|
-
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1290
|
-
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1291
|
-
end
|
1292
|
-
|
1293
|
-
def test_destroying_by_fixnum_id
|
1294
|
-
force_signal37_to_load_all_clients_of_firm
|
1295
|
-
|
1296
|
-
assert_difference "Client.count", -1 do
|
1297
|
-
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id)
|
1298
|
-
end
|
1299
|
-
|
1300
|
-
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1301
|
-
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1302
|
-
end
|
1303
|
-
|
1304
|
-
def test_destroying_by_string_id
|
1305
|
-
force_signal37_to_load_all_clients_of_firm
|
1306
|
-
|
1307
|
-
assert_difference "Client.count", -1 do
|
1308
|
-
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id.to_s)
|
1309
|
-
end
|
1310
|
-
|
1311
|
-
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1312
|
-
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1313
|
-
end
|
1314
|
-
|
1315
|
-
def test_destroying_a_collection
|
1316
|
-
force_signal37_to_load_all_clients_of_firm
|
1317
|
-
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
1318
|
-
assert_equal 3, companies(:first_firm).clients_of_firm.size
|
1319
|
-
|
1320
|
-
assert_difference "Client.count", -2 do
|
1321
|
-
companies(:first_firm).clients_of_firm.destroy([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
|
1322
|
-
end
|
1323
|
-
|
1324
|
-
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1325
|
-
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1326
|
-
end
|
1327
|
-
|
1328
|
-
def test_destroy_all
|
1329
|
-
force_signal37_to_load_all_clients_of_firm
|
1330
|
-
clients = companies(:first_firm).clients_of_firm.to_a
|
1331
|
-
assert !clients.empty?, "37signals has clients after load"
|
1332
|
-
destroyed = companies(:first_firm).clients_of_firm.destroy_all
|
1333
|
-
assert_equal clients.sort_by(&:id), destroyed.sort_by(&:id)
|
1334
|
-
assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
|
1335
|
-
assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
|
1336
|
-
assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
|
1337
|
-
end
|
1338
|
-
|
1339
|
-
def test_dependence
|
1340
|
-
firm = companies(:first_firm)
|
1341
|
-
assert_equal 3, firm.clients.size
|
1342
|
-
firm.destroy
|
1343
|
-
assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
|
1344
|
-
end
|
1345
|
-
|
1346
|
-
def test_dependence_for_associations_with_hash_condition
|
1347
|
-
david = authors(:david)
|
1348
|
-
assert_difference('Post.count', -1) { assert david.destroy }
|
1349
|
-
end
|
1350
|
-
|
1351
|
-
def test_destroy_dependent_when_deleted_from_association
|
1352
|
-
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
|
1353
|
-
firm = Firm.all.merge!(:order => "id").first
|
1354
|
-
assert_equal 3, firm.clients.size
|
1355
|
-
|
1356
|
-
client = firm.clients.first
|
1357
|
-
firm.clients.delete(client)
|
1358
|
-
|
1359
|
-
assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
|
1360
|
-
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
|
1361
|
-
assert_equal 2, firm.clients.size
|
1362
|
-
end
|
1363
|
-
|
1364
|
-
def test_three_levels_of_dependence
|
1365
|
-
topic = Topic.create "title" => "neat and simple"
|
1366
|
-
reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
|
1367
|
-
reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
|
1368
|
-
|
1369
|
-
assert_nothing_raised { topic.destroy }
|
1370
|
-
end
|
1371
|
-
|
1372
|
-
uses_transaction :test_dependence_with_transaction_support_on_failure
|
1373
|
-
def test_dependence_with_transaction_support_on_failure
|
1374
|
-
firm = companies(:first_firm)
|
1375
|
-
clients = firm.clients
|
1376
|
-
assert_equal 3, clients.length
|
1377
|
-
clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end }
|
1378
|
-
|
1379
|
-
firm.destroy rescue "do nothing"
|
1380
|
-
|
1381
|
-
assert_equal 3, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
|
1382
|
-
end
|
1383
|
-
|
1384
|
-
def test_dependence_on_account
|
1385
|
-
num_accounts = Account.count
|
1386
|
-
companies(:first_firm).destroy
|
1387
|
-
assert_equal num_accounts - 1, Account.count
|
1388
|
-
end
|
1389
|
-
|
1390
|
-
def test_depends_and_nullify
|
1391
|
-
num_accounts = Account.count
|
1392
|
-
|
1393
|
-
core = companies(:rails_core)
|
1394
|
-
assert_equal accounts(:rails_core_account), core.account
|
1395
|
-
assert_equal companies(:leetsoft, :jadedpixel), core.companies
|
1396
|
-
core.destroy
|
1397
|
-
assert_nil accounts(:rails_core_account).reload.firm_id
|
1398
|
-
assert_nil companies(:leetsoft).reload.client_of
|
1399
|
-
assert_nil companies(:jadedpixel).reload.client_of
|
1400
|
-
|
1401
|
-
assert_equal num_accounts, Account.count
|
1402
|
-
end
|
1403
|
-
|
1404
|
-
def test_restrict_with_exception
|
1405
|
-
firm = RestrictedWithExceptionFirm.create!(:name => 'restrict')
|
1406
|
-
firm.companies.create(:name => 'child')
|
1407
|
-
|
1408
|
-
assert !firm.companies.empty?
|
1409
|
-
assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
|
1410
|
-
assert RestrictedWithExceptionFirm.exists?(:name => 'restrict')
|
1411
|
-
assert firm.companies.exists?(:name => 'child')
|
1412
|
-
end
|
1413
|
-
|
1414
|
-
def test_restrict_with_error
|
1415
|
-
firm = RestrictedWithErrorFirm.create!(:name => 'restrict')
|
1416
|
-
firm.companies.create(:name => 'child')
|
1417
|
-
|
1418
|
-
assert !firm.companies.empty?
|
1419
|
-
|
1420
|
-
firm.destroy
|
1421
|
-
|
1422
|
-
assert !firm.errors.empty?
|
1423
|
-
|
1424
|
-
assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first
|
1425
|
-
assert RestrictedWithErrorFirm.exists?(:name => 'restrict')
|
1426
|
-
assert firm.companies.exists?(:name => 'child')
|
1427
|
-
end
|
1428
|
-
|
1429
|
-
def test_included_in_collection
|
1430
|
-
assert_equal true, companies(:first_firm).clients.include?(Client.find(2))
|
1431
|
-
end
|
1432
|
-
|
1433
|
-
def test_included_in_collection_for_new_records
|
1434
|
-
client = Client.create(:name => 'Persisted')
|
1435
|
-
assert_nil client.client_of
|
1436
|
-
assert_equal false, Firm.new.clients_of_firm.include?(client),
|
1437
|
-
'includes a client that does not belong to any firm'
|
1438
|
-
end
|
1439
|
-
|
1440
|
-
def test_adding_array_and_collection
|
1441
|
-
assert_nothing_raised { Firm.first.clients + Firm.all.last.clients }
|
1442
|
-
end
|
1443
|
-
|
1444
|
-
def test_replace_with_less
|
1445
|
-
firm = Firm.all.merge!(:order => "id").first
|
1446
|
-
firm.clients = [companies(:first_client)]
|
1447
|
-
assert firm.save, "Could not save firm"
|
1448
|
-
firm.reload
|
1449
|
-
assert_equal 1, firm.clients.length
|
1450
|
-
end
|
1451
|
-
|
1452
|
-
def test_replace_with_less_and_dependent_nullify
|
1453
|
-
num_companies = Company.count
|
1454
|
-
companies(:rails_core).companies = []
|
1455
|
-
assert_equal num_companies, Company.count
|
1456
|
-
end
|
1457
|
-
|
1458
|
-
def test_replace_with_new
|
1459
|
-
firm = Firm.all.merge!(:order => "id").first
|
1460
|
-
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
|
1461
|
-
firm.save
|
1462
|
-
firm.reload
|
1463
|
-
assert_equal 2, firm.clients.length
|
1464
|
-
assert_equal false, firm.clients.include?(:first_client)
|
1465
|
-
end
|
1466
|
-
|
1467
|
-
def test_replace_failure
|
1468
|
-
firm = companies(:first_firm)
|
1469
|
-
account = Account.new
|
1470
|
-
orig_accounts = firm.accounts.to_a
|
1471
|
-
|
1472
|
-
assert !account.valid?
|
1473
|
-
assert !orig_accounts.empty?
|
1474
|
-
error = assert_raise ActiveRecord::RecordNotSaved do
|
1475
|
-
firm.accounts = [account]
|
1476
|
-
end
|
1477
|
-
|
1478
|
-
assert_equal orig_accounts, firm.accounts
|
1479
|
-
assert_equal "Failed to replace accounts because one or more of the " \
|
1480
|
-
"new records could not be saved.", error.message
|
1481
|
-
end
|
1482
|
-
|
1483
|
-
def test_replace_with_same_content
|
1484
|
-
firm = Firm.first
|
1485
|
-
firm.clients = []
|
1486
|
-
firm.save
|
1487
|
-
|
1488
|
-
assert_queries(0, ignore_none: true) do
|
1489
|
-
firm.clients = []
|
1490
|
-
end
|
1491
|
-
end
|
1492
|
-
|
1493
|
-
def test_transactions_when_replacing_on_persisted
|
1494
|
-
good = Client.new(:name => "Good")
|
1495
|
-
bad = Client.new(:name => "Bad", :raise_on_save => true)
|
1496
|
-
|
1497
|
-
companies(:first_firm).clients_of_firm = [good]
|
1498
|
-
|
1499
|
-
begin
|
1500
|
-
companies(:first_firm).clients_of_firm = [bad]
|
1501
|
-
rescue Client::RaisedOnSave
|
1502
|
-
end
|
1503
|
-
|
1504
|
-
assert_equal [good], companies(:first_firm).clients_of_firm(true)
|
1505
|
-
end
|
1506
|
-
|
1507
|
-
def test_transactions_when_replacing_on_new_record
|
1508
|
-
assert_no_queries(ignore_none: false) do
|
1509
|
-
firm = Firm.new
|
1510
|
-
firm.clients_of_firm = [Client.new("name" => "New Client")]
|
1511
|
-
end
|
1512
|
-
end
|
1513
|
-
|
1514
|
-
def test_get_ids
|
1515
|
-
assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], companies(:first_firm).client_ids
|
1516
|
-
end
|
1517
|
-
|
1518
|
-
def test_get_ids_for_loaded_associations
|
1519
|
-
company = companies(:first_firm)
|
1520
|
-
company.clients(true)
|
1521
|
-
assert_queries(0) do
|
1522
|
-
company.client_ids
|
1523
|
-
company.client_ids
|
1524
|
-
end
|
1525
|
-
end
|
1526
|
-
|
1527
|
-
def test_get_ids_for_unloaded_associations_does_not_load_them
|
1528
|
-
company = companies(:first_firm)
|
1529
|
-
assert !company.clients.loaded?
|
1530
|
-
assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], company.client_ids
|
1531
|
-
assert !company.clients.loaded?
|
1532
|
-
end
|
1533
|
-
|
1534
|
-
def test_get_ids_ignores_include_option
|
1535
|
-
assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids
|
1536
|
-
end
|
1537
|
-
|
1538
|
-
def test_get_ids_for_ordered_association
|
1539
|
-
assert_equal [companies(:another_first_firm_client).id, companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
|
1540
|
-
end
|
1541
|
-
|
1542
|
-
def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
|
1543
|
-
Company.columns # Load schema information so we don't query below
|
1544
|
-
Contract.columns # if running just this test.
|
1545
|
-
|
1546
|
-
company = Company.new
|
1547
|
-
assert_queries(0) do
|
1548
|
-
company.contract_ids
|
1549
|
-
end
|
1550
|
-
|
1551
|
-
assert_equal [], company.contract_ids
|
1552
|
-
end
|
1553
|
-
|
1554
|
-
def test_set_ids_for_association_on_new_record_applies_association_correctly
|
1555
|
-
contract_a = Contract.create!
|
1556
|
-
contract_b = Contract.create!
|
1557
|
-
Contract.create! # another contract
|
1558
|
-
company = Company.new(:name => "Some Company")
|
1559
|
-
|
1560
|
-
company.contract_ids = [contract_a.id, contract_b.id]
|
1561
|
-
assert_equal [contract_a.id, contract_b.id], company.contract_ids
|
1562
|
-
assert_equal [contract_a, contract_b], company.contracts
|
1563
|
-
|
1564
|
-
company.save!
|
1565
|
-
assert_equal company, contract_a.reload.company
|
1566
|
-
assert_equal company, contract_b.reload.company
|
1567
|
-
end
|
1568
|
-
|
1569
|
-
def test_assign_ids_ignoring_blanks
|
1570
|
-
firm = Firm.create!(:name => 'Apple')
|
1571
|
-
firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
|
1572
|
-
firm.save!
|
1573
|
-
|
1574
|
-
assert_equal 2, firm.clients(true).size
|
1575
|
-
assert_equal true, firm.clients.include?(companies(:second_client))
|
1576
|
-
end
|
1577
|
-
|
1578
|
-
def test_get_ids_for_through
|
1579
|
-
assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
|
1580
|
-
end
|
1581
|
-
|
1582
|
-
def test_modifying_a_through_a_has_many_should_raise
|
1583
|
-
[
|
1584
|
-
lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
|
1585
|
-
lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
|
1586
|
-
lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
|
1587
|
-
lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
|
1588
|
-
].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
|
1589
|
-
end
|
1590
|
-
|
1591
|
-
def test_dynamic_find_should_respect_association_order_for_through
|
1592
|
-
assert_equal Comment.find(10), authors(:david).comments_desc.where("comments.type = 'SpecialComment'").first
|
1593
|
-
assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
|
1594
|
-
end
|
1595
|
-
|
1596
|
-
def test_has_many_through_respects_hash_conditions
|
1597
|
-
assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
|
1598
|
-
assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
|
1599
|
-
end
|
1600
|
-
|
1601
|
-
def test_include_uses_array_include_after_loaded
|
1602
|
-
firm = companies(:first_firm)
|
1603
|
-
firm.clients.load_target
|
1604
|
-
|
1605
|
-
client = firm.clients.first
|
1606
|
-
|
1607
|
-
assert_no_queries do
|
1608
|
-
assert firm.clients.loaded?
|
1609
|
-
assert_equal true, firm.clients.include?(client)
|
1610
|
-
end
|
1611
|
-
end
|
1612
|
-
|
1613
|
-
def test_include_checks_if_record_exists_if_target_not_loaded
|
1614
|
-
firm = companies(:first_firm)
|
1615
|
-
client = firm.clients.first
|
1616
|
-
|
1617
|
-
firm.reload
|
1618
|
-
assert ! firm.clients.loaded?
|
1619
|
-
assert_queries(1) do
|
1620
|
-
assert_equal true, firm.clients.include?(client)
|
1621
|
-
end
|
1622
|
-
assert ! firm.clients.loaded?
|
1623
|
-
end
|
1624
|
-
|
1625
|
-
def test_include_returns_false_for_non_matching_record_to_verify_scoping
|
1626
|
-
firm = companies(:first_firm)
|
1627
|
-
client = Client.create!(:name => 'Not Associated')
|
1628
|
-
|
1629
|
-
assert ! firm.clients.loaded?
|
1630
|
-
assert_equal false, firm.clients.include?(client)
|
1631
|
-
end
|
1632
|
-
|
1633
|
-
def test_calling_first_nth_or_last_on_association_should_not_load_association
|
1634
|
-
firm = companies(:first_firm)
|
1635
|
-
firm.clients.first
|
1636
|
-
firm.clients.second
|
1637
|
-
firm.clients.last
|
1638
|
-
assert !firm.clients.loaded?
|
1639
|
-
end
|
1640
|
-
|
1641
|
-
def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
|
1642
|
-
firm = companies(:first_firm)
|
1643
|
-
firm.clients.load_target
|
1644
|
-
assert firm.clients.loaded?
|
1645
|
-
|
1646
|
-
assert_no_queries(ignore_none: false) do
|
1647
|
-
firm.clients.first
|
1648
|
-
assert_equal 2, firm.clients.first(2).size
|
1649
|
-
firm.clients.last
|
1650
|
-
assert_equal 2, firm.clients.last(2).size
|
1651
|
-
end
|
1652
|
-
end
|
1653
|
-
|
1654
|
-
def test_calling_first_or_last_on_existing_record_with_build_should_load_association
|
1655
|
-
firm = companies(:first_firm)
|
1656
|
-
firm.clients.build(:name => 'Foo')
|
1657
|
-
assert !firm.clients.loaded?
|
1658
|
-
|
1659
|
-
assert_queries 1 do
|
1660
|
-
firm.clients.first
|
1661
|
-
firm.clients.second
|
1662
|
-
firm.clients.last
|
1663
|
-
end
|
1664
|
-
|
1665
|
-
assert firm.clients.loaded?
|
1666
|
-
end
|
1667
|
-
|
1668
|
-
def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_load_association
|
1669
|
-
firm = companies(:first_firm)
|
1670
|
-
firm.clients.create(:name => 'Foo')
|
1671
|
-
assert !firm.clients.loaded?
|
1672
|
-
|
1673
|
-
assert_queries 3 do
|
1674
|
-
firm.clients.first
|
1675
|
-
firm.clients.second
|
1676
|
-
firm.clients.last
|
1677
|
-
end
|
1678
|
-
|
1679
|
-
assert !firm.clients.loaded?
|
1680
|
-
end
|
1681
|
-
|
1682
|
-
def test_calling_first_nth_or_last_on_new_record_should_not_run_queries
|
1683
|
-
firm = Firm.new
|
1684
|
-
|
1685
|
-
assert_no_queries do
|
1686
|
-
firm.clients.first
|
1687
|
-
firm.clients.second
|
1688
|
-
firm.clients.last
|
1689
|
-
end
|
1690
|
-
end
|
1691
|
-
|
1692
|
-
def test_calling_first_or_last_with_integer_on_association_should_not_load_association
|
1693
|
-
firm = companies(:first_firm)
|
1694
|
-
firm.clients.create(:name => 'Foo')
|
1695
|
-
assert !firm.clients.loaded?
|
1696
|
-
|
1697
|
-
assert_queries 2 do
|
1698
|
-
firm.clients.first(2)
|
1699
|
-
firm.clients.last(2)
|
1700
|
-
end
|
1701
|
-
|
1702
|
-
assert !firm.clients.loaded?
|
1703
|
-
end
|
1704
|
-
|
1705
|
-
def test_calling_many_should_count_instead_of_loading_association
|
1706
|
-
firm = companies(:first_firm)
|
1707
|
-
assert_queries(1) do
|
1708
|
-
firm.clients.many? # use count query
|
1709
|
-
end
|
1710
|
-
assert !firm.clients.loaded?
|
1711
|
-
end
|
1712
|
-
|
1713
|
-
def test_calling_many_on_loaded_association_should_not_use_query
|
1714
|
-
firm = companies(:first_firm)
|
1715
|
-
firm.clients.collect # force load
|
1716
|
-
assert_no_queries { assert firm.clients.many? }
|
1717
|
-
end
|
1718
|
-
|
1719
|
-
def test_calling_many_should_defer_to_collection_if_using_a_block
|
1720
|
-
firm = companies(:first_firm)
|
1721
|
-
assert_queries(1) do
|
1722
|
-
firm.clients.expects(:size).never
|
1723
|
-
firm.clients.many? { true }
|
1724
|
-
end
|
1725
|
-
assert firm.clients.loaded?
|
1726
|
-
end
|
1727
|
-
|
1728
|
-
def test_calling_many_should_return_false_if_none_or_one
|
1729
|
-
firm = companies(:another_firm)
|
1730
|
-
assert !firm.clients_like_ms.many?
|
1731
|
-
assert_equal 0, firm.clients_like_ms.size
|
1732
|
-
|
1733
|
-
firm = companies(:first_firm)
|
1734
|
-
assert !firm.limited_clients.many?
|
1735
|
-
assert_equal 1, firm.limited_clients.size
|
1736
|
-
end
|
1737
|
-
|
1738
|
-
def test_calling_many_should_return_true_if_more_than_one
|
1739
|
-
firm = companies(:first_firm)
|
1740
|
-
assert firm.clients.many?
|
1741
|
-
assert_equal 3, firm.clients.size
|
1742
|
-
end
|
1743
|
-
|
1744
|
-
def test_joins_with_namespaced_model_should_use_correct_type
|
1745
|
-
old = ActiveRecord::Base.store_full_sti_class
|
1746
|
-
ActiveRecord::Base.store_full_sti_class = true
|
1747
|
-
|
1748
|
-
firm = Namespaced::Firm.create({ :name => 'Some Company' })
|
1749
|
-
firm.clients.create({ :name => 'Some Client' })
|
1750
|
-
|
1751
|
-
stats = Namespaced::Firm.all.merge!(
|
1752
|
-
:select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
|
1753
|
-
:joins => :clients,
|
1754
|
-
:group => "#{Namespaced::Firm.table_name}.id"
|
1755
|
-
).find firm.id
|
1756
|
-
assert_equal 1, stats.num_clients.to_i
|
1757
|
-
ensure
|
1758
|
-
ActiveRecord::Base.store_full_sti_class = old
|
1759
|
-
end
|
1760
|
-
|
1761
|
-
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
1762
|
-
Comment.expects(:transaction)
|
1763
|
-
Post.first.comments.transaction do
|
1764
|
-
# nothing
|
1765
|
-
end
|
1766
|
-
end
|
1767
|
-
|
1768
|
-
def test_sending_new_to_association_proxy_should_have_same_effect_as_calling_new
|
1769
|
-
client_association = companies(:first_firm).clients
|
1770
|
-
assert_equal client_association.new.attributes, client_association.send(:new).attributes
|
1771
|
-
end
|
1772
|
-
|
1773
|
-
def test_respond_to_private_class_methods
|
1774
|
-
client_association = companies(:first_firm).clients
|
1775
|
-
assert !client_association.respond_to?(:private_method)
|
1776
|
-
assert client_association.respond_to?(:private_method, true)
|
1777
|
-
end
|
1778
|
-
|
1779
|
-
def test_creating_using_primary_key
|
1780
|
-
firm = Firm.all.merge!(:order => "id").first
|
1781
|
-
client = firm.clients_using_primary_key.create!(:name => 'test')
|
1782
|
-
assert_equal firm.name, client.firm_name
|
1783
|
-
end
|
1784
|
-
|
1785
|
-
def test_defining_has_many_association_with_delete_all_dependency_lazily_evaluates_target_class
|
1786
|
-
ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
|
1787
|
-
class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
1788
|
-
class DeleteAllModel < ActiveRecord::Base
|
1789
|
-
has_many :nonentities, :dependent => :delete_all
|
1790
|
-
end
|
1791
|
-
EOF
|
1792
|
-
end
|
1793
|
-
|
1794
|
-
def test_defining_has_many_association_with_nullify_dependency_lazily_evaluates_target_class
|
1795
|
-
ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
|
1796
|
-
class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
1797
|
-
class NullifyModel < ActiveRecord::Base
|
1798
|
-
has_many :nonentities, :dependent => :nullify
|
1799
|
-
end
|
1800
|
-
EOF
|
1801
|
-
end
|
1802
|
-
|
1803
|
-
def test_attributes_are_being_set_when_initialized_from_has_many_association_with_where_clause
|
1804
|
-
new_comment = posts(:welcome).comments.where(:body => "Some content").build
|
1805
|
-
assert_equal new_comment.body, "Some content"
|
1806
|
-
end
|
1807
|
-
|
1808
|
-
def test_attributes_are_being_set_when_initialized_from_has_many_association_with_multiple_where_clauses
|
1809
|
-
new_comment = posts(:welcome).comments.where(:body => "Some content").where(:type => 'SpecialComment').build
|
1810
|
-
assert_equal new_comment.body, "Some content"
|
1811
|
-
assert_equal new_comment.type, "SpecialComment"
|
1812
|
-
assert_equal new_comment.post_id, posts(:welcome).id
|
1813
|
-
end
|
1814
|
-
|
1815
|
-
def test_include_method_in_has_many_association_should_return_true_for_instance_added_with_build
|
1816
|
-
post = Post.new
|
1817
|
-
comment = post.comments.build
|
1818
|
-
assert_equal true, post.comments.include?(comment)
|
1819
|
-
end
|
1820
|
-
|
1821
|
-
def test_load_target_respects_protected_attributes
|
1822
|
-
topic = Topic.create!
|
1823
|
-
reply = topic.replies.create(:title => "reply 1")
|
1824
|
-
reply.approved = false
|
1825
|
-
reply.save!
|
1826
|
-
|
1827
|
-
# Save with a different object instance, so the instance that's still held
|
1828
|
-
# in topic.relies doesn't know about the changed attribute.
|
1829
|
-
reply2 = Reply.find(reply.id)
|
1830
|
-
reply2.approved = true
|
1831
|
-
reply2.save!
|
1832
|
-
|
1833
|
-
# Force loading the collection from the db. This will merge the existing
|
1834
|
-
# object (reply) with what gets loaded from the db (which includes the
|
1835
|
-
# changed approved attribute). approved is a protected attribute, so if mass
|
1836
|
-
# assignment is used, it won't get updated and will still be false.
|
1837
|
-
first = topic.replies.to_a.first
|
1838
|
-
assert_equal reply.id, first.id
|
1839
|
-
assert_equal true, first.approved?
|
1840
|
-
end
|
1841
|
-
|
1842
|
-
def test_to_a_should_dup_target
|
1843
|
-
ary = topics(:first).replies.to_a
|
1844
|
-
target = topics(:first).replies.target
|
1845
|
-
|
1846
|
-
assert_not_equal target.object_id, ary.object_id
|
1847
|
-
end
|
1848
|
-
|
1849
|
-
def test_merging_with_custom_attribute_writer
|
1850
|
-
bulb = Bulb.new(:color => "red")
|
1851
|
-
assert_equal "RED!", bulb.color
|
1852
|
-
|
1853
|
-
car = Car.create!
|
1854
|
-
car.bulbs << bulb
|
1855
|
-
|
1856
|
-
assert_equal "RED!", car.bulbs.to_a.first.color
|
1857
|
-
end
|
1858
|
-
|
1859
|
-
def test_abstract_class_with_polymorphic_has_many
|
1860
|
-
post = SubStiPost.create! :title => "fooo", :body => "baa"
|
1861
|
-
tagging = Tagging.create! :taggable => post
|
1862
|
-
assert_equal [tagging], post.taggings
|
1863
|
-
end
|
1864
|
-
|
1865
|
-
def test_with_polymorphic_has_many_with_custom_columns_name
|
1866
|
-
post = Post.create! :title => 'foo', :body => 'bar'
|
1867
|
-
image = Image.create!
|
1868
|
-
|
1869
|
-
post.images << image
|
1870
|
-
|
1871
|
-
assert_equal [image], post.images
|
1872
|
-
end
|
1873
|
-
|
1874
|
-
def test_build_with_polymorphic_has_many_does_not_allow_to_override_type_and_id
|
1875
|
-
welcome = posts(:welcome)
|
1876
|
-
tagging = welcome.taggings.build(:taggable_id => 99, :taggable_type => 'ShouldNotChange')
|
1877
|
-
|
1878
|
-
assert_equal welcome.id, tagging.taggable_id
|
1879
|
-
assert_equal 'Post', tagging.taggable_type
|
1880
|
-
end
|
1881
|
-
|
1882
|
-
def test_dont_call_save_callbacks_twice_on_has_many
|
1883
|
-
firm = companies(:first_firm)
|
1884
|
-
contract = firm.contracts.create!
|
1885
|
-
|
1886
|
-
assert_equal 1, contract.hi_count
|
1887
|
-
assert_equal 1, contract.bye_count
|
1888
|
-
end
|
1889
|
-
|
1890
|
-
def test_association_attributes_are_available_to_after_initialize
|
1891
|
-
car = Car.create(:name => 'honda')
|
1892
|
-
bulb = car.bulbs.build
|
1893
|
-
|
1894
|
-
assert_equal car.id, bulb.attributes_after_initialize['car_id']
|
1895
|
-
end
|
1896
|
-
|
1897
|
-
def test_attributes_are_set_when_initialized_from_has_many_null_relationship
|
1898
|
-
car = Car.new name: 'honda'
|
1899
|
-
bulb = car.bulbs.where(name: 'headlight').first_or_initialize
|
1900
|
-
assert_equal 'headlight', bulb.name
|
1901
|
-
end
|
1902
|
-
|
1903
|
-
def test_attributes_are_set_when_initialized_from_polymorphic_has_many_null_relationship
|
1904
|
-
post = Post.new title: 'title', body: 'bar'
|
1905
|
-
tag = Tag.create!(name: 'foo')
|
1906
|
-
|
1907
|
-
tagging = post.taggings.where(tag: tag).first_or_initialize
|
1908
|
-
|
1909
|
-
assert_equal tag.id, tagging.tag_id
|
1910
|
-
assert_equal 'Post', tagging.taggable_type
|
1911
|
-
end
|
1912
|
-
|
1913
|
-
def test_replace
|
1914
|
-
car = Car.create(:name => 'honda')
|
1915
|
-
bulb1 = car.bulbs.create
|
1916
|
-
bulb2 = Bulb.create
|
1917
|
-
|
1918
|
-
assert_equal [bulb1], car.bulbs
|
1919
|
-
car.bulbs.replace([bulb2])
|
1920
|
-
assert_equal [bulb2], car.bulbs
|
1921
|
-
assert_equal [bulb2], car.reload.bulbs
|
1922
|
-
end
|
1923
|
-
|
1924
|
-
def test_replace_returns_target
|
1925
|
-
car = Car.create(:name => 'honda')
|
1926
|
-
bulb1 = car.bulbs.create
|
1927
|
-
bulb2 = car.bulbs.create
|
1928
|
-
bulb3 = Bulb.create
|
1929
|
-
|
1930
|
-
assert_equal [bulb1, bulb2], car.bulbs
|
1931
|
-
result = car.bulbs.replace([bulb3, bulb1])
|
1932
|
-
assert_equal [bulb1, bulb3], car.bulbs
|
1933
|
-
assert_equal [bulb1, bulb3], result
|
1934
|
-
end
|
1935
|
-
|
1936
|
-
def test_collection_association_with_private_kernel_method
|
1937
|
-
firm = companies(:first_firm)
|
1938
|
-
assert_equal [accounts(:signals37)], firm.accounts.open
|
1939
|
-
end
|
1940
|
-
|
1941
|
-
test "first_or_initialize adds the record to the association" do
|
1942
|
-
firm = Firm.create! name: 'omg'
|
1943
|
-
client = firm.clients_of_firm.first_or_initialize
|
1944
|
-
assert_equal [client], firm.clients_of_firm
|
1945
|
-
end
|
1946
|
-
|
1947
|
-
test "first_or_create adds the record to the association" do
|
1948
|
-
firm = Firm.create! name: 'omg'
|
1949
|
-
firm.clients_of_firm.load_target
|
1950
|
-
client = firm.clients_of_firm.first_or_create name: 'lol'
|
1951
|
-
assert_equal [client], firm.clients_of_firm
|
1952
|
-
assert_equal [client], firm.reload.clients_of_firm
|
1953
|
-
end
|
1954
|
-
|
1955
|
-
test "delete_all, when not loaded, doesn't load the records" do
|
1956
|
-
post = posts(:welcome)
|
1957
|
-
|
1958
|
-
assert post.taggings_with_delete_all.count > 0
|
1959
|
-
assert !post.taggings_with_delete_all.loaded?
|
1960
|
-
|
1961
|
-
# 2 queries: one DELETE and another to update the counter cache
|
1962
|
-
assert_queries(2) do
|
1963
|
-
post.taggings_with_delete_all.delete_all
|
1964
|
-
end
|
1965
|
-
end
|
1966
|
-
|
1967
|
-
test "has many associations on new records use null relations" do
|
1968
|
-
post = Post.new
|
1969
|
-
|
1970
|
-
assert_no_queries(ignore_none: false) do
|
1971
|
-
assert_equal [], post.comments
|
1972
|
-
assert_equal [], post.comments.where(body: 'omg')
|
1973
|
-
assert_equal [], post.comments.pluck(:body)
|
1974
|
-
assert_equal 0, post.comments.sum(:id)
|
1975
|
-
assert_equal 0, post.comments.count
|
1976
|
-
end
|
1977
|
-
end
|
1978
|
-
|
1979
|
-
test "collection proxy respects default scope" do
|
1980
|
-
author = authors(:mary)
|
1981
|
-
assert !author.first_posts.exists?
|
1982
|
-
end
|
1983
|
-
|
1984
|
-
test "association with extend option" do
|
1985
|
-
post = posts(:welcome)
|
1986
|
-
assert_equal "lifo", post.comments_with_extend.author
|
1987
|
-
assert_equal "hello", post.comments_with_extend.greeting
|
1988
|
-
end
|
1989
|
-
|
1990
|
-
test "association with extend option with multiple extensions" do
|
1991
|
-
post = posts(:welcome)
|
1992
|
-
assert_equal "lifo", post.comments_with_extend_2.author
|
1993
|
-
assert_equal "hello", post.comments_with_extend_2.greeting
|
1994
|
-
end
|
1995
|
-
|
1996
|
-
test "delete record with complex joins" do
|
1997
|
-
david = authors(:david)
|
1998
|
-
|
1999
|
-
post = david.posts.first
|
2000
|
-
post.type = 'PostWithSpecialCategorization'
|
2001
|
-
post.save
|
2002
|
-
|
2003
|
-
categorization = post.categorizations.first
|
2004
|
-
categorization.special = true
|
2005
|
-
categorization.save
|
2006
|
-
|
2007
|
-
assert_not_equal [], david.posts_with_special_categorizations
|
2008
|
-
david.posts_with_special_categorizations = []
|
2009
|
-
assert_equal [], david.posts_with_special_categorizations
|
2010
|
-
end
|
2011
|
-
|
2012
|
-
test "does not duplicate associations when used with natural primary keys" do
|
2013
|
-
speedometer = Speedometer.create!(id: '4')
|
2014
|
-
speedometer.minivans.create!(minivan_id: 'a-van-red' ,name: 'a van', color: 'red')
|
2015
|
-
|
2016
|
-
assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}"
|
2017
|
-
assert_equal 1, speedometer.reload.minivans.to_a.size
|
2018
|
-
end
|
2019
|
-
|
2020
|
-
test "can unscope the default scope of the associated model" do
|
2021
|
-
car = Car.create!
|
2022
|
-
bulb1 = Bulb.create! name: "defaulty", car: car
|
2023
|
-
bulb2 = Bulb.create! name: "other", car: car
|
2024
|
-
|
2025
|
-
assert_equal [bulb1], car.bulbs
|
2026
|
-
assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
|
2027
|
-
end
|
2028
|
-
|
2029
|
-
test
|
2030
|
-
|
2031
|
-
|
2032
|
-
|
2033
|
-
|
2034
|
-
|
2035
|
-
|
2036
|
-
|
2037
|
-
|
2038
|
-
|
2039
|
-
|
2040
|
-
|
2041
|
-
|
2042
|
-
|
2043
|
-
|
2044
|
-
|
2045
|
-
assert_equal [
|
2046
|
-
assert_equal
|
2047
|
-
end
|
2048
|
-
|
2049
|
-
test '
|
2050
|
-
|
2051
|
-
|
2052
|
-
|
2053
|
-
|
2054
|
-
|
2055
|
-
end
|
2056
|
-
|
2057
|
-
test
|
2058
|
-
|
2059
|
-
|
2060
|
-
|
2061
|
-
|
2062
|
-
|
2063
|
-
|
2064
|
-
|
2065
|
-
|
2066
|
-
|
2067
|
-
|
2068
|
-
|
2069
|
-
|
2070
|
-
|
2071
|
-
|
2072
|
-
|
2073
|
-
|
2074
|
-
|
2075
|
-
|
2076
|
-
|
2077
|
-
|
2078
|
-
|
2079
|
-
|
2080
|
-
|
2081
|
-
|
2082
|
-
|
2083
|
-
|
2084
|
-
|
2085
|
-
|
2086
|
-
|
2087
|
-
|
2088
|
-
|
2089
|
-
|
2090
|
-
|
2091
|
-
|
2092
|
-
|
2093
|
-
|
2094
|
-
|
2095
|
-
|
2096
|
-
|
2097
|
-
|
2098
|
-
|
2099
|
-
|
2100
|
-
|
2101
|
-
|
2102
|
-
|
2103
|
-
|
2104
|
-
|
2105
|
-
|
2106
|
-
|
2107
|
-
|
2108
|
-
|
2109
|
-
|
2110
|
-
|
2111
|
-
|
2112
|
-
|
2113
|
-
|
2114
|
-
|
2115
|
-
|
2116
|
-
|
2117
|
-
|
2118
|
-
|
2119
|
-
|
2120
|
-
|
2121
|
-
|
2122
|
-
|
2123
|
-
|
2124
|
-
|
2125
|
-
|
2126
|
-
|
2127
|
-
|
2128
|
-
|
2129
|
-
|
2130
|
-
|
2131
|
-
bulb = Bulb.create!
|
2132
|
-
car =
|
2133
|
-
|
2134
|
-
new_bulb = Bulb.find(bulb.id)
|
2135
|
-
|
2136
|
-
|
2137
|
-
|
2138
|
-
|
2139
|
-
|
2140
|
-
|
2141
|
-
|
2142
|
-
|
2143
|
-
|
2144
|
-
|
2145
|
-
|
2146
|
-
|
2147
|
-
|
2148
|
-
|
2149
|
-
|
2150
|
-
|
2151
|
-
|
2152
|
-
|
2153
|
-
|
2154
|
-
|
2155
|
-
|
2156
|
-
|
2157
|
-
|
2158
|
-
|
2159
|
-
|
2160
|
-
|
2161
|
-
|
2162
|
-
|
1
|
+
require "cases/helper"
|
2
|
+
require 'models/developer'
|
3
|
+
require 'models/computer'
|
4
|
+
require 'models/project'
|
5
|
+
require 'models/company'
|
6
|
+
require 'models/contract'
|
7
|
+
require 'models/topic'
|
8
|
+
require 'models/reply'
|
9
|
+
require 'models/category'
|
10
|
+
require 'models/image'
|
11
|
+
require 'models/post'
|
12
|
+
require 'models/author'
|
13
|
+
require 'models/essay'
|
14
|
+
require 'models/comment'
|
15
|
+
require 'models/person'
|
16
|
+
require 'models/reader'
|
17
|
+
require 'models/tagging'
|
18
|
+
require 'models/tag'
|
19
|
+
require 'models/invoice'
|
20
|
+
require 'models/line_item'
|
21
|
+
require 'models/car'
|
22
|
+
require 'models/bulb'
|
23
|
+
require 'models/engine'
|
24
|
+
require 'models/categorization'
|
25
|
+
require 'models/minivan'
|
26
|
+
require 'models/speedometer'
|
27
|
+
require 'models/reference'
|
28
|
+
require 'models/job'
|
29
|
+
require 'models/college'
|
30
|
+
require 'models/student'
|
31
|
+
require 'models/pirate'
|
32
|
+
require 'models/ship'
|
33
|
+
require 'models/treasure'
|
34
|
+
require 'models/parrot'
|
35
|
+
require 'models/tyre'
|
36
|
+
require 'models/subscriber'
|
37
|
+
require 'models/subscription'
|
38
|
+
require 'models/zine'
|
39
|
+
require 'models/interest'
|
40
|
+
|
41
|
+
class HasManyAssociationsTestForReorderWithJoinDependency < ActiveRecord::TestCase
|
42
|
+
fixtures :authors, :posts, :comments, :author_addresses
|
43
|
+
|
44
|
+
def test_should_generate_valid_sql
|
45
|
+
author = authors(:david)
|
46
|
+
# this can fail on adapters which require ORDER BY expressions to be included in the SELECT expression
|
47
|
+
# if the reorder clauses are not correctly handled
|
48
|
+
assert author.posts_with_comments_sorted_by_comment_id.where('comments.id > 0').reorder('posts.comments_count DESC', 'posts.tags_count DESC').last
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class HasManyAssociationsTestPrimaryKeys < ActiveRecord::TestCase
|
53
|
+
fixtures :authors, :essays, :subscribers, :subscriptions, :people
|
54
|
+
|
55
|
+
def test_custom_primary_key_on_new_record_should_fetch_with_query
|
56
|
+
subscriber = Subscriber.new(nick: 'webster132')
|
57
|
+
assert !subscriber.subscriptions.loaded?
|
58
|
+
|
59
|
+
assert_queries 1 do
|
60
|
+
assert_equal 2, subscriber.subscriptions.size
|
61
|
+
end
|
62
|
+
|
63
|
+
assert_equal subscriber.subscriptions, Subscription.where(subscriber_id: 'webster132')
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_association_primary_key_on_new_record_should_fetch_with_query
|
67
|
+
author = Author.new(:name => "David")
|
68
|
+
assert !author.essays.loaded?
|
69
|
+
|
70
|
+
assert_queries 1 do
|
71
|
+
assert_equal 1, author.essays.size
|
72
|
+
end
|
73
|
+
|
74
|
+
assert_equal author.essays, Essay.where(writer_id: "David")
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_has_many_custom_primary_key
|
78
|
+
david = authors(:david)
|
79
|
+
assert_equal david.essays, Essay.where(writer_id: "David")
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_has_many_assignment_with_custom_primary_key
|
83
|
+
david = people(:david)
|
84
|
+
|
85
|
+
assert_equal ["A Modest Proposal"], david.essays.map(&:name)
|
86
|
+
david.essays = [Essay.create!(name: "Remote Work" )]
|
87
|
+
assert_equal ["Remote Work"], david.essays.map(&:name)
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_blank_custom_primary_key_on_new_record_should_not_run_queries
|
91
|
+
author = Author.new
|
92
|
+
assert !author.essays.loaded?
|
93
|
+
|
94
|
+
assert_queries 0 do
|
95
|
+
assert_equal 0, author.essays.size
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class HasManyAssociationsTest < ActiveRecord::TestCase
|
101
|
+
fixtures :accounts, :categories, :companies, :developers, :projects,
|
102
|
+
:developers_projects, :topics, :authors, :comments,
|
103
|
+
:posts, :readers, :taggings, :cars, :jobs, :tags,
|
104
|
+
:categorizations, :zines, :interests
|
105
|
+
|
106
|
+
def setup
|
107
|
+
Client.destroyed_client_ids.clear
|
108
|
+
end
|
109
|
+
|
110
|
+
def test_sti_subselect_count
|
111
|
+
tag = Tag.first
|
112
|
+
len = Post.tagged_with(tag.id).limit(10).size
|
113
|
+
assert_operator len, :>, 0
|
114
|
+
end
|
115
|
+
|
116
|
+
def test_anonymous_has_many
|
117
|
+
developer = Class.new(ActiveRecord::Base) {
|
118
|
+
self.table_name = 'developers'
|
119
|
+
dev = self
|
120
|
+
|
121
|
+
developer_project = Class.new(ActiveRecord::Base) {
|
122
|
+
self.table_name = 'developers_projects'
|
123
|
+
belongs_to :developer, :anonymous_class => dev
|
124
|
+
}
|
125
|
+
has_many :developer_projects, :anonymous_class => developer_project, :foreign_key => 'developer_id'
|
126
|
+
}
|
127
|
+
dev = developer.first
|
128
|
+
named = Developer.find(dev.id)
|
129
|
+
assert_operator dev.developer_projects.count, :>, 0
|
130
|
+
assert_equal named.projects.map(&:id).sort,
|
131
|
+
dev.developer_projects.map(&:project_id).sort
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_default_scope_on_relations_is_not_cached
|
135
|
+
counter = 0
|
136
|
+
posts = Class.new(ActiveRecord::Base) {
|
137
|
+
self.table_name = 'posts'
|
138
|
+
self.inheritance_column = 'not_there'
|
139
|
+
post = self
|
140
|
+
|
141
|
+
comments = Class.new(ActiveRecord::Base) {
|
142
|
+
self.table_name = 'comments'
|
143
|
+
self.inheritance_column = 'not_there'
|
144
|
+
belongs_to :post, :anonymous_class => post
|
145
|
+
default_scope -> {
|
146
|
+
counter += 1
|
147
|
+
where("id = :inc", :inc => counter)
|
148
|
+
}
|
149
|
+
}
|
150
|
+
has_many :comments, :anonymous_class => comments, :foreign_key => 'post_id'
|
151
|
+
}
|
152
|
+
assert_equal 0, counter
|
153
|
+
post = posts.first
|
154
|
+
assert_equal 0, counter
|
155
|
+
sql = capture_sql { post.comments.to_a }
|
156
|
+
post.comments.reset
|
157
|
+
assert_not_equal sql, capture_sql { post.comments.to_a }
|
158
|
+
end
|
159
|
+
|
160
|
+
def test_has_many_build_with_options
|
161
|
+
college = College.create(name: 'UFMT')
|
162
|
+
Student.create(active: true, college_id: college.id, name: 'Sarah')
|
163
|
+
|
164
|
+
assert_equal college.students, Student.where(active: true, college_id: college.id)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_create_from_association_should_respect_default_scope
|
168
|
+
car = Car.create(:name => 'honda')
|
169
|
+
assert_equal 'honda', car.name
|
170
|
+
|
171
|
+
bulb = Bulb.create
|
172
|
+
assert_equal 'defaulty', bulb.name
|
173
|
+
|
174
|
+
bulb = car.bulbs.build
|
175
|
+
assert_equal 'defaulty', bulb.name
|
176
|
+
|
177
|
+
bulb = car.bulbs.create
|
178
|
+
assert_equal 'defaulty', bulb.name
|
179
|
+
|
180
|
+
bulb = car.bulbs.create(:name => 'exotic')
|
181
|
+
assert_equal 'exotic', bulb.name
|
182
|
+
end
|
183
|
+
|
184
|
+
def test_build_from_association_should_respect_scope
|
185
|
+
author = Author.new
|
186
|
+
|
187
|
+
post = author.thinking_posts.build
|
188
|
+
assert_equal 'So I was thinking', post.title
|
189
|
+
end
|
190
|
+
|
191
|
+
def test_create_from_association_with_nil_values_should_work
|
192
|
+
car = Car.create(:name => 'honda')
|
193
|
+
|
194
|
+
bulb = car.bulbs.new(nil)
|
195
|
+
assert_equal 'defaulty', bulb.name
|
196
|
+
|
197
|
+
bulb = car.bulbs.build(nil)
|
198
|
+
assert_equal 'defaulty', bulb.name
|
199
|
+
|
200
|
+
bulb = car.bulbs.create(nil)
|
201
|
+
assert_equal 'defaulty', bulb.name
|
202
|
+
end
|
203
|
+
|
204
|
+
def test_do_not_call_callbacks_for_delete_all
|
205
|
+
car = Car.create(:name => 'honda')
|
206
|
+
car.funky_bulbs.create!
|
207
|
+
assert_nothing_raised { car.reload.funky_bulbs.delete_all }
|
208
|
+
assert_equal 0, Bulb.count, "bulbs should have been deleted using :delete_all strategy"
|
209
|
+
end
|
210
|
+
|
211
|
+
def test_delete_all_on_association_is_the_same_as_not_loaded
|
212
|
+
author = authors :david
|
213
|
+
author.thinking_posts.create!(:body => "test")
|
214
|
+
author.reload
|
215
|
+
expected_sql = capture_sql { author.thinking_posts.delete_all }
|
216
|
+
|
217
|
+
author.thinking_posts.create!(:body => "test")
|
218
|
+
author.reload
|
219
|
+
author.thinking_posts.inspect
|
220
|
+
loaded_sql = capture_sql { author.thinking_posts.delete_all }
|
221
|
+
assert_equal(expected_sql, loaded_sql)
|
222
|
+
end
|
223
|
+
|
224
|
+
def test_delete_all_on_association_with_nil_dependency_is_the_same_as_not_loaded
|
225
|
+
author = authors :david
|
226
|
+
author.posts.create!(:title => "test", :body => "body")
|
227
|
+
author.reload
|
228
|
+
expected_sql = capture_sql { author.posts.delete_all }
|
229
|
+
|
230
|
+
author.posts.create!(:title => "test", :body => "body")
|
231
|
+
author.reload
|
232
|
+
author.posts.to_a
|
233
|
+
loaded_sql = capture_sql { author.posts.delete_all }
|
234
|
+
assert_equal(expected_sql, loaded_sql)
|
235
|
+
end
|
236
|
+
|
237
|
+
def test_building_the_associated_object_with_implicit_sti_base_class
|
238
|
+
firm = DependentFirm.new
|
239
|
+
company = firm.companies.build
|
240
|
+
assert_kind_of Company, company, "Expected #{company.class} to be a Company"
|
241
|
+
end
|
242
|
+
|
243
|
+
def test_building_the_associated_object_with_explicit_sti_base_class
|
244
|
+
firm = DependentFirm.new
|
245
|
+
company = firm.companies.build(:type => "Company")
|
246
|
+
assert_kind_of Company, company, "Expected #{company.class} to be a Company"
|
247
|
+
end
|
248
|
+
|
249
|
+
def test_building_the_associated_object_with_sti_subclass
|
250
|
+
firm = DependentFirm.new
|
251
|
+
company = firm.companies.build(:type => "Client")
|
252
|
+
assert_kind_of Client, company, "Expected #{company.class} to be a Client"
|
253
|
+
end
|
254
|
+
|
255
|
+
def test_building_the_associated_object_with_an_invalid_type
|
256
|
+
firm = DependentFirm.new
|
257
|
+
assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Invalid") }
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_building_the_associated_object_with_an_unrelated_type
|
261
|
+
firm = DependentFirm.new
|
262
|
+
assert_raise(ActiveRecord::SubclassNotFound) { firm.companies.build(:type => "Account") }
|
263
|
+
end
|
264
|
+
|
265
|
+
test "building the association with an array" do
|
266
|
+
speedometer = Speedometer.new(speedometer_id: "a")
|
267
|
+
data = [{name: "first"}, {name: "second"}]
|
268
|
+
speedometer.minivans.build(data)
|
269
|
+
|
270
|
+
assert_equal 2, speedometer.minivans.size
|
271
|
+
assert speedometer.save
|
272
|
+
assert_equal ["first", "second"], speedometer.reload.minivans.map(&:name)
|
273
|
+
end
|
274
|
+
|
275
|
+
def test_association_keys_bypass_attribute_protection
|
276
|
+
car = Car.create(:name => 'honda')
|
277
|
+
|
278
|
+
bulb = car.bulbs.new
|
279
|
+
assert_equal car.id, bulb.car_id
|
280
|
+
|
281
|
+
bulb = car.bulbs.new :car_id => car.id + 1
|
282
|
+
assert_equal car.id, bulb.car_id
|
283
|
+
|
284
|
+
bulb = car.bulbs.build
|
285
|
+
assert_equal car.id, bulb.car_id
|
286
|
+
|
287
|
+
bulb = car.bulbs.build :car_id => car.id + 1
|
288
|
+
assert_equal car.id, bulb.car_id
|
289
|
+
|
290
|
+
bulb = car.bulbs.create
|
291
|
+
assert_equal car.id, bulb.car_id
|
292
|
+
|
293
|
+
bulb = car.bulbs.create :car_id => car.id + 1
|
294
|
+
assert_equal car.id, bulb.car_id
|
295
|
+
end
|
296
|
+
|
297
|
+
def test_association_protect_foreign_key
|
298
|
+
invoice = Invoice.create
|
299
|
+
|
300
|
+
line_item = invoice.line_items.new
|
301
|
+
assert_equal invoice.id, line_item.invoice_id
|
302
|
+
|
303
|
+
line_item = invoice.line_items.new :invoice_id => invoice.id + 1
|
304
|
+
assert_equal invoice.id, line_item.invoice_id
|
305
|
+
|
306
|
+
line_item = invoice.line_items.build
|
307
|
+
assert_equal invoice.id, line_item.invoice_id
|
308
|
+
|
309
|
+
line_item = invoice.line_items.build :invoice_id => invoice.id + 1
|
310
|
+
assert_equal invoice.id, line_item.invoice_id
|
311
|
+
|
312
|
+
line_item = invoice.line_items.create
|
313
|
+
assert_equal invoice.id, line_item.invoice_id
|
314
|
+
|
315
|
+
line_item = invoice.line_items.create :invoice_id => invoice.id + 1
|
316
|
+
assert_equal invoice.id, line_item.invoice_id
|
317
|
+
end
|
318
|
+
|
319
|
+
# When creating objects on the association, we must not do it within a scope (even though it
|
320
|
+
# would be convenient), because this would cause that scope to be applied to any callbacks etc.
|
321
|
+
def test_build_and_create_should_not_happen_within_scope
|
322
|
+
car = cars(:honda)
|
323
|
+
scoped_count = car.foo_bulbs.where_values.count
|
324
|
+
|
325
|
+
bulb = car.foo_bulbs.build
|
326
|
+
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
|
327
|
+
|
328
|
+
bulb = car.foo_bulbs.create
|
329
|
+
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
|
330
|
+
|
331
|
+
bulb = car.foo_bulbs.create!
|
332
|
+
assert_not_equal scoped_count, bulb.scope_after_initialize.where_values.count
|
333
|
+
end
|
334
|
+
|
335
|
+
def test_no_sql_should_be_fired_if_association_already_loaded
|
336
|
+
Car.create(:name => 'honda')
|
337
|
+
bulbs = Car.first.bulbs
|
338
|
+
bulbs.to_a # to load all instances of bulbs
|
339
|
+
|
340
|
+
assert_no_queries do
|
341
|
+
bulbs.first()
|
342
|
+
bulbs.first({})
|
343
|
+
end
|
344
|
+
|
345
|
+
assert_no_queries do
|
346
|
+
bulbs.second()
|
347
|
+
bulbs.second({})
|
348
|
+
end
|
349
|
+
|
350
|
+
assert_no_queries do
|
351
|
+
bulbs.third()
|
352
|
+
bulbs.third({})
|
353
|
+
end
|
354
|
+
|
355
|
+
assert_no_queries do
|
356
|
+
bulbs.fourth()
|
357
|
+
bulbs.fourth({})
|
358
|
+
end
|
359
|
+
|
360
|
+
assert_no_queries do
|
361
|
+
bulbs.fifth()
|
362
|
+
bulbs.fifth({})
|
363
|
+
end
|
364
|
+
|
365
|
+
assert_no_queries do
|
366
|
+
bulbs.forty_two()
|
367
|
+
bulbs.forty_two({})
|
368
|
+
end
|
369
|
+
|
370
|
+
assert_no_queries do
|
371
|
+
bulbs.last()
|
372
|
+
bulbs.last({})
|
373
|
+
end
|
374
|
+
end
|
375
|
+
|
376
|
+
def test_create_resets_cached_counters
|
377
|
+
person = Person.create!(:first_name => 'tenderlove')
|
378
|
+
post = Post.first
|
379
|
+
|
380
|
+
assert_equal [], person.readers
|
381
|
+
assert_nil person.readers.find_by_post_id(post.id)
|
382
|
+
|
383
|
+
person.readers.create(:post_id => post.id)
|
384
|
+
|
385
|
+
assert_equal 1, person.readers.count
|
386
|
+
assert_equal 1, person.readers.length
|
387
|
+
assert_equal post, person.readers.first.post
|
388
|
+
assert_equal person, person.readers.first.person
|
389
|
+
end
|
390
|
+
|
391
|
+
def force_signal37_to_load_all_clients_of_firm
|
392
|
+
companies(:first_firm).clients_of_firm.each {|f| }
|
393
|
+
end
|
394
|
+
|
395
|
+
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
|
396
|
+
def test_counting_with_counter_sql
|
397
|
+
assert_equal 3, Firm.all.merge!(:order => "id").first.clients.count
|
398
|
+
end
|
399
|
+
|
400
|
+
def test_counting
|
401
|
+
assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count
|
402
|
+
end
|
403
|
+
|
404
|
+
def test_counting_with_single_hash
|
405
|
+
assert_equal 1, Firm.all.merge!(:order => "id").first.plain_clients.where(:name => "Microsoft").count
|
406
|
+
end
|
407
|
+
|
408
|
+
def test_counting_with_column_name_and_hash
|
409
|
+
assert_equal 3, Firm.all.merge!(:order => "id").first.plain_clients.count(:name)
|
410
|
+
end
|
411
|
+
|
412
|
+
def test_counting_with_association_limit
|
413
|
+
firm = companies(:first_firm)
|
414
|
+
assert_equal firm.limited_clients.length, firm.limited_clients.size
|
415
|
+
assert_equal firm.limited_clients.length, firm.limited_clients.count
|
416
|
+
end
|
417
|
+
|
418
|
+
def test_finding
|
419
|
+
assert_equal 3, Firm.all.merge!(:order => "id").first.clients.length
|
420
|
+
end
|
421
|
+
|
422
|
+
def test_finding_array_compatibility
|
423
|
+
assert_equal 3, Firm.order(:id).find{|f| f.id > 0}.clients.length
|
424
|
+
end
|
425
|
+
|
426
|
+
def test_find_many_with_merged_options
|
427
|
+
assert_equal 1, companies(:first_firm).limited_clients.size
|
428
|
+
assert_equal 1, companies(:first_firm).limited_clients.to_a.size
|
429
|
+
assert_equal 3, companies(:first_firm).limited_clients.limit(nil).to_a.size
|
430
|
+
end
|
431
|
+
|
432
|
+
def test_find_should_append_to_association_order
|
433
|
+
ordered_clients = companies(:first_firm).clients_sorted_desc.order('companies.id')
|
434
|
+
assert_equal ['id DESC', 'companies.id'], ordered_clients.order_values
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_dynamic_find_should_respect_association_order
|
438
|
+
assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.where("type = 'Client'").first
|
439
|
+
assert_equal companies(:another_first_firm_client), companies(:first_firm).clients_sorted_desc.find_by_type('Client')
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_taking
|
443
|
+
posts(:other_by_bob).destroy
|
444
|
+
assert_equal posts(:misc_by_bob), authors(:bob).posts.take
|
445
|
+
assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
|
446
|
+
authors(:bob).posts.to_a
|
447
|
+
assert_equal posts(:misc_by_bob), authors(:bob).posts.take
|
448
|
+
assert_equal posts(:misc_by_bob), authors(:bob).posts.take!
|
449
|
+
end
|
450
|
+
|
451
|
+
def test_taking_not_found
|
452
|
+
authors(:bob).posts.delete_all
|
453
|
+
assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
|
454
|
+
authors(:bob).posts.to_a
|
455
|
+
assert_raise(ActiveRecord::RecordNotFound) { authors(:bob).posts.take! }
|
456
|
+
end
|
457
|
+
|
458
|
+
def test_taking_with_a_number
|
459
|
+
# taking from unloaded Relation
|
460
|
+
bob = Author.find(authors(:bob).id)
|
461
|
+
assert_equal [posts(:misc_by_bob)], bob.posts.take(1)
|
462
|
+
bob = Author.find(authors(:bob).id)
|
463
|
+
assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], bob.posts.take(2)
|
464
|
+
|
465
|
+
# taking from loaded Relation
|
466
|
+
bob.posts.to_a
|
467
|
+
assert_equal [posts(:misc_by_bob)], authors(:bob).posts.take(1)
|
468
|
+
assert_equal [posts(:misc_by_bob), posts(:other_by_bob)], authors(:bob).posts.take(2)
|
469
|
+
end
|
470
|
+
|
471
|
+
def test_taking_with_inverse_of
|
472
|
+
interests(:woodsmanship).destroy
|
473
|
+
interests(:survival).destroy
|
474
|
+
|
475
|
+
zine = zines(:going_out)
|
476
|
+
interest = zine.interests.take
|
477
|
+
assert_equal interests(:hunting), interest
|
478
|
+
assert_same zine, interest.zine
|
479
|
+
end
|
480
|
+
|
481
|
+
def test_cant_save_has_many_readonly_association
|
482
|
+
authors(:david).readonly_comments.each { |c| assert_raise(ActiveRecord::ReadOnlyRecord) { c.save! } }
|
483
|
+
authors(:david).readonly_comments.each { |c| assert c.readonly? }
|
484
|
+
end
|
485
|
+
|
486
|
+
def test_finding_default_orders
|
487
|
+
assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients.first.name
|
488
|
+
end
|
489
|
+
|
490
|
+
def test_finding_with_different_class_name_and_order
|
491
|
+
assert_equal "Apex", Firm.all.merge!(:order => "id").first.clients_sorted_desc.first.name
|
492
|
+
end
|
493
|
+
|
494
|
+
def test_finding_with_foreign_key
|
495
|
+
assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_of_firm.first.name
|
496
|
+
end
|
497
|
+
|
498
|
+
def test_finding_with_condition
|
499
|
+
assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms.first.name
|
500
|
+
end
|
501
|
+
|
502
|
+
def test_finding_with_condition_hash
|
503
|
+
assert_equal "Microsoft", Firm.all.merge!(:order => "id").first.clients_like_ms_with_hash_conditions.first.name
|
504
|
+
end
|
505
|
+
|
506
|
+
def test_finding_using_primary_key
|
507
|
+
assert_equal "Summit", Firm.all.merge!(:order => "id").first.clients_using_primary_key.first.name
|
508
|
+
end
|
509
|
+
|
510
|
+
def test_update_all_on_association_accessed_before_save
|
511
|
+
firm = Firm.new(name: 'Firm')
|
512
|
+
firm.clients << Client.first
|
513
|
+
firm.save!
|
514
|
+
assert_equal firm.clients.count, firm.clients.update_all(description: 'Great!')
|
515
|
+
end
|
516
|
+
|
517
|
+
def test_belongs_to_sanity
|
518
|
+
c = Client.new
|
519
|
+
assert_nil c.firm, "belongs_to failed sanity check on new object"
|
520
|
+
end
|
521
|
+
|
522
|
+
def test_find_ids
|
523
|
+
firm = Firm.all.merge!(:order => "id").first
|
524
|
+
|
525
|
+
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find }
|
526
|
+
|
527
|
+
client = firm.clients.find(2)
|
528
|
+
assert_kind_of Client, client
|
529
|
+
|
530
|
+
client_ary = firm.clients.find([2])
|
531
|
+
assert_kind_of Array, client_ary
|
532
|
+
assert_equal client, client_ary.first
|
533
|
+
|
534
|
+
client_ary = firm.clients.find(2, 3)
|
535
|
+
assert_kind_of Array, client_ary
|
536
|
+
assert_equal 2, client_ary.size
|
537
|
+
assert_equal client, client_ary.first
|
538
|
+
|
539
|
+
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(2, 99) }
|
540
|
+
end
|
541
|
+
|
542
|
+
def test_find_ids_and_inverse_of
|
543
|
+
force_signal37_to_load_all_clients_of_firm
|
544
|
+
|
545
|
+
firm = companies(:first_firm)
|
546
|
+
client = firm.clients_of_firm.find(3)
|
547
|
+
assert_kind_of Client, client
|
548
|
+
|
549
|
+
client_ary = firm.clients_of_firm.find([3])
|
550
|
+
assert_kind_of Array, client_ary
|
551
|
+
assert_equal client, client_ary.first
|
552
|
+
end
|
553
|
+
|
554
|
+
def test_find_all
|
555
|
+
firm = Firm.all.merge!(:order => "id").first
|
556
|
+
assert_equal 3, firm.clients.where("#{QUOTED_TYPE} = 'Client'").to_a.length
|
557
|
+
assert_equal 1, firm.clients.where("name = 'Summit'").to_a.length
|
558
|
+
end
|
559
|
+
|
560
|
+
def test_find_each
|
561
|
+
firm = companies(:first_firm)
|
562
|
+
|
563
|
+
assert ! firm.clients.loaded?
|
564
|
+
|
565
|
+
assert_queries(4) do
|
566
|
+
firm.clients.find_each(:batch_size => 1) {|c| assert_equal firm.id, c.firm_id }
|
567
|
+
end
|
568
|
+
|
569
|
+
assert ! firm.clients.loaded?
|
570
|
+
end
|
571
|
+
|
572
|
+
def test_find_each_with_conditions
|
573
|
+
firm = companies(:first_firm)
|
574
|
+
|
575
|
+
assert_queries(2) do
|
576
|
+
firm.clients.where(name: 'Microsoft').find_each(batch_size: 1) do |c|
|
577
|
+
assert_equal firm.id, c.firm_id
|
578
|
+
assert_equal "Microsoft", c.name
|
579
|
+
end
|
580
|
+
end
|
581
|
+
|
582
|
+
assert ! firm.clients.loaded?
|
583
|
+
end
|
584
|
+
|
585
|
+
def test_find_in_batches
|
586
|
+
firm = companies(:first_firm)
|
587
|
+
|
588
|
+
assert ! firm.clients.loaded?
|
589
|
+
|
590
|
+
assert_queries(2) do
|
591
|
+
firm.clients.find_in_batches(:batch_size => 2) do |clients|
|
592
|
+
clients.each {|c| assert_equal firm.id, c.firm_id }
|
593
|
+
end
|
594
|
+
end
|
595
|
+
|
596
|
+
assert ! firm.clients.loaded?
|
597
|
+
end
|
598
|
+
|
599
|
+
def test_find_all_sanitized
|
600
|
+
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
|
601
|
+
firm = Firm.all.merge!(:order => "id").first
|
602
|
+
summit = firm.clients.where("name = 'Summit'").to_a
|
603
|
+
assert_equal summit, firm.clients.where("name = ?", "Summit").to_a
|
604
|
+
assert_equal summit, firm.clients.where("name = :name", { :name => "Summit" }).to_a
|
605
|
+
end
|
606
|
+
|
607
|
+
def test_find_first
|
608
|
+
firm = Firm.all.merge!(:order => "id").first
|
609
|
+
client2 = Client.find(2)
|
610
|
+
assert_equal firm.clients.first, firm.clients.order("id").first
|
611
|
+
assert_equal client2, firm.clients.where("#{QUOTED_TYPE} = 'Client'").order("id").first
|
612
|
+
end
|
613
|
+
|
614
|
+
def test_find_first_sanitized
|
615
|
+
firm = Firm.all.merge!(:order => "id").first
|
616
|
+
client2 = Client.find(2)
|
617
|
+
assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = ?", 'Client'], :order => "id").first
|
618
|
+
assert_equal client2, firm.clients.merge!(:where => ["#{QUOTED_TYPE} = :type", { :type => 'Client' }], :order => "id").first
|
619
|
+
end
|
620
|
+
|
621
|
+
def test_find_all_with_include_and_conditions
|
622
|
+
assert_nothing_raised do
|
623
|
+
Developer.all.merge!(:joins => :audit_logs, :where => {'audit_logs.message' => nil, :name => 'Smith'}).to_a
|
624
|
+
end
|
625
|
+
end
|
626
|
+
|
627
|
+
def test_find_in_collection
|
628
|
+
assert_equal Client.find(2).name, companies(:first_firm).clients.find(2).name
|
629
|
+
assert_raise(ActiveRecord::RecordNotFound) { companies(:first_firm).clients.find(6) }
|
630
|
+
end
|
631
|
+
|
632
|
+
def test_find_grouped
|
633
|
+
all_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1").to_a
|
634
|
+
grouped_clients_of_firm1 = Client.all.merge!(:where => "firm_id = 1", :group => "firm_id", :select => 'firm_id, count(id) as clients_count').to_a
|
635
|
+
assert_equal 3, all_clients_of_firm1.size
|
636
|
+
assert_equal 1, grouped_clients_of_firm1.size
|
637
|
+
end
|
638
|
+
|
639
|
+
def test_find_scoped_grouped
|
640
|
+
assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.size
|
641
|
+
assert_equal 1, companies(:first_firm).clients_grouped_by_firm_id.length
|
642
|
+
assert_equal 3, companies(:first_firm).clients_grouped_by_name.size
|
643
|
+
assert_equal 3, companies(:first_firm).clients_grouped_by_name.length
|
644
|
+
end
|
645
|
+
|
646
|
+
def test_find_scoped_grouped_having
|
647
|
+
assert_equal 1, authors(:david).popular_grouped_posts.length
|
648
|
+
assert_equal 0, authors(:mary).popular_grouped_posts.length
|
649
|
+
end
|
650
|
+
|
651
|
+
def test_default_select
|
652
|
+
assert_equal Comment.column_names.sort, posts(:welcome).comments.first.attributes.keys.sort
|
653
|
+
end
|
654
|
+
|
655
|
+
def test_select_query_method
|
656
|
+
assert_equal ['id', 'body'], posts(:welcome).comments.select(:id, :body).first.attributes.keys
|
657
|
+
end
|
658
|
+
|
659
|
+
def test_select_with_block
|
660
|
+
assert_equal [1], posts(:welcome).comments.select { |c| c.id == 1 }.map(&:id)
|
661
|
+
end
|
662
|
+
|
663
|
+
def test_select_without_foreign_key
|
664
|
+
assert_equal companies(:first_firm).accounts.first.credit_limit, companies(:first_firm).accounts.select(:credit_limit).first.credit_limit
|
665
|
+
end
|
666
|
+
|
667
|
+
def test_adding
|
668
|
+
force_signal37_to_load_all_clients_of_firm
|
669
|
+
natural = Client.new("name" => "Natural Company")
|
670
|
+
companies(:first_firm).clients_of_firm << natural
|
671
|
+
assert_equal 3, companies(:first_firm).clients_of_firm.size # checking via the collection
|
672
|
+
assert_equal 3, companies(:first_firm).clients_of_firm(true).size # checking using the db
|
673
|
+
assert_equal natural, companies(:first_firm).clients_of_firm.last
|
674
|
+
end
|
675
|
+
|
676
|
+
def test_adding_using_create
|
677
|
+
first_firm = companies(:first_firm)
|
678
|
+
assert_equal 3, first_firm.plain_clients.size
|
679
|
+
first_firm.plain_clients.create(:name => "Natural Company")
|
680
|
+
assert_equal 4, first_firm.plain_clients.length
|
681
|
+
assert_equal 4, first_firm.plain_clients.size
|
682
|
+
end
|
683
|
+
|
684
|
+
def test_create_with_bang_on_has_many_when_parent_is_new_raises
|
685
|
+
error = assert_raise(ActiveRecord::RecordNotSaved) do
|
686
|
+
firm = Firm.new
|
687
|
+
firm.plain_clients.create! :name=>"Whoever"
|
688
|
+
end
|
689
|
+
|
690
|
+
assert_equal "You cannot call create unless the parent is saved", error.message
|
691
|
+
end
|
692
|
+
|
693
|
+
def test_regular_create_on_has_many_when_parent_is_new_raises
|
694
|
+
error = assert_raise(ActiveRecord::RecordNotSaved) do
|
695
|
+
firm = Firm.new
|
696
|
+
firm.plain_clients.create :name=>"Whoever"
|
697
|
+
end
|
698
|
+
|
699
|
+
assert_equal "You cannot call create unless the parent is saved", error.message
|
700
|
+
end
|
701
|
+
|
702
|
+
def test_create_with_bang_on_has_many_raises_when_record_not_saved
|
703
|
+
assert_raise(ActiveRecord::RecordInvalid) do
|
704
|
+
firm = Firm.all.merge!(:order => "id").first
|
705
|
+
firm.plain_clients.create!
|
706
|
+
end
|
707
|
+
end
|
708
|
+
|
709
|
+
def test_create_with_bang_on_habtm_when_parent_is_new_raises
|
710
|
+
error = assert_raise(ActiveRecord::RecordNotSaved) do
|
711
|
+
Developer.new("name" => "Aredridel").projects.create!
|
712
|
+
end
|
713
|
+
|
714
|
+
assert_equal "You cannot call create unless the parent is saved", error.message
|
715
|
+
end
|
716
|
+
|
717
|
+
def test_adding_a_mismatch_class
|
718
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << nil }
|
719
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << 1 }
|
720
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { companies(:first_firm).clients_of_firm << Topic.find(1) }
|
721
|
+
end
|
722
|
+
|
723
|
+
def test_adding_a_collection
|
724
|
+
force_signal37_to_load_all_clients_of_firm
|
725
|
+
companies(:first_firm).clients_of_firm.concat([Client.new("name" => "Natural Company"), Client.new("name" => "Apple")])
|
726
|
+
assert_equal 4, companies(:first_firm).clients_of_firm.size
|
727
|
+
assert_equal 4, companies(:first_firm).clients_of_firm(true).size
|
728
|
+
end
|
729
|
+
|
730
|
+
def test_transactions_when_adding_to_persisted
|
731
|
+
good = Client.new(:name => "Good")
|
732
|
+
bad = Client.new(:name => "Bad", :raise_on_save => true)
|
733
|
+
|
734
|
+
begin
|
735
|
+
companies(:first_firm).clients_of_firm.concat(good, bad)
|
736
|
+
rescue Client::RaisedOnSave
|
737
|
+
end
|
738
|
+
|
739
|
+
assert !companies(:first_firm).clients_of_firm(true).include?(good)
|
740
|
+
end
|
741
|
+
|
742
|
+
def test_transactions_when_adding_to_new_record
|
743
|
+
assert_no_queries(ignore_none: false) do
|
744
|
+
firm = Firm.new
|
745
|
+
firm.clients_of_firm.concat(Client.new("name" => "Natural Company"))
|
746
|
+
end
|
747
|
+
end
|
748
|
+
|
749
|
+
def test_inverse_on_before_validate
|
750
|
+
firm = companies(:first_firm)
|
751
|
+
assert_queries(1) do
|
752
|
+
firm.clients_of_firm << Client.new("name" => "Natural Company")
|
753
|
+
end
|
754
|
+
end
|
755
|
+
|
756
|
+
def test_new_aliased_to_build
|
757
|
+
company = companies(:first_firm)
|
758
|
+
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.new("name" => "Another Client") }
|
759
|
+
assert !company.clients_of_firm.loaded?
|
760
|
+
|
761
|
+
assert_equal "Another Client", new_client.name
|
762
|
+
assert !new_client.persisted?
|
763
|
+
assert_equal new_client, company.clients_of_firm.last
|
764
|
+
end
|
765
|
+
|
766
|
+
def test_build
|
767
|
+
company = companies(:first_firm)
|
768
|
+
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build("name" => "Another Client") }
|
769
|
+
assert !company.clients_of_firm.loaded?
|
770
|
+
|
771
|
+
assert_equal "Another Client", new_client.name
|
772
|
+
assert !new_client.persisted?
|
773
|
+
assert_equal new_client, company.clients_of_firm.last
|
774
|
+
end
|
775
|
+
|
776
|
+
def test_collection_size_after_building
|
777
|
+
company = companies(:first_firm) # company already has one client
|
778
|
+
company.clients_of_firm.build("name" => "Another Client")
|
779
|
+
company.clients_of_firm.build("name" => "Yet Another Client")
|
780
|
+
assert_equal 4, company.clients_of_firm.size
|
781
|
+
end
|
782
|
+
|
783
|
+
def test_collection_not_empty_after_building
|
784
|
+
company = companies(:first_firm)
|
785
|
+
assert_predicate company.contracts, :empty?
|
786
|
+
company.contracts.build
|
787
|
+
assert_not_predicate company.contracts, :empty?
|
788
|
+
end
|
789
|
+
|
790
|
+
def test_collection_size_twice_for_regressions
|
791
|
+
post = posts(:thinking)
|
792
|
+
assert_equal 0, post.readers.size
|
793
|
+
# This test needs a post that has no readers, we assert it to ensure it holds,
|
794
|
+
# but need to reload the post because the very call to #size hides the bug.
|
795
|
+
post.reload
|
796
|
+
post.readers.build
|
797
|
+
size1 = post.readers.size
|
798
|
+
size2 = post.readers.size
|
799
|
+
assert_equal size1, size2
|
800
|
+
end
|
801
|
+
|
802
|
+
def test_build_many
|
803
|
+
company = companies(:first_firm)
|
804
|
+
new_clients = assert_no_queries(ignore_none: false) { company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) }
|
805
|
+
assert_equal 2, new_clients.size
|
806
|
+
end
|
807
|
+
|
808
|
+
def test_build_followed_by_save_does_not_load_target
|
809
|
+
companies(:first_firm).clients_of_firm.build("name" => "Another Client")
|
810
|
+
assert companies(:first_firm).save
|
811
|
+
assert !companies(:first_firm).clients_of_firm.loaded?
|
812
|
+
end
|
813
|
+
|
814
|
+
def test_build_without_loading_association
|
815
|
+
first_topic = topics(:first)
|
816
|
+
Reply.column_names
|
817
|
+
|
818
|
+
assert_equal 1, first_topic.replies.length
|
819
|
+
|
820
|
+
assert_no_queries do
|
821
|
+
first_topic.replies.build(:title => "Not saved", :content => "Superstars")
|
822
|
+
assert_equal 2, first_topic.replies.size
|
823
|
+
end
|
824
|
+
|
825
|
+
assert_equal 2, first_topic.replies.to_ary.size
|
826
|
+
end
|
827
|
+
|
828
|
+
def test_build_via_block
|
829
|
+
company = companies(:first_firm)
|
830
|
+
new_client = assert_no_queries(ignore_none: false) { company.clients_of_firm.build {|client| client.name = "Another Client" } }
|
831
|
+
assert !company.clients_of_firm.loaded?
|
832
|
+
|
833
|
+
assert_equal "Another Client", new_client.name
|
834
|
+
assert !new_client.persisted?
|
835
|
+
assert_equal new_client, company.clients_of_firm.last
|
836
|
+
end
|
837
|
+
|
838
|
+
def test_build_many_via_block
|
839
|
+
company = companies(:first_firm)
|
840
|
+
new_clients = assert_no_queries(ignore_none: false) do
|
841
|
+
company.clients_of_firm.build([{"name" => "Another Client"}, {"name" => "Another Client II"}]) do |client|
|
842
|
+
client.name = "changed"
|
843
|
+
end
|
844
|
+
end
|
845
|
+
|
846
|
+
assert_equal 2, new_clients.size
|
847
|
+
assert_equal "changed", new_clients.first.name
|
848
|
+
assert_equal "changed", new_clients.last.name
|
849
|
+
end
|
850
|
+
|
851
|
+
def test_create_without_loading_association
|
852
|
+
first_firm = companies(:first_firm)
|
853
|
+
Firm.column_names
|
854
|
+
Client.column_names
|
855
|
+
|
856
|
+
assert_equal 2, first_firm.clients_of_firm.size
|
857
|
+
first_firm.clients_of_firm.reset
|
858
|
+
|
859
|
+
assert_queries(1) do
|
860
|
+
first_firm.clients_of_firm.create(:name => "Superstars")
|
861
|
+
end
|
862
|
+
|
863
|
+
assert_equal 3, first_firm.clients_of_firm.size
|
864
|
+
end
|
865
|
+
|
866
|
+
def test_create
|
867
|
+
force_signal37_to_load_all_clients_of_firm
|
868
|
+
new_client = companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
869
|
+
assert new_client.persisted?
|
870
|
+
assert_equal new_client, companies(:first_firm).clients_of_firm.last
|
871
|
+
assert_equal new_client, companies(:first_firm).clients_of_firm(true).last
|
872
|
+
end
|
873
|
+
|
874
|
+
def test_create_many
|
875
|
+
companies(:first_firm).clients_of_firm.create([{"name" => "Another Client"}, {"name" => "Another Client II"}])
|
876
|
+
assert_equal 4, companies(:first_firm).clients_of_firm(true).size
|
877
|
+
end
|
878
|
+
|
879
|
+
def test_create_followed_by_save_does_not_load_target
|
880
|
+
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
881
|
+
assert companies(:first_firm).save
|
882
|
+
assert !companies(:first_firm).clients_of_firm.loaded?
|
883
|
+
end
|
884
|
+
|
885
|
+
def test_deleting
|
886
|
+
force_signal37_to_load_all_clients_of_firm
|
887
|
+
companies(:first_firm).clients_of_firm.delete(companies(:first_firm).clients_of_firm.first)
|
888
|
+
assert_equal 1, companies(:first_firm).clients_of_firm.size
|
889
|
+
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
890
|
+
end
|
891
|
+
|
892
|
+
def test_deleting_before_save
|
893
|
+
new_firm = Firm.new("name" => "A New Firm, Inc.")
|
894
|
+
new_client = new_firm.clients_of_firm.build("name" => "Another Client")
|
895
|
+
assert_equal 1, new_firm.clients_of_firm.size
|
896
|
+
new_firm.clients_of_firm.delete(new_client)
|
897
|
+
assert_equal 0, new_firm.clients_of_firm.size
|
898
|
+
end
|
899
|
+
|
900
|
+
def test_has_many_without_counter_cache_option
|
901
|
+
# Ship has a conventionally named `treasures_count` column, but the counter_cache
|
902
|
+
# option is not given on the association.
|
903
|
+
ship = Ship.create(name: 'Countless', treasures_count: 10)
|
904
|
+
|
905
|
+
assert_not ship.treasures.instance_variable_get('@association').send(:has_cached_counter?)
|
906
|
+
|
907
|
+
# Count should come from sql count() of treasures rather than treasures_count attribute
|
908
|
+
assert_equal ship.treasures.size, 0
|
909
|
+
|
910
|
+
assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
|
911
|
+
ship.treasures.create(name: 'Gold')
|
912
|
+
end
|
913
|
+
|
914
|
+
assert_no_difference lambda { ship.reload.treasures_count }, "treasures_count should not be changed" do
|
915
|
+
ship.treasures.destroy_all
|
916
|
+
end
|
917
|
+
end
|
918
|
+
|
919
|
+
def test_deleting_updates_counter_cache
|
920
|
+
topic = Topic.order("id ASC").first
|
921
|
+
assert_equal topic.replies.to_a.size, topic.replies_count
|
922
|
+
|
923
|
+
topic.replies.delete(topic.replies.first)
|
924
|
+
topic.reload
|
925
|
+
assert_equal topic.replies.to_a.size, topic.replies_count
|
926
|
+
end
|
927
|
+
|
928
|
+
def test_counter_cache_updates_in_memory_after_concat
|
929
|
+
topic = Topic.create title: "Zoom-zoom-zoom"
|
930
|
+
|
931
|
+
topic.replies << Reply.create(title: "re: zoom", content: "speedy quick!")
|
932
|
+
assert_equal 1, topic.replies_count
|
933
|
+
assert_equal 1, topic.replies.size
|
934
|
+
assert_equal 1, topic.reload.replies.size
|
935
|
+
end
|
936
|
+
|
937
|
+
def test_counter_cache_updates_in_memory_after_create
|
938
|
+
topic = Topic.create title: "Zoom-zoom-zoom"
|
939
|
+
|
940
|
+
topic.replies.create!(title: "re: zoom", content: "speedy quick!")
|
941
|
+
assert_equal 1, topic.replies_count
|
942
|
+
assert_equal 1, topic.replies.size
|
943
|
+
assert_equal 1, topic.reload.replies.size
|
944
|
+
end
|
945
|
+
|
946
|
+
def test_counter_cache_updates_in_memory_after_create_with_array
|
947
|
+
topic = Topic.create title: "Zoom-zoom-zoom"
|
948
|
+
|
949
|
+
topic.replies.create!([
|
950
|
+
{ title: "re: zoom", content: "speedy quick!" },
|
951
|
+
{ title: "re: zoom 2", content: "OMG lol!" },
|
952
|
+
])
|
953
|
+
assert_equal 2, topic.replies_count
|
954
|
+
assert_equal 2, topic.replies.size
|
955
|
+
assert_equal 2, topic.reload.replies.size
|
956
|
+
end
|
957
|
+
|
958
|
+
def test_pushing_association_updates_counter_cache
|
959
|
+
topic = Topic.order("id ASC").first
|
960
|
+
reply = Reply.create!
|
961
|
+
|
962
|
+
assert_difference "topic.reload.replies_count", 1 do
|
963
|
+
topic.replies << reply
|
964
|
+
end
|
965
|
+
end
|
966
|
+
|
967
|
+
def test_deleting_updates_counter_cache_without_dependent_option
|
968
|
+
post = posts(:welcome)
|
969
|
+
|
970
|
+
assert_difference "post.reload.tags_count", -1 do
|
971
|
+
post.taggings.delete(post.taggings.first)
|
972
|
+
end
|
973
|
+
end
|
974
|
+
|
975
|
+
def test_deleting_updates_counter_cache_with_dependent_delete_all
|
976
|
+
post = posts(:welcome)
|
977
|
+
post.update_columns(taggings_with_delete_all_count: post.tags_count)
|
978
|
+
|
979
|
+
assert_difference "post.reload.taggings_with_delete_all_count", -1 do
|
980
|
+
post.taggings_with_delete_all.delete(post.taggings_with_delete_all.first)
|
981
|
+
end
|
982
|
+
end
|
983
|
+
|
984
|
+
def test_deleting_updates_counter_cache_with_dependent_destroy
|
985
|
+
post = posts(:welcome)
|
986
|
+
post.update_columns(taggings_with_destroy_count: post.tags_count)
|
987
|
+
|
988
|
+
assert_difference "post.reload.taggings_with_destroy_count", -1 do
|
989
|
+
post.taggings_with_destroy.delete(post.taggings_with_destroy.first)
|
990
|
+
end
|
991
|
+
end
|
992
|
+
|
993
|
+
def test_calling_empty_with_counter_cache
|
994
|
+
post = posts(:welcome)
|
995
|
+
assert_queries(0) do
|
996
|
+
assert_not post.comments.empty?
|
997
|
+
end
|
998
|
+
end
|
999
|
+
|
1000
|
+
def test_custom_named_counter_cache
|
1001
|
+
topic = topics(:first)
|
1002
|
+
|
1003
|
+
assert_difference "topic.reload.replies_count", -1 do
|
1004
|
+
topic.approved_replies.clear
|
1005
|
+
end
|
1006
|
+
end
|
1007
|
+
|
1008
|
+
def test_calling_update_attributes_on_id_changes_the_counter_cache
|
1009
|
+
topic = Topic.order("id ASC").first
|
1010
|
+
original_count = topic.replies.to_a.size
|
1011
|
+
assert_equal original_count, topic.replies_count
|
1012
|
+
|
1013
|
+
first_reply = topic.replies.first
|
1014
|
+
first_reply.update_attributes(:parent_id => nil)
|
1015
|
+
assert_equal original_count - 1, topic.reload.replies_count
|
1016
|
+
|
1017
|
+
first_reply.update_attributes(:parent_id => topic.id)
|
1018
|
+
assert_equal original_count, topic.reload.replies_count
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
def test_calling_update_attributes_changing_ids_doesnt_change_counter_cache
|
1022
|
+
topic1 = Topic.find(1)
|
1023
|
+
topic2 = Topic.find(3)
|
1024
|
+
original_count1 = topic1.replies.to_a.size
|
1025
|
+
original_count2 = topic2.replies.to_a.size
|
1026
|
+
|
1027
|
+
reply1 = topic1.replies.first
|
1028
|
+
reply2 = topic2.replies.first
|
1029
|
+
|
1030
|
+
reply1.update_attributes(:parent_id => topic2.id)
|
1031
|
+
assert_equal original_count1 - 1, topic1.reload.replies_count
|
1032
|
+
assert_equal original_count2 + 1, topic2.reload.replies_count
|
1033
|
+
|
1034
|
+
reply2.update_attributes(:parent_id => topic1.id)
|
1035
|
+
assert_equal original_count1, topic1.reload.replies_count
|
1036
|
+
assert_equal original_count2, topic2.reload.replies_count
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
def test_deleting_a_collection
|
1040
|
+
force_signal37_to_load_all_clients_of_firm
|
1041
|
+
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
1042
|
+
assert_equal 3, companies(:first_firm).clients_of_firm.size
|
1043
|
+
companies(:first_firm).clients_of_firm.delete([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1], companies(:first_firm).clients_of_firm[2]])
|
1044
|
+
assert_equal 0, companies(:first_firm).clients_of_firm.size
|
1045
|
+
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
|
1046
|
+
end
|
1047
|
+
|
1048
|
+
def test_delete_all
|
1049
|
+
force_signal37_to_load_all_clients_of_firm
|
1050
|
+
companies(:first_firm).dependent_clients_of_firm.create("name" => "Another Client")
|
1051
|
+
clients = companies(:first_firm).dependent_clients_of_firm.to_a
|
1052
|
+
assert_equal 3, clients.count
|
1053
|
+
|
1054
|
+
assert_difference "Client.count", -(clients.count) do
|
1055
|
+
companies(:first_firm).dependent_clients_of_firm.delete_all
|
1056
|
+
end
|
1057
|
+
end
|
1058
|
+
|
1059
|
+
def test_delete_all_with_not_yet_loaded_association_collection
|
1060
|
+
force_signal37_to_load_all_clients_of_firm
|
1061
|
+
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
1062
|
+
assert_equal 3, companies(:first_firm).clients_of_firm.size
|
1063
|
+
companies(:first_firm).clients_of_firm.reset
|
1064
|
+
companies(:first_firm).clients_of_firm.delete_all
|
1065
|
+
assert_equal 0, companies(:first_firm).clients_of_firm.size
|
1066
|
+
assert_equal 0, companies(:first_firm).clients_of_firm(true).size
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
def test_transaction_when_deleting_persisted
|
1070
|
+
good = Client.new(:name => "Good")
|
1071
|
+
bad = Client.new(:name => "Bad", :raise_on_destroy => true)
|
1072
|
+
|
1073
|
+
companies(:first_firm).clients_of_firm = [good, bad]
|
1074
|
+
|
1075
|
+
begin
|
1076
|
+
companies(:first_firm).clients_of_firm.destroy(good, bad)
|
1077
|
+
rescue Client::RaisedOnDestroy
|
1078
|
+
end
|
1079
|
+
|
1080
|
+
assert_equal [good, bad], companies(:first_firm).clients_of_firm(true)
|
1081
|
+
end
|
1082
|
+
|
1083
|
+
def test_transaction_when_deleting_new_record
|
1084
|
+
assert_no_queries(ignore_none: false) do
|
1085
|
+
firm = Firm.new
|
1086
|
+
client = Client.new("name" => "New Client")
|
1087
|
+
firm.clients_of_firm << client
|
1088
|
+
firm.clients_of_firm.destroy(client)
|
1089
|
+
end
|
1090
|
+
end
|
1091
|
+
|
1092
|
+
def test_clearing_an_association_collection
|
1093
|
+
firm = companies(:first_firm)
|
1094
|
+
client_id = firm.clients_of_firm.first.id
|
1095
|
+
assert_equal 2, firm.clients_of_firm.size
|
1096
|
+
|
1097
|
+
firm.clients_of_firm.clear
|
1098
|
+
|
1099
|
+
assert_equal 0, firm.clients_of_firm.size
|
1100
|
+
assert_equal 0, firm.clients_of_firm(true).size
|
1101
|
+
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1102
|
+
|
1103
|
+
# Should not be destroyed since the association is not dependent.
|
1104
|
+
assert_nothing_raised do
|
1105
|
+
assert_nil Client.find(client_id).firm
|
1106
|
+
end
|
1107
|
+
end
|
1108
|
+
|
1109
|
+
def test_clearing_updates_counter_cache
|
1110
|
+
topic = Topic.first
|
1111
|
+
|
1112
|
+
assert_difference 'topic.reload.replies_count', -1 do
|
1113
|
+
topic.replies.clear
|
1114
|
+
end
|
1115
|
+
end
|
1116
|
+
|
1117
|
+
def test_clearing_updates_counter_cache_when_inverse_counter_cache_is_a_symbol_with_dependent_destroy
|
1118
|
+
car = Car.first
|
1119
|
+
car.engines.create!
|
1120
|
+
|
1121
|
+
assert_difference 'car.reload.engines_count', -1 do
|
1122
|
+
car.engines.clear
|
1123
|
+
end
|
1124
|
+
end
|
1125
|
+
|
1126
|
+
def test_clearing_a_dependent_association_collection
|
1127
|
+
firm = companies(:first_firm)
|
1128
|
+
client_id = firm.dependent_clients_of_firm.first.id
|
1129
|
+
assert_equal 2, firm.dependent_clients_of_firm.size
|
1130
|
+
assert_equal 1, Client.find_by_id(client_id).client_of
|
1131
|
+
|
1132
|
+
# :delete_all is called on each client since the dependent options is :destroy
|
1133
|
+
firm.dependent_clients_of_firm.clear
|
1134
|
+
|
1135
|
+
assert_equal 0, firm.dependent_clients_of_firm.size
|
1136
|
+
assert_equal 0, firm.dependent_clients_of_firm(true).size
|
1137
|
+
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1138
|
+
|
1139
|
+
# Should be destroyed since the association is dependent.
|
1140
|
+
assert_nil Client.find_by_id(client_id)
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
def test_delete_all_with_option_delete_all
|
1144
|
+
firm = companies(:first_firm)
|
1145
|
+
client_id = firm.dependent_clients_of_firm.first.id
|
1146
|
+
firm.dependent_clients_of_firm.delete_all(:delete_all)
|
1147
|
+
assert_nil Client.find_by_id(client_id)
|
1148
|
+
end
|
1149
|
+
|
1150
|
+
def test_delete_all_accepts_limited_parameters
|
1151
|
+
firm = companies(:first_firm)
|
1152
|
+
assert_raise(ArgumentError) do
|
1153
|
+
firm.dependent_clients_of_firm.delete_all(:destroy)
|
1154
|
+
end
|
1155
|
+
end
|
1156
|
+
|
1157
|
+
def test_clearing_an_exclusively_dependent_association_collection
|
1158
|
+
firm = companies(:first_firm)
|
1159
|
+
client_id = firm.exclusively_dependent_clients_of_firm.first.id
|
1160
|
+
assert_equal 2, firm.exclusively_dependent_clients_of_firm.size
|
1161
|
+
|
1162
|
+
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1163
|
+
|
1164
|
+
# :exclusively_dependent means each client is deleted directly from
|
1165
|
+
# the database without looping through them calling destroy.
|
1166
|
+
firm.exclusively_dependent_clients_of_firm.clear
|
1167
|
+
|
1168
|
+
assert_equal 0, firm.exclusively_dependent_clients_of_firm.size
|
1169
|
+
assert_equal 0, firm.exclusively_dependent_clients_of_firm(true).size
|
1170
|
+
# no destroy-filters should have been called
|
1171
|
+
assert_equal [], Client.destroyed_client_ids[firm.id]
|
1172
|
+
|
1173
|
+
# Should be destroyed since the association is exclusively dependent.
|
1174
|
+
assert_nil Client.find_by_id(client_id)
|
1175
|
+
end
|
1176
|
+
|
1177
|
+
def test_dependent_association_respects_optional_conditions_on_delete
|
1178
|
+
firm = companies(:odegy)
|
1179
|
+
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
1180
|
+
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
1181
|
+
# only one of two clients is included in the association due to the :conditions key
|
1182
|
+
assert_equal 2, Client.where(client_of: firm.id).size
|
1183
|
+
assert_equal 1, firm.dependent_conditional_clients_of_firm.size
|
1184
|
+
firm.destroy
|
1185
|
+
# only the correctly associated client should have been deleted
|
1186
|
+
assert_equal 1, Client.where(client_of: firm.id).size
|
1187
|
+
end
|
1188
|
+
|
1189
|
+
def test_dependent_association_respects_optional_sanitized_conditions_on_delete
|
1190
|
+
firm = companies(:odegy)
|
1191
|
+
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
1192
|
+
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
1193
|
+
# only one of two clients is included in the association due to the :conditions key
|
1194
|
+
assert_equal 2, Client.where(client_of: firm.id).size
|
1195
|
+
assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
|
1196
|
+
firm.destroy
|
1197
|
+
# only the correctly associated client should have been deleted
|
1198
|
+
assert_equal 1, Client.where(client_of: firm.id).size
|
1199
|
+
end
|
1200
|
+
|
1201
|
+
def test_dependent_association_respects_optional_hash_conditions_on_delete
|
1202
|
+
firm = companies(:odegy)
|
1203
|
+
Client.create(:client_of => firm.id, :name => "BigShot Inc.")
|
1204
|
+
Client.create(:client_of => firm.id, :name => "SmallTime Inc.")
|
1205
|
+
# only one of two clients is included in the association due to the :conditions key
|
1206
|
+
assert_equal 2, Client.where(client_of: firm.id).size
|
1207
|
+
assert_equal 1, firm.dependent_sanitized_conditional_clients_of_firm.size
|
1208
|
+
firm.destroy
|
1209
|
+
# only the correctly associated client should have been deleted
|
1210
|
+
assert_equal 1, Client.where(client_of: firm.id).size
|
1211
|
+
end
|
1212
|
+
|
1213
|
+
def test_delete_all_association_with_primary_key_deletes_correct_records
|
1214
|
+
firm = Firm.first
|
1215
|
+
# break the vanilla firm_id foreign key
|
1216
|
+
assert_equal 3, firm.clients.count
|
1217
|
+
firm.clients.first.update_columns(firm_id: nil)
|
1218
|
+
assert_equal 2, firm.clients(true).count
|
1219
|
+
assert_equal 2, firm.clients_using_primary_key_with_delete_all.count
|
1220
|
+
old_record = firm.clients_using_primary_key_with_delete_all.first
|
1221
|
+
firm = Firm.first
|
1222
|
+
firm.destroy
|
1223
|
+
assert_nil Client.find_by_id(old_record.id)
|
1224
|
+
end
|
1225
|
+
|
1226
|
+
def test_creation_respects_hash_condition
|
1227
|
+
ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.build
|
1228
|
+
|
1229
|
+
assert ms_client.save
|
1230
|
+
assert_equal 'Microsoft', ms_client.name
|
1231
|
+
|
1232
|
+
another_ms_client = companies(:first_firm).clients_like_ms_with_hash_conditions.create
|
1233
|
+
|
1234
|
+
assert another_ms_client.persisted?
|
1235
|
+
assert_equal 'Microsoft', another_ms_client.name
|
1236
|
+
end
|
1237
|
+
|
1238
|
+
def test_clearing_without_initial_access
|
1239
|
+
firm = companies(:first_firm)
|
1240
|
+
|
1241
|
+
firm.clients_of_firm.clear
|
1242
|
+
|
1243
|
+
assert_equal 0, firm.clients_of_firm.size
|
1244
|
+
assert_equal 0, firm.clients_of_firm(true).size
|
1245
|
+
end
|
1246
|
+
|
1247
|
+
def test_deleting_a_item_which_is_not_in_the_collection
|
1248
|
+
force_signal37_to_load_all_clients_of_firm
|
1249
|
+
summit = Client.find_by_name('Summit')
|
1250
|
+
companies(:first_firm).clients_of_firm.delete(summit)
|
1251
|
+
assert_equal 2, companies(:first_firm).clients_of_firm.size
|
1252
|
+
assert_equal 2, companies(:first_firm).clients_of_firm(true).size
|
1253
|
+
assert_equal 2, summit.client_of
|
1254
|
+
end
|
1255
|
+
|
1256
|
+
def test_deleting_by_fixnum_id
|
1257
|
+
david = Developer.find(1)
|
1258
|
+
|
1259
|
+
assert_difference 'david.projects.count', -1 do
|
1260
|
+
assert_equal 1, david.projects.delete(1).size
|
1261
|
+
end
|
1262
|
+
|
1263
|
+
assert_equal 1, david.projects.size
|
1264
|
+
end
|
1265
|
+
|
1266
|
+
def test_deleting_by_string_id
|
1267
|
+
david = Developer.find(1)
|
1268
|
+
|
1269
|
+
assert_difference 'david.projects.count', -1 do
|
1270
|
+
assert_equal 1, david.projects.delete('1').size
|
1271
|
+
end
|
1272
|
+
|
1273
|
+
assert_equal 1, david.projects.size
|
1274
|
+
end
|
1275
|
+
|
1276
|
+
def test_deleting_self_type_mismatch
|
1277
|
+
david = Developer.find(1)
|
1278
|
+
david.projects.reload
|
1279
|
+
assert_raise(ActiveRecord::AssociationTypeMismatch) { david.projects.delete(Project.find(1).developers) }
|
1280
|
+
end
|
1281
|
+
|
1282
|
+
def test_destroying
|
1283
|
+
force_signal37_to_load_all_clients_of_firm
|
1284
|
+
|
1285
|
+
assert_difference "Client.count", -1 do
|
1286
|
+
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first)
|
1287
|
+
end
|
1288
|
+
|
1289
|
+
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1290
|
+
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1291
|
+
end
|
1292
|
+
|
1293
|
+
def test_destroying_by_fixnum_id
|
1294
|
+
force_signal37_to_load_all_clients_of_firm
|
1295
|
+
|
1296
|
+
assert_difference "Client.count", -1 do
|
1297
|
+
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id)
|
1298
|
+
end
|
1299
|
+
|
1300
|
+
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1301
|
+
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1302
|
+
end
|
1303
|
+
|
1304
|
+
def test_destroying_by_string_id
|
1305
|
+
force_signal37_to_load_all_clients_of_firm
|
1306
|
+
|
1307
|
+
assert_difference "Client.count", -1 do
|
1308
|
+
companies(:first_firm).clients_of_firm.destroy(companies(:first_firm).clients_of_firm.first.id.to_s)
|
1309
|
+
end
|
1310
|
+
|
1311
|
+
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1312
|
+
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1313
|
+
end
|
1314
|
+
|
1315
|
+
def test_destroying_a_collection
|
1316
|
+
force_signal37_to_load_all_clients_of_firm
|
1317
|
+
companies(:first_firm).clients_of_firm.create("name" => "Another Client")
|
1318
|
+
assert_equal 3, companies(:first_firm).clients_of_firm.size
|
1319
|
+
|
1320
|
+
assert_difference "Client.count", -2 do
|
1321
|
+
companies(:first_firm).clients_of_firm.destroy([companies(:first_firm).clients_of_firm[0], companies(:first_firm).clients_of_firm[1]])
|
1322
|
+
end
|
1323
|
+
|
1324
|
+
assert_equal 1, companies(:first_firm).reload.clients_of_firm.size
|
1325
|
+
assert_equal 1, companies(:first_firm).clients_of_firm(true).size
|
1326
|
+
end
|
1327
|
+
|
1328
|
+
def test_destroy_all
|
1329
|
+
force_signal37_to_load_all_clients_of_firm
|
1330
|
+
clients = companies(:first_firm).clients_of_firm.to_a
|
1331
|
+
assert !clients.empty?, "37signals has clients after load"
|
1332
|
+
destroyed = companies(:first_firm).clients_of_firm.destroy_all
|
1333
|
+
assert_equal clients.sort_by(&:id), destroyed.sort_by(&:id)
|
1334
|
+
assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
|
1335
|
+
assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
|
1336
|
+
assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
|
1337
|
+
end
|
1338
|
+
|
1339
|
+
def test_dependence
|
1340
|
+
firm = companies(:first_firm)
|
1341
|
+
assert_equal 3, firm.clients.size
|
1342
|
+
firm.destroy
|
1343
|
+
assert Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.empty?
|
1344
|
+
end
|
1345
|
+
|
1346
|
+
def test_dependence_for_associations_with_hash_condition
|
1347
|
+
david = authors(:david)
|
1348
|
+
assert_difference('Post.count', -1) { assert david.destroy }
|
1349
|
+
end
|
1350
|
+
|
1351
|
+
def test_destroy_dependent_when_deleted_from_association
|
1352
|
+
# sometimes tests on Oracle fail if ORDER BY is not provided therefore add always :order with :first
|
1353
|
+
firm = Firm.all.merge!(:order => "id").first
|
1354
|
+
assert_equal 3, firm.clients.size
|
1355
|
+
|
1356
|
+
client = firm.clients.first
|
1357
|
+
firm.clients.delete(client)
|
1358
|
+
|
1359
|
+
assert_raise(ActiveRecord::RecordNotFound) { Client.find(client.id) }
|
1360
|
+
assert_raise(ActiveRecord::RecordNotFound) { firm.clients.find(client.id) }
|
1361
|
+
assert_equal 2, firm.clients.size
|
1362
|
+
end
|
1363
|
+
|
1364
|
+
def test_three_levels_of_dependence
|
1365
|
+
topic = Topic.create "title" => "neat and simple"
|
1366
|
+
reply = topic.replies.create "title" => "neat and simple", "content" => "still digging it"
|
1367
|
+
reply.replies.create "title" => "neat and simple", "content" => "ain't complaining"
|
1368
|
+
|
1369
|
+
assert_nothing_raised { topic.destroy }
|
1370
|
+
end
|
1371
|
+
|
1372
|
+
uses_transaction :test_dependence_with_transaction_support_on_failure
|
1373
|
+
def test_dependence_with_transaction_support_on_failure
|
1374
|
+
firm = companies(:first_firm)
|
1375
|
+
clients = firm.clients
|
1376
|
+
assert_equal 3, clients.length
|
1377
|
+
clients.last.instance_eval { def overwrite_to_raise() raise "Trigger rollback" end }
|
1378
|
+
|
1379
|
+
firm.destroy rescue "do nothing"
|
1380
|
+
|
1381
|
+
assert_equal 3, Client.all.merge!(:where => "firm_id=#{firm.id}").to_a.size
|
1382
|
+
end
|
1383
|
+
|
1384
|
+
def test_dependence_on_account
|
1385
|
+
num_accounts = Account.count
|
1386
|
+
companies(:first_firm).destroy
|
1387
|
+
assert_equal num_accounts - 1, Account.count
|
1388
|
+
end
|
1389
|
+
|
1390
|
+
def test_depends_and_nullify
|
1391
|
+
num_accounts = Account.count
|
1392
|
+
|
1393
|
+
core = companies(:rails_core)
|
1394
|
+
assert_equal accounts(:rails_core_account), core.account
|
1395
|
+
assert_equal companies(:leetsoft, :jadedpixel), core.companies
|
1396
|
+
core.destroy
|
1397
|
+
assert_nil accounts(:rails_core_account).reload.firm_id
|
1398
|
+
assert_nil companies(:leetsoft).reload.client_of
|
1399
|
+
assert_nil companies(:jadedpixel).reload.client_of
|
1400
|
+
|
1401
|
+
assert_equal num_accounts, Account.count
|
1402
|
+
end
|
1403
|
+
|
1404
|
+
def test_restrict_with_exception
|
1405
|
+
firm = RestrictedWithExceptionFirm.create!(:name => 'restrict')
|
1406
|
+
firm.companies.create(:name => 'child')
|
1407
|
+
|
1408
|
+
assert !firm.companies.empty?
|
1409
|
+
assert_raise(ActiveRecord::DeleteRestrictionError) { firm.destroy }
|
1410
|
+
assert RestrictedWithExceptionFirm.exists?(:name => 'restrict')
|
1411
|
+
assert firm.companies.exists?(:name => 'child')
|
1412
|
+
end
|
1413
|
+
|
1414
|
+
def test_restrict_with_error
|
1415
|
+
firm = RestrictedWithErrorFirm.create!(:name => 'restrict')
|
1416
|
+
firm.companies.create(:name => 'child')
|
1417
|
+
|
1418
|
+
assert !firm.companies.empty?
|
1419
|
+
|
1420
|
+
firm.destroy
|
1421
|
+
|
1422
|
+
assert !firm.errors.empty?
|
1423
|
+
|
1424
|
+
assert_equal "Cannot delete record because dependent companies exist", firm.errors[:base].first
|
1425
|
+
assert RestrictedWithErrorFirm.exists?(:name => 'restrict')
|
1426
|
+
assert firm.companies.exists?(:name => 'child')
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
def test_included_in_collection
|
1430
|
+
assert_equal true, companies(:first_firm).clients.include?(Client.find(2))
|
1431
|
+
end
|
1432
|
+
|
1433
|
+
def test_included_in_collection_for_new_records
|
1434
|
+
client = Client.create(:name => 'Persisted')
|
1435
|
+
assert_nil client.client_of
|
1436
|
+
assert_equal false, Firm.new.clients_of_firm.include?(client),
|
1437
|
+
'includes a client that does not belong to any firm'
|
1438
|
+
end
|
1439
|
+
|
1440
|
+
def test_adding_array_and_collection
|
1441
|
+
assert_nothing_raised { Firm.first.clients + Firm.all.last.clients }
|
1442
|
+
end
|
1443
|
+
|
1444
|
+
def test_replace_with_less
|
1445
|
+
firm = Firm.all.merge!(:order => "id").first
|
1446
|
+
firm.clients = [companies(:first_client)]
|
1447
|
+
assert firm.save, "Could not save firm"
|
1448
|
+
firm.reload
|
1449
|
+
assert_equal 1, firm.clients.length
|
1450
|
+
end
|
1451
|
+
|
1452
|
+
def test_replace_with_less_and_dependent_nullify
|
1453
|
+
num_companies = Company.count
|
1454
|
+
companies(:rails_core).companies = []
|
1455
|
+
assert_equal num_companies, Company.count
|
1456
|
+
end
|
1457
|
+
|
1458
|
+
def test_replace_with_new
|
1459
|
+
firm = Firm.all.merge!(:order => "id").first
|
1460
|
+
firm.clients = [companies(:second_client), Client.new("name" => "New Client")]
|
1461
|
+
firm.save
|
1462
|
+
firm.reload
|
1463
|
+
assert_equal 2, firm.clients.length
|
1464
|
+
assert_equal false, firm.clients.include?(:first_client)
|
1465
|
+
end
|
1466
|
+
|
1467
|
+
def test_replace_failure
|
1468
|
+
firm = companies(:first_firm)
|
1469
|
+
account = Account.new
|
1470
|
+
orig_accounts = firm.accounts.to_a
|
1471
|
+
|
1472
|
+
assert !account.valid?
|
1473
|
+
assert !orig_accounts.empty?
|
1474
|
+
error = assert_raise ActiveRecord::RecordNotSaved do
|
1475
|
+
firm.accounts = [account]
|
1476
|
+
end
|
1477
|
+
|
1478
|
+
assert_equal orig_accounts, firm.accounts
|
1479
|
+
assert_equal "Failed to replace accounts because one or more of the " \
|
1480
|
+
"new records could not be saved.", error.message
|
1481
|
+
end
|
1482
|
+
|
1483
|
+
def test_replace_with_same_content
|
1484
|
+
firm = Firm.first
|
1485
|
+
firm.clients = []
|
1486
|
+
firm.save
|
1487
|
+
|
1488
|
+
assert_queries(0, ignore_none: true) do
|
1489
|
+
firm.clients = []
|
1490
|
+
end
|
1491
|
+
end
|
1492
|
+
|
1493
|
+
def test_transactions_when_replacing_on_persisted
|
1494
|
+
good = Client.new(:name => "Good")
|
1495
|
+
bad = Client.new(:name => "Bad", :raise_on_save => true)
|
1496
|
+
|
1497
|
+
companies(:first_firm).clients_of_firm = [good]
|
1498
|
+
|
1499
|
+
begin
|
1500
|
+
companies(:first_firm).clients_of_firm = [bad]
|
1501
|
+
rescue Client::RaisedOnSave
|
1502
|
+
end
|
1503
|
+
|
1504
|
+
assert_equal [good], companies(:first_firm).clients_of_firm(true)
|
1505
|
+
end
|
1506
|
+
|
1507
|
+
def test_transactions_when_replacing_on_new_record
|
1508
|
+
assert_no_queries(ignore_none: false) do
|
1509
|
+
firm = Firm.new
|
1510
|
+
firm.clients_of_firm = [Client.new("name" => "New Client")]
|
1511
|
+
end
|
1512
|
+
end
|
1513
|
+
|
1514
|
+
def test_get_ids
|
1515
|
+
assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], companies(:first_firm).client_ids
|
1516
|
+
end
|
1517
|
+
|
1518
|
+
def test_get_ids_for_loaded_associations
|
1519
|
+
company = companies(:first_firm)
|
1520
|
+
company.clients(true)
|
1521
|
+
assert_queries(0) do
|
1522
|
+
company.client_ids
|
1523
|
+
company.client_ids
|
1524
|
+
end
|
1525
|
+
end
|
1526
|
+
|
1527
|
+
def test_get_ids_for_unloaded_associations_does_not_load_them
|
1528
|
+
company = companies(:first_firm)
|
1529
|
+
assert !company.clients.loaded?
|
1530
|
+
assert_equal [companies(:first_client).id, companies(:second_client).id, companies(:another_first_firm_client).id], company.client_ids
|
1531
|
+
assert !company.clients.loaded?
|
1532
|
+
end
|
1533
|
+
|
1534
|
+
def test_get_ids_ignores_include_option
|
1535
|
+
assert_equal [readers(:michael_welcome).id], posts(:welcome).readers_with_person_ids
|
1536
|
+
end
|
1537
|
+
|
1538
|
+
def test_get_ids_for_ordered_association
|
1539
|
+
assert_equal [companies(:another_first_firm_client).id, companies(:second_client).id, companies(:first_client).id], companies(:first_firm).clients_ordered_by_name_ids
|
1540
|
+
end
|
1541
|
+
|
1542
|
+
def test_get_ids_for_association_on_new_record_does_not_try_to_find_records
|
1543
|
+
Company.columns # Load schema information so we don't query below
|
1544
|
+
Contract.columns # if running just this test.
|
1545
|
+
|
1546
|
+
company = Company.new
|
1547
|
+
assert_queries(0) do
|
1548
|
+
company.contract_ids
|
1549
|
+
end
|
1550
|
+
|
1551
|
+
assert_equal [], company.contract_ids
|
1552
|
+
end
|
1553
|
+
|
1554
|
+
def test_set_ids_for_association_on_new_record_applies_association_correctly
|
1555
|
+
contract_a = Contract.create!
|
1556
|
+
contract_b = Contract.create!
|
1557
|
+
Contract.create! # another contract
|
1558
|
+
company = Company.new(:name => "Some Company")
|
1559
|
+
|
1560
|
+
company.contract_ids = [contract_a.id, contract_b.id]
|
1561
|
+
assert_equal [contract_a.id, contract_b.id], company.contract_ids
|
1562
|
+
assert_equal [contract_a, contract_b], company.contracts
|
1563
|
+
|
1564
|
+
company.save!
|
1565
|
+
assert_equal company, contract_a.reload.company
|
1566
|
+
assert_equal company, contract_b.reload.company
|
1567
|
+
end
|
1568
|
+
|
1569
|
+
def test_assign_ids_ignoring_blanks
|
1570
|
+
firm = Firm.create!(:name => 'Apple')
|
1571
|
+
firm.client_ids = [companies(:first_client).id, nil, companies(:second_client).id, '']
|
1572
|
+
firm.save!
|
1573
|
+
|
1574
|
+
assert_equal 2, firm.clients(true).size
|
1575
|
+
assert_equal true, firm.clients.include?(companies(:second_client))
|
1576
|
+
end
|
1577
|
+
|
1578
|
+
def test_get_ids_for_through
|
1579
|
+
assert_equal [comments(:eager_other_comment1).id], authors(:mary).comment_ids
|
1580
|
+
end
|
1581
|
+
|
1582
|
+
def test_modifying_a_through_a_has_many_should_raise
|
1583
|
+
[
|
1584
|
+
lambda { authors(:mary).comment_ids = [comments(:greetings).id, comments(:more_greetings).id] },
|
1585
|
+
lambda { authors(:mary).comments = [comments(:greetings), comments(:more_greetings)] },
|
1586
|
+
lambda { authors(:mary).comments << Comment.create!(:body => "Yay", :post_id => 424242) },
|
1587
|
+
lambda { authors(:mary).comments.delete(authors(:mary).comments.first) },
|
1588
|
+
].each {|block| assert_raise(ActiveRecord::HasManyThroughCantAssociateThroughHasOneOrManyReflection, &block) }
|
1589
|
+
end
|
1590
|
+
|
1591
|
+
def test_dynamic_find_should_respect_association_order_for_through
|
1592
|
+
assert_equal Comment.find(10), authors(:david).comments_desc.where("comments.type = 'SpecialComment'").first
|
1593
|
+
assert_equal Comment.find(10), authors(:david).comments_desc.find_by_type('SpecialComment')
|
1594
|
+
end
|
1595
|
+
|
1596
|
+
def test_has_many_through_respects_hash_conditions
|
1597
|
+
assert_equal authors(:david).hello_posts, authors(:david).hello_posts_with_hash_conditions
|
1598
|
+
assert_equal authors(:david).hello_post_comments, authors(:david).hello_post_comments_with_hash_conditions
|
1599
|
+
end
|
1600
|
+
|
1601
|
+
def test_include_uses_array_include_after_loaded
|
1602
|
+
firm = companies(:first_firm)
|
1603
|
+
firm.clients.load_target
|
1604
|
+
|
1605
|
+
client = firm.clients.first
|
1606
|
+
|
1607
|
+
assert_no_queries do
|
1608
|
+
assert firm.clients.loaded?
|
1609
|
+
assert_equal true, firm.clients.include?(client)
|
1610
|
+
end
|
1611
|
+
end
|
1612
|
+
|
1613
|
+
def test_include_checks_if_record_exists_if_target_not_loaded
|
1614
|
+
firm = companies(:first_firm)
|
1615
|
+
client = firm.clients.first
|
1616
|
+
|
1617
|
+
firm.reload
|
1618
|
+
assert ! firm.clients.loaded?
|
1619
|
+
assert_queries(1) do
|
1620
|
+
assert_equal true, firm.clients.include?(client)
|
1621
|
+
end
|
1622
|
+
assert ! firm.clients.loaded?
|
1623
|
+
end
|
1624
|
+
|
1625
|
+
def test_include_returns_false_for_non_matching_record_to_verify_scoping
|
1626
|
+
firm = companies(:first_firm)
|
1627
|
+
client = Client.create!(:name => 'Not Associated')
|
1628
|
+
|
1629
|
+
assert ! firm.clients.loaded?
|
1630
|
+
assert_equal false, firm.clients.include?(client)
|
1631
|
+
end
|
1632
|
+
|
1633
|
+
def test_calling_first_nth_or_last_on_association_should_not_load_association
|
1634
|
+
firm = companies(:first_firm)
|
1635
|
+
firm.clients.first
|
1636
|
+
firm.clients.second
|
1637
|
+
firm.clients.last
|
1638
|
+
assert !firm.clients.loaded?
|
1639
|
+
end
|
1640
|
+
|
1641
|
+
def test_calling_first_or_last_on_loaded_association_should_not_fetch_with_query
|
1642
|
+
firm = companies(:first_firm)
|
1643
|
+
firm.clients.load_target
|
1644
|
+
assert firm.clients.loaded?
|
1645
|
+
|
1646
|
+
assert_no_queries(ignore_none: false) do
|
1647
|
+
firm.clients.first
|
1648
|
+
assert_equal 2, firm.clients.first(2).size
|
1649
|
+
firm.clients.last
|
1650
|
+
assert_equal 2, firm.clients.last(2).size
|
1651
|
+
end
|
1652
|
+
end
|
1653
|
+
|
1654
|
+
def test_calling_first_or_last_on_existing_record_with_build_should_load_association
|
1655
|
+
firm = companies(:first_firm)
|
1656
|
+
firm.clients.build(:name => 'Foo')
|
1657
|
+
assert !firm.clients.loaded?
|
1658
|
+
|
1659
|
+
assert_queries 1 do
|
1660
|
+
firm.clients.first
|
1661
|
+
firm.clients.second
|
1662
|
+
firm.clients.last
|
1663
|
+
end
|
1664
|
+
|
1665
|
+
assert firm.clients.loaded?
|
1666
|
+
end
|
1667
|
+
|
1668
|
+
def test_calling_first_nth_or_last_on_existing_record_with_create_should_not_load_association
|
1669
|
+
firm = companies(:first_firm)
|
1670
|
+
firm.clients.create(:name => 'Foo')
|
1671
|
+
assert !firm.clients.loaded?
|
1672
|
+
|
1673
|
+
assert_queries 3 do
|
1674
|
+
firm.clients.first
|
1675
|
+
firm.clients.second
|
1676
|
+
firm.clients.last
|
1677
|
+
end
|
1678
|
+
|
1679
|
+
assert !firm.clients.loaded?
|
1680
|
+
end
|
1681
|
+
|
1682
|
+
def test_calling_first_nth_or_last_on_new_record_should_not_run_queries
|
1683
|
+
firm = Firm.new
|
1684
|
+
|
1685
|
+
assert_no_queries do
|
1686
|
+
firm.clients.first
|
1687
|
+
firm.clients.second
|
1688
|
+
firm.clients.last
|
1689
|
+
end
|
1690
|
+
end
|
1691
|
+
|
1692
|
+
def test_calling_first_or_last_with_integer_on_association_should_not_load_association
|
1693
|
+
firm = companies(:first_firm)
|
1694
|
+
firm.clients.create(:name => 'Foo')
|
1695
|
+
assert !firm.clients.loaded?
|
1696
|
+
|
1697
|
+
assert_queries 2 do
|
1698
|
+
firm.clients.first(2)
|
1699
|
+
firm.clients.last(2)
|
1700
|
+
end
|
1701
|
+
|
1702
|
+
assert !firm.clients.loaded?
|
1703
|
+
end
|
1704
|
+
|
1705
|
+
def test_calling_many_should_count_instead_of_loading_association
|
1706
|
+
firm = companies(:first_firm)
|
1707
|
+
assert_queries(1) do
|
1708
|
+
firm.clients.many? # use count query
|
1709
|
+
end
|
1710
|
+
assert !firm.clients.loaded?
|
1711
|
+
end
|
1712
|
+
|
1713
|
+
def test_calling_many_on_loaded_association_should_not_use_query
|
1714
|
+
firm = companies(:first_firm)
|
1715
|
+
firm.clients.collect # force load
|
1716
|
+
assert_no_queries { assert firm.clients.many? }
|
1717
|
+
end
|
1718
|
+
|
1719
|
+
def test_calling_many_should_defer_to_collection_if_using_a_block
|
1720
|
+
firm = companies(:first_firm)
|
1721
|
+
assert_queries(1) do
|
1722
|
+
firm.clients.expects(:size).never
|
1723
|
+
firm.clients.many? { true }
|
1724
|
+
end
|
1725
|
+
assert firm.clients.loaded?
|
1726
|
+
end
|
1727
|
+
|
1728
|
+
def test_calling_many_should_return_false_if_none_or_one
|
1729
|
+
firm = companies(:another_firm)
|
1730
|
+
assert !firm.clients_like_ms.many?
|
1731
|
+
assert_equal 0, firm.clients_like_ms.size
|
1732
|
+
|
1733
|
+
firm = companies(:first_firm)
|
1734
|
+
assert !firm.limited_clients.many?
|
1735
|
+
assert_equal 1, firm.limited_clients.size
|
1736
|
+
end
|
1737
|
+
|
1738
|
+
def test_calling_many_should_return_true_if_more_than_one
|
1739
|
+
firm = companies(:first_firm)
|
1740
|
+
assert firm.clients.many?
|
1741
|
+
assert_equal 3, firm.clients.size
|
1742
|
+
end
|
1743
|
+
|
1744
|
+
def test_joins_with_namespaced_model_should_use_correct_type
|
1745
|
+
old = ActiveRecord::Base.store_full_sti_class
|
1746
|
+
ActiveRecord::Base.store_full_sti_class = true
|
1747
|
+
|
1748
|
+
firm = Namespaced::Firm.create({ :name => 'Some Company' })
|
1749
|
+
firm.clients.create({ :name => 'Some Client' })
|
1750
|
+
|
1751
|
+
stats = Namespaced::Firm.all.merge!(
|
1752
|
+
:select => "#{Namespaced::Firm.table_name}.id, COUNT(#{Namespaced::Client.table_name}.id) AS num_clients",
|
1753
|
+
:joins => :clients,
|
1754
|
+
:group => "#{Namespaced::Firm.table_name}.id"
|
1755
|
+
).find firm.id
|
1756
|
+
assert_equal 1, stats.num_clients.to_i
|
1757
|
+
ensure
|
1758
|
+
ActiveRecord::Base.store_full_sti_class = old
|
1759
|
+
end
|
1760
|
+
|
1761
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
1762
|
+
Comment.expects(:transaction)
|
1763
|
+
Post.first.comments.transaction do
|
1764
|
+
# nothing
|
1765
|
+
end
|
1766
|
+
end
|
1767
|
+
|
1768
|
+
def test_sending_new_to_association_proxy_should_have_same_effect_as_calling_new
|
1769
|
+
client_association = companies(:first_firm).clients
|
1770
|
+
assert_equal client_association.new.attributes, client_association.send(:new).attributes
|
1771
|
+
end
|
1772
|
+
|
1773
|
+
def test_respond_to_private_class_methods
|
1774
|
+
client_association = companies(:first_firm).clients
|
1775
|
+
assert !client_association.respond_to?(:private_method)
|
1776
|
+
assert client_association.respond_to?(:private_method, true)
|
1777
|
+
end
|
1778
|
+
|
1779
|
+
def test_creating_using_primary_key
|
1780
|
+
firm = Firm.all.merge!(:order => "id").first
|
1781
|
+
client = firm.clients_using_primary_key.create!(:name => 'test')
|
1782
|
+
assert_equal firm.name, client.firm_name
|
1783
|
+
end
|
1784
|
+
|
1785
|
+
def test_defining_has_many_association_with_delete_all_dependency_lazily_evaluates_target_class
|
1786
|
+
ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
|
1787
|
+
class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
1788
|
+
class DeleteAllModel < ActiveRecord::Base
|
1789
|
+
has_many :nonentities, :dependent => :delete_all
|
1790
|
+
end
|
1791
|
+
EOF
|
1792
|
+
end
|
1793
|
+
|
1794
|
+
def test_defining_has_many_association_with_nullify_dependency_lazily_evaluates_target_class
|
1795
|
+
ActiveRecord::Reflection::AssociationReflection.any_instance.expects(:class_name).never
|
1796
|
+
class_eval(<<-EOF, __FILE__, __LINE__ + 1)
|
1797
|
+
class NullifyModel < ActiveRecord::Base
|
1798
|
+
has_many :nonentities, :dependent => :nullify
|
1799
|
+
end
|
1800
|
+
EOF
|
1801
|
+
end
|
1802
|
+
|
1803
|
+
def test_attributes_are_being_set_when_initialized_from_has_many_association_with_where_clause
|
1804
|
+
new_comment = posts(:welcome).comments.where(:body => "Some content").build
|
1805
|
+
assert_equal new_comment.body, "Some content"
|
1806
|
+
end
|
1807
|
+
|
1808
|
+
def test_attributes_are_being_set_when_initialized_from_has_many_association_with_multiple_where_clauses
|
1809
|
+
new_comment = posts(:welcome).comments.where(:body => "Some content").where(:type => 'SpecialComment').build
|
1810
|
+
assert_equal new_comment.body, "Some content"
|
1811
|
+
assert_equal new_comment.type, "SpecialComment"
|
1812
|
+
assert_equal new_comment.post_id, posts(:welcome).id
|
1813
|
+
end
|
1814
|
+
|
1815
|
+
def test_include_method_in_has_many_association_should_return_true_for_instance_added_with_build
|
1816
|
+
post = Post.new
|
1817
|
+
comment = post.comments.build
|
1818
|
+
assert_equal true, post.comments.include?(comment)
|
1819
|
+
end
|
1820
|
+
|
1821
|
+
def test_load_target_respects_protected_attributes
|
1822
|
+
topic = Topic.create!
|
1823
|
+
reply = topic.replies.create(:title => "reply 1")
|
1824
|
+
reply.approved = false
|
1825
|
+
reply.save!
|
1826
|
+
|
1827
|
+
# Save with a different object instance, so the instance that's still held
|
1828
|
+
# in topic.relies doesn't know about the changed attribute.
|
1829
|
+
reply2 = Reply.find(reply.id)
|
1830
|
+
reply2.approved = true
|
1831
|
+
reply2.save!
|
1832
|
+
|
1833
|
+
# Force loading the collection from the db. This will merge the existing
|
1834
|
+
# object (reply) with what gets loaded from the db (which includes the
|
1835
|
+
# changed approved attribute). approved is a protected attribute, so if mass
|
1836
|
+
# assignment is used, it won't get updated and will still be false.
|
1837
|
+
first = topic.replies.to_a.first
|
1838
|
+
assert_equal reply.id, first.id
|
1839
|
+
assert_equal true, first.approved?
|
1840
|
+
end
|
1841
|
+
|
1842
|
+
def test_to_a_should_dup_target
|
1843
|
+
ary = topics(:first).replies.to_a
|
1844
|
+
target = topics(:first).replies.target
|
1845
|
+
|
1846
|
+
assert_not_equal target.object_id, ary.object_id
|
1847
|
+
end
|
1848
|
+
|
1849
|
+
def test_merging_with_custom_attribute_writer
|
1850
|
+
bulb = Bulb.new(:color => "red")
|
1851
|
+
assert_equal "RED!", bulb.color
|
1852
|
+
|
1853
|
+
car = Car.create!
|
1854
|
+
car.bulbs << bulb
|
1855
|
+
|
1856
|
+
assert_equal "RED!", car.bulbs.to_a.first.color
|
1857
|
+
end
|
1858
|
+
|
1859
|
+
def test_abstract_class_with_polymorphic_has_many
|
1860
|
+
post = SubStiPost.create! :title => "fooo", :body => "baa"
|
1861
|
+
tagging = Tagging.create! :taggable => post
|
1862
|
+
assert_equal [tagging], post.taggings
|
1863
|
+
end
|
1864
|
+
|
1865
|
+
def test_with_polymorphic_has_many_with_custom_columns_name
|
1866
|
+
post = Post.create! :title => 'foo', :body => 'bar'
|
1867
|
+
image = Image.create!
|
1868
|
+
|
1869
|
+
post.images << image
|
1870
|
+
|
1871
|
+
assert_equal [image], post.images
|
1872
|
+
end
|
1873
|
+
|
1874
|
+
def test_build_with_polymorphic_has_many_does_not_allow_to_override_type_and_id
|
1875
|
+
welcome = posts(:welcome)
|
1876
|
+
tagging = welcome.taggings.build(:taggable_id => 99, :taggable_type => 'ShouldNotChange')
|
1877
|
+
|
1878
|
+
assert_equal welcome.id, tagging.taggable_id
|
1879
|
+
assert_equal 'Post', tagging.taggable_type
|
1880
|
+
end
|
1881
|
+
|
1882
|
+
def test_dont_call_save_callbacks_twice_on_has_many
|
1883
|
+
firm = companies(:first_firm)
|
1884
|
+
contract = firm.contracts.create!
|
1885
|
+
|
1886
|
+
assert_equal 1, contract.hi_count
|
1887
|
+
assert_equal 1, contract.bye_count
|
1888
|
+
end
|
1889
|
+
|
1890
|
+
def test_association_attributes_are_available_to_after_initialize
|
1891
|
+
car = Car.create(:name => 'honda')
|
1892
|
+
bulb = car.bulbs.build
|
1893
|
+
|
1894
|
+
assert_equal car.id, bulb.attributes_after_initialize['car_id']
|
1895
|
+
end
|
1896
|
+
|
1897
|
+
def test_attributes_are_set_when_initialized_from_has_many_null_relationship
|
1898
|
+
car = Car.new name: 'honda'
|
1899
|
+
bulb = car.bulbs.where(name: 'headlight').first_or_initialize
|
1900
|
+
assert_equal 'headlight', bulb.name
|
1901
|
+
end
|
1902
|
+
|
1903
|
+
def test_attributes_are_set_when_initialized_from_polymorphic_has_many_null_relationship
|
1904
|
+
post = Post.new title: 'title', body: 'bar'
|
1905
|
+
tag = Tag.create!(name: 'foo')
|
1906
|
+
|
1907
|
+
tagging = post.taggings.where(tag: tag).first_or_initialize
|
1908
|
+
|
1909
|
+
assert_equal tag.id, tagging.tag_id
|
1910
|
+
assert_equal 'Post', tagging.taggable_type
|
1911
|
+
end
|
1912
|
+
|
1913
|
+
def test_replace
|
1914
|
+
car = Car.create(:name => 'honda')
|
1915
|
+
bulb1 = car.bulbs.create
|
1916
|
+
bulb2 = Bulb.create
|
1917
|
+
|
1918
|
+
assert_equal [bulb1], car.bulbs
|
1919
|
+
car.bulbs.replace([bulb2])
|
1920
|
+
assert_equal [bulb2], car.bulbs
|
1921
|
+
assert_equal [bulb2], car.reload.bulbs
|
1922
|
+
end
|
1923
|
+
|
1924
|
+
def test_replace_returns_target
|
1925
|
+
car = Car.create(:name => 'honda')
|
1926
|
+
bulb1 = car.bulbs.create
|
1927
|
+
bulb2 = car.bulbs.create
|
1928
|
+
bulb3 = Bulb.create
|
1929
|
+
|
1930
|
+
assert_equal [bulb1, bulb2], car.bulbs
|
1931
|
+
result = car.bulbs.replace([bulb3, bulb1])
|
1932
|
+
assert_equal [bulb1, bulb3], car.bulbs
|
1933
|
+
assert_equal [bulb1, bulb3], result
|
1934
|
+
end
|
1935
|
+
|
1936
|
+
def test_collection_association_with_private_kernel_method
|
1937
|
+
firm = companies(:first_firm)
|
1938
|
+
assert_equal [accounts(:signals37)], firm.accounts.open
|
1939
|
+
end
|
1940
|
+
|
1941
|
+
test "first_or_initialize adds the record to the association" do
|
1942
|
+
firm = Firm.create! name: 'omg'
|
1943
|
+
client = firm.clients_of_firm.first_or_initialize
|
1944
|
+
assert_equal [client], firm.clients_of_firm
|
1945
|
+
end
|
1946
|
+
|
1947
|
+
test "first_or_create adds the record to the association" do
|
1948
|
+
firm = Firm.create! name: 'omg'
|
1949
|
+
firm.clients_of_firm.load_target
|
1950
|
+
client = firm.clients_of_firm.first_or_create name: 'lol'
|
1951
|
+
assert_equal [client], firm.clients_of_firm
|
1952
|
+
assert_equal [client], firm.reload.clients_of_firm
|
1953
|
+
end
|
1954
|
+
|
1955
|
+
test "delete_all, when not loaded, doesn't load the records" do
|
1956
|
+
post = posts(:welcome)
|
1957
|
+
|
1958
|
+
assert post.taggings_with_delete_all.count > 0
|
1959
|
+
assert !post.taggings_with_delete_all.loaded?
|
1960
|
+
|
1961
|
+
# 2 queries: one DELETE and another to update the counter cache
|
1962
|
+
assert_queries(2) do
|
1963
|
+
post.taggings_with_delete_all.delete_all
|
1964
|
+
end
|
1965
|
+
end
|
1966
|
+
|
1967
|
+
test "has many associations on new records use null relations" do
|
1968
|
+
post = Post.new
|
1969
|
+
|
1970
|
+
assert_no_queries(ignore_none: false) do
|
1971
|
+
assert_equal [], post.comments
|
1972
|
+
assert_equal [], post.comments.where(body: 'omg')
|
1973
|
+
assert_equal [], post.comments.pluck(:body)
|
1974
|
+
assert_equal 0, post.comments.sum(:id)
|
1975
|
+
assert_equal 0, post.comments.count
|
1976
|
+
end
|
1977
|
+
end
|
1978
|
+
|
1979
|
+
test "collection proxy respects default scope" do
|
1980
|
+
author = authors(:mary)
|
1981
|
+
assert !author.first_posts.exists?
|
1982
|
+
end
|
1983
|
+
|
1984
|
+
test "association with extend option" do
|
1985
|
+
post = posts(:welcome)
|
1986
|
+
assert_equal "lifo", post.comments_with_extend.author
|
1987
|
+
assert_equal "hello", post.comments_with_extend.greeting
|
1988
|
+
end
|
1989
|
+
|
1990
|
+
test "association with extend option with multiple extensions" do
|
1991
|
+
post = posts(:welcome)
|
1992
|
+
assert_equal "lifo", post.comments_with_extend_2.author
|
1993
|
+
assert_equal "hello", post.comments_with_extend_2.greeting
|
1994
|
+
end
|
1995
|
+
|
1996
|
+
test "delete record with complex joins" do
|
1997
|
+
david = authors(:david)
|
1998
|
+
|
1999
|
+
post = david.posts.first
|
2000
|
+
post.type = 'PostWithSpecialCategorization'
|
2001
|
+
post.save
|
2002
|
+
|
2003
|
+
categorization = post.categorizations.first
|
2004
|
+
categorization.special = true
|
2005
|
+
categorization.save
|
2006
|
+
|
2007
|
+
assert_not_equal [], david.posts_with_special_categorizations
|
2008
|
+
david.posts_with_special_categorizations = []
|
2009
|
+
assert_equal [], david.posts_with_special_categorizations
|
2010
|
+
end
|
2011
|
+
|
2012
|
+
test "does not duplicate associations when used with natural primary keys" do
|
2013
|
+
speedometer = Speedometer.create!(id: '4')
|
2014
|
+
speedometer.minivans.create!(minivan_id: 'a-van-red' ,name: 'a van', color: 'red')
|
2015
|
+
|
2016
|
+
assert_equal 1, speedometer.minivans.to_a.size, "Only one association should be present:\n#{speedometer.minivans.to_a}"
|
2017
|
+
assert_equal 1, speedometer.reload.minivans.to_a.size
|
2018
|
+
end
|
2019
|
+
|
2020
|
+
test "can unscope the default scope of the associated model" do
|
2021
|
+
car = Car.create!
|
2022
|
+
bulb1 = Bulb.create! name: "defaulty", car: car
|
2023
|
+
bulb2 = Bulb.create! name: "other", car: car
|
2024
|
+
|
2025
|
+
assert_equal [bulb1], car.bulbs
|
2026
|
+
assert_equal [bulb1, bulb2], car.all_bulbs.sort_by(&:id)
|
2027
|
+
end
|
2028
|
+
|
2029
|
+
test "can unscope and where the default scope of the associated model" do
|
2030
|
+
Car.has_many :other_bulbs, -> { unscope(where: [:name]).where(name: 'other') }, class_name: "Bulb"
|
2031
|
+
car = Car.create!
|
2032
|
+
bulb1 = Bulb.create! name: "defaulty", car: car
|
2033
|
+
bulb2 = Bulb.create! name: "other", car: car
|
2034
|
+
|
2035
|
+
assert_equal [bulb1], car.bulbs
|
2036
|
+
assert_equal [bulb2], car.other_bulbs
|
2037
|
+
end
|
2038
|
+
|
2039
|
+
test "can rewhere the default scope of the associated model" do
|
2040
|
+
Car.has_many :old_bulbs, -> { rewhere(name: 'old') }, class_name: "Bulb"
|
2041
|
+
car = Car.create!
|
2042
|
+
bulb1 = Bulb.create! name: "defaulty", car: car
|
2043
|
+
bulb2 = Bulb.create! name: "old", car: car
|
2044
|
+
|
2045
|
+
assert_equal [bulb1], car.bulbs
|
2046
|
+
assert_equal [bulb2], car.old_bulbs
|
2047
|
+
end
|
2048
|
+
|
2049
|
+
test 'unscopes the default scope of associated model when used with include' do
|
2050
|
+
car = Car.create!
|
2051
|
+
bulb = Bulb.create! name: "other", car: car
|
2052
|
+
|
2053
|
+
assert_equal bulb, Car.find(car.id).all_bulbs.first
|
2054
|
+
assert_equal bulb, Car.includes(:all_bulbs).find(car.id).all_bulbs.first
|
2055
|
+
end
|
2056
|
+
|
2057
|
+
test "raises RecordNotDestroyed when replaced child can't be destroyed" do
|
2058
|
+
car = Car.create!
|
2059
|
+
original_child = FailedBulb.create!(car: car)
|
2060
|
+
|
2061
|
+
error = assert_raise(ActiveRecord::RecordNotDestroyed) do
|
2062
|
+
car.failed_bulbs = [FailedBulb.create!]
|
2063
|
+
end
|
2064
|
+
|
2065
|
+
assert_equal [original_child], car.reload.failed_bulbs
|
2066
|
+
assert_equal "Failed to destroy the record", error.message
|
2067
|
+
end
|
2068
|
+
|
2069
|
+
test 'updates counter cache when default scope is given' do
|
2070
|
+
topic = DefaultRejectedTopic.create approved: true
|
2071
|
+
|
2072
|
+
assert_difference "topic.reload.replies_count", 1 do
|
2073
|
+
topic.approved_replies.create!
|
2074
|
+
end
|
2075
|
+
end
|
2076
|
+
|
2077
|
+
test 'dangerous association name raises ArgumentError' do
|
2078
|
+
[:errors, 'errors', :save, 'save'].each do |name|
|
2079
|
+
assert_raises(ArgumentError, "Association #{name} should not be allowed") do
|
2080
|
+
Class.new(ActiveRecord::Base) do
|
2081
|
+
has_many name
|
2082
|
+
end
|
2083
|
+
end
|
2084
|
+
end
|
2085
|
+
end
|
2086
|
+
|
2087
|
+
test 'passes custom context validation to validate children' do
|
2088
|
+
pirate = FamousPirate.new
|
2089
|
+
pirate.famous_ships << ship = FamousShip.new
|
2090
|
+
|
2091
|
+
assert pirate.valid?
|
2092
|
+
assert_not pirate.valid?(:conference)
|
2093
|
+
assert_equal "can't be blank", ship.errors[:name].first
|
2094
|
+
end
|
2095
|
+
|
2096
|
+
test 'association with instance dependent scope' do
|
2097
|
+
bob = authors(:bob)
|
2098
|
+
Post.create!(title: "signed post by bob", body: "stuff", author: authors(:bob))
|
2099
|
+
Post.create!(title: "anonymous post", body: "more stuff", author: authors(:bob))
|
2100
|
+
assert_equal ["misc post by bob", "other post by bob",
|
2101
|
+
"signed post by bob"], bob.posts_with_signature.map(&:title).sort
|
2102
|
+
|
2103
|
+
assert_equal [], authors(:david).posts_with_signature.map(&:title)
|
2104
|
+
end
|
2105
|
+
|
2106
|
+
test 'associations autosaves when object is already persited' do
|
2107
|
+
bulb = Bulb.create!
|
2108
|
+
tyre = Tyre.create!
|
2109
|
+
|
2110
|
+
car = Car.create! do |c|
|
2111
|
+
c.bulbs << bulb
|
2112
|
+
c.tyres << tyre
|
2113
|
+
end
|
2114
|
+
|
2115
|
+
assert_equal 1, car.bulbs.count
|
2116
|
+
assert_equal 1, car.tyres.count
|
2117
|
+
end
|
2118
|
+
|
2119
|
+
test 'associations replace in memory when records have the same id' do
|
2120
|
+
bulb = Bulb.create!
|
2121
|
+
car = Car.create!(bulbs: [bulb])
|
2122
|
+
|
2123
|
+
new_bulb = Bulb.find(bulb.id)
|
2124
|
+
new_bulb.name = "foo"
|
2125
|
+
car.bulbs = [new_bulb]
|
2126
|
+
|
2127
|
+
assert_equal "foo", car.bulbs.first.name
|
2128
|
+
end
|
2129
|
+
|
2130
|
+
test 'in memory replacement executes no queries' do
|
2131
|
+
bulb = Bulb.create!
|
2132
|
+
car = Car.create!(bulbs: [bulb])
|
2133
|
+
|
2134
|
+
new_bulb = Bulb.find(bulb.id)
|
2135
|
+
|
2136
|
+
assert_no_queries do
|
2137
|
+
car.bulbs = [new_bulb]
|
2138
|
+
end
|
2139
|
+
end
|
2140
|
+
|
2141
|
+
test 'in memory replacements do not execute callbacks' do
|
2142
|
+
raise_after_add = false
|
2143
|
+
klass = Class.new(ActiveRecord::Base) do
|
2144
|
+
self.table_name = :cars
|
2145
|
+
has_many :bulbs, after_add: proc { raise if raise_after_add }
|
2146
|
+
|
2147
|
+
def self.name
|
2148
|
+
"Car"
|
2149
|
+
end
|
2150
|
+
end
|
2151
|
+
bulb = Bulb.create!
|
2152
|
+
car = klass.create!(bulbs: [bulb])
|
2153
|
+
|
2154
|
+
new_bulb = Bulb.find(bulb.id)
|
2155
|
+
raise_after_add = true
|
2156
|
+
|
2157
|
+
assert_nothing_raised do
|
2158
|
+
car.bulbs = [new_bulb]
|
2159
|
+
end
|
2160
|
+
end
|
2161
|
+
|
2162
|
+
test 'in memory replacements sets inverse instance' do
|
2163
|
+
bulb = Bulb.create!
|
2164
|
+
car = Car.create!(bulbs: [bulb])
|
2165
|
+
|
2166
|
+
new_bulb = Bulb.find(bulb.id)
|
2167
|
+
car.bulbs = [new_bulb]
|
2168
|
+
|
2169
|
+
assert_same car, new_bulb.car
|
2170
|
+
end
|
2171
|
+
|
2172
|
+
test 'in memory replacement maintains order' do
|
2173
|
+
first_bulb = Bulb.create!
|
2174
|
+
second_bulb = Bulb.create!
|
2175
|
+
car = Car.create!(bulbs: [first_bulb, second_bulb])
|
2176
|
+
|
2177
|
+
same_bulb = Bulb.find(first_bulb.id)
|
2178
|
+
car.bulbs = [second_bulb, same_bulb]
|
2179
|
+
|
2180
|
+
assert_equal [first_bulb, second_bulb], car.bulbs
|
2181
|
+
end
|
2182
|
+
end
|