shoulda-matchers 3.1.0 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/{MIT-LICENSE → LICENSE} +1 -1
- data/README.md +407 -232
- data/docs/errors/NonCaseSwappableValueError.md +2 -2
- data/lib/shoulda/matchers/action_controller/callback_matcher.rb +7 -80
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +4 -3
- data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
- data/lib/shoulda/matchers/action_controller/permit_matcher.rb +36 -30
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +8 -10
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +7 -9
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +18 -15
- data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +3 -2
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +3 -3
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +88 -29
- data/lib/shoulda/matchers/action_controller/route_params.rb +2 -2
- data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +4 -4
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -3
- data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
- data/lib/shoulda/matchers/action_controller.rb +2 -0
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -9
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +42 -39
- data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +52 -26
- data/lib/shoulda/matchers/active_model/helpers.rb +2 -2
- data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -30
- data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +2 -1
- data/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
- data/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
- data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
- data/lib/shoulda/matchers/active_model/qualifiers.rb +2 -0
- data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +30 -6
- data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +8 -3
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +31 -16
- data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +52 -16
- data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +137 -84
- data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +159 -46
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +130 -66
- data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +251 -24
- data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +12 -9
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +38 -6
- data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
- data/lib/shoulda/matchers/active_model/validator.rb +4 -9
- data/lib/shoulda/matchers/active_model.rb +3 -5
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +10 -7
- data/lib/shoulda/matchers/active_record/association_matcher.rb +386 -111
- data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
- data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
- data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +14 -15
- data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +30 -8
- data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +34 -11
- data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +69 -0
- data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
- data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +74 -0
- data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
- data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
- data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +458 -42
- data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +185 -0
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +63 -23
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +164 -48
- data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +106 -0
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +13 -11
- data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
- data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +18 -18
- data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
- data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
- data/lib/shoulda/matchers/active_record/uniqueness.rb +1 -1
- data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +430 -200
- data/lib/shoulda/matchers/active_record.rb +28 -20
- data/lib/shoulda/matchers/configuration.rb +12 -1
- data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
- data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
- data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
- data/lib/shoulda/matchers/doublespeak/object_double.rb +6 -2
- data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
- data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
- data/lib/shoulda/matchers/doublespeak.rb +2 -1
- data/lib/shoulda/matchers/error.rb +1 -1
- data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +109 -29
- data/lib/shoulda/matchers/independent.rb +2 -2
- data/lib/shoulda/matchers/integrations/configuration.rb +8 -4
- data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
- data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
- data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
- data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
- data/lib/shoulda/matchers/rails_shim.rb +172 -51
- data/lib/shoulda/matchers/routing.rb +2 -2
- data/lib/shoulda/matchers/util/word_wrap.rb +17 -12
- data/lib/shoulda/matchers/util.rb +39 -5
- data/lib/shoulda/matchers/version.rb +1 -1
- data/lib/shoulda/matchers/warn.rb +4 -3
- data/shoulda-matchers.gemspec +33 -15
- metadata +31 -338
- data/.gitignore +0 -12
- data/.hound.yml +0 -3
- data/.hound_config/ruby.yml +0 -12
- data/.travis.yml +0 -19
- data/.yardopts +0 -10
- data/Appraisals +0 -73
- data/CONTRIBUTING.md +0 -101
- data/Gemfile +0 -15
- data/Gemfile.lock +0 -70
- data/NEWS.md +0 -986
- data/Rakefile +0 -39
- data/custom_plan.rb +0 -88
- data/doc_config/gh-pages/index.html.erb +0 -9
- data/doc_config/yard/setup.rb +0 -22
- data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -5967
- data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +0 -12
- data/doc_config/yard/templates/default/fulldoc/html/css/global.css +0 -62
- data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +0 -69
- data/doc_config/yard/templates/default/fulldoc/html/css/style.css +0 -312
- data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -32
- data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +0 -1
- data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +0 -8
- data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -298
- data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +0 -1
- data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +0 -289
- data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +0 -6
- data/doc_config/yard/templates/default/fulldoc/html/setup.rb +0 -8
- data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +0 -14
- data/doc_config/yard/templates/default/layout/html/fonts.erb +0 -1
- data/doc_config/yard/templates/default/layout/html/footer.erb +0 -6
- data/doc_config/yard/templates/default/layout/html/layout.erb +0 -23
- data/doc_config/yard/templates/default/layout/html/search.erb +0 -13
- data/doc_config/yard/templates/default/layout/html/setup.rb +0 -40
- data/doc_config/yard/templates/default/method_details/html/source.erb +0 -10
- data/doc_config/yard/templates/default/module/html/box_info.erb +0 -31
- data/gemfiles/4.0.0.gemfile +0 -38
- data/gemfiles/4.0.0.gemfile.lock +0 -223
- data/gemfiles/4.0.1.gemfile +0 -38
- data/gemfiles/4.0.1.gemfile.lock +0 -225
- data/gemfiles/4.1.gemfile +0 -38
- data/gemfiles/4.1.gemfile.lock +0 -220
- data/gemfiles/4.2.gemfile +0 -38
- data/gemfiles/4.2.gemfile.lock +0 -243
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -159
- data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +0 -37
- data/script/SUPPORTED_VERSIONS +0 -1
- data/script/install_gems_in_all_appraisals +0 -14
- data/script/run_all_tests +0 -14
- data/script/update_gem_in_all_appraisals +0 -15
- data/script/update_gems_in_all_appraisals +0 -14
- data/spec/acceptance/active_model_integration_spec.rb +0 -23
- data/spec/acceptance/independent_matchers_spec.rb +0 -125
- data/spec/acceptance/multiple_libraries_integration_spec.rb +0 -55
- data/spec/acceptance/rails_integration_spec.rb +0 -156
- data/spec/acceptance_spec_helper.rb +0 -23
- data/spec/doublespeak_spec_helper.rb +0 -2
- data/spec/report_warnings.rb +0 -7
- data/spec/spec_helper.rb +0 -21
- data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +0 -133
- data/spec/support/acceptance/helpers/active_model_helpers.rb +0 -11
- data/spec/support/acceptance/helpers/array_helpers.rb +0 -13
- data/spec/support/acceptance/helpers/base_helpers.rb +0 -19
- data/spec/support/acceptance/helpers/command_helpers.rb +0 -55
- data/spec/support/acceptance/helpers/file_helpers.rb +0 -19
- data/spec/support/acceptance/helpers/gem_helpers.rb +0 -31
- data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -11
- data/spec/support/acceptance/helpers/n_unit_helpers.rb +0 -25
- data/spec/support/acceptance/helpers/pluralization_helpers.rb +0 -13
- data/spec/support/acceptance/helpers/rails_version_helpers.rb +0 -11
- data/spec/support/acceptance/helpers/rspec_helpers.rb +0 -24
- data/spec/support/acceptance/helpers/ruby_version_helpers.rb +0 -9
- data/spec/support/acceptance/helpers/step_helpers.rb +0 -127
- data/spec/support/acceptance/helpers.rb +0 -31
- data/spec/support/acceptance/matchers/have_output.rb +0 -31
- data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +0 -55
- data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +0 -103
- data/spec/support/tests/bundle.rb +0 -94
- data/spec/support/tests/command_runner.rb +0 -230
- data/spec/support/tests/current_bundle.rb +0 -61
- data/spec/support/tests/database.rb +0 -28
- data/spec/support/tests/database_adapters/postgresql.rb +0 -25
- data/spec/support/tests/database_adapters/sqlite3.rb +0 -26
- data/spec/support/tests/database_configuration.rb +0 -33
- data/spec/support/tests/database_configuration_registry.rb +0 -28
- data/spec/support/tests/filesystem.rb +0 -100
- data/spec/support/tests/version.rb +0 -45
- data/spec/support/unit/active_record/create_table.rb +0 -54
- data/spec/support/unit/attribute.rb +0 -47
- data/spec/support/unit/capture.rb +0 -40
- data/spec/support/unit/change_value.rb +0 -111
- data/spec/support/unit/create_model_arguments/basic.rb +0 -135
- data/spec/support/unit/create_model_arguments/has_many.rb +0 -15
- data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +0 -74
- data/spec/support/unit/helpers/active_model_helpers.rb +0 -27
- data/spec/support/unit/helpers/active_model_versions.rb +0 -28
- data/spec/support/unit/helpers/active_record_versions.rb +0 -24
- data/spec/support/unit/helpers/active_resource_builder.rb +0 -27
- data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +0 -15
- data/spec/support/unit/helpers/class_builder.rb +0 -90
- data/spec/support/unit/helpers/column_type_helpers.rb +0 -26
- data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +0 -17
- data/spec/support/unit/helpers/controller_builder.rb +0 -63
- data/spec/support/unit/helpers/database_helpers.rb +0 -20
- data/spec/support/unit/helpers/i18n_faker.rb +0 -15
- data/spec/support/unit/helpers/mailer_builder.rb +0 -12
- data/spec/support/unit/helpers/model_builder.rb +0 -114
- data/spec/support/unit/helpers/rails_versions.rb +0 -28
- data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +0 -44
- data/spec/support/unit/i18n.rb +0 -7
- data/spec/support/unit/load_environment.rb +0 -12
- data/spec/support/unit/matchers/deprecate.rb +0 -60
- data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +0 -51
- data/spec/support/unit/matchers/fail_with_message_matcher.rb +0 -62
- data/spec/support/unit/matchers/print_warning_including.rb +0 -59
- data/spec/support/unit/model_creation_strategies/active_model.rb +0 -111
- data/spec/support/unit/model_creation_strategies/active_record.rb +0 -77
- data/spec/support/unit/model_creators/active_model.rb +0 -39
- data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +0 -95
- data/spec/support/unit/model_creators/active_record/has_many.rb +0 -67
- data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +0 -42
- data/spec/support/unit/model_creators/active_record.rb +0 -43
- data/spec/support/unit/model_creators/basic.rb +0 -97
- data/spec/support/unit/model_creators.rb +0 -19
- data/spec/support/unit/rails_application.rb +0 -126
- data/spec/support/unit/record_builder_with_i18n_validation_message.rb +0 -69
- data/spec/support/unit/record_validating_confirmation_builder.rb +0 -51
- data/spec/support/unit/record_with_different_error_attribute_builder.rb +0 -92
- data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +0 -79
- data/spec/support/unit/shared_examples/numerical_submatcher.rb +0 -17
- data/spec/support/unit/shared_examples/set_session_or_flash.rb +0 -360
- data/spec/support/unit/validation_matcher_scenario.rb +0 -62
- data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +0 -82
- data/spec/unit/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +0 -28
- data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +0 -592
- data/spec/unit/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +0 -42
- data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +0 -76
- data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +0 -62
- data/spec/unit/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +0 -90
- data/spec/unit/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +0 -31
- data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -330
- data/spec/unit/shoulda/matchers/action_controller/route_params_spec.rb +0 -30
- data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +0 -67
- data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -17
- data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +0 -562
- data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -115
- data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +0 -823
- data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -86
- data/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +0 -20
- data/spec/unit/shoulda/matchers/active_model/helpers_spec.rb +0 -162
- data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +0 -266
- data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +0 -91
- data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -149
- data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -207
- data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -1015
- data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -288
- data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +0 -1837
- data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -380
- data/spec/unit/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -107
- data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +0 -1242
- data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +0 -251
- data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +0 -168
- data/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +0 -111
- data/spec/unit/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +0 -85
- data/spec/unit/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +0 -41
- data/spec/unit/shoulda/matchers/active_record/serialize_matcher_spec.rb +0 -86
- data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +0 -1418
- data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +0 -190
- data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +0 -21
- data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +0 -271
- data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +0 -77
- data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +0 -72
- data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +0 -101
- data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +0 -80
- data/spec/unit/shoulda/matchers/doublespeak_spec.rb +0 -27
- data/spec/unit/shoulda/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +0 -43
- data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -517
- data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +0 -242
- data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +0 -252
- data/spec/unit_spec_helper.rb +0 -46
- data/spec/warnings_spy/filesystem.rb +0 -45
- data/spec/warnings_spy/partitioner.rb +0 -36
- data/spec/warnings_spy/reader.rb +0 -53
- data/spec/warnings_spy/reporter.rb +0 -88
- data/spec/warnings_spy.rb +0 -64
- data/tasks/documentation.rb +0 -199
- data/zeus.json +0 -11
@@ -11,7 +11,7 @@ module Shoulda
|
|
11
11
|
# end
|
12
12
|
#
|
13
13
|
# # RSpec
|
14
|
-
# describe Person do
|
14
|
+
# RSpec.describe Person, type: :model do
|
15
15
|
# it { should belong_to(:organization) }
|
16
16
|
# end
|
17
17
|
#
|
@@ -28,7 +28,7 @@ module Shoulda
|
|
28
28
|
# end
|
29
29
|
#
|
30
30
|
# # RSpec
|
31
|
-
# describe Comment do
|
31
|
+
# RSpec.describe Comment, type: :model do
|
32
32
|
# it { should belong_to(:commentable) }
|
33
33
|
# end
|
34
34
|
#
|
@@ -49,7 +49,7 @@ module Shoulda
|
|
49
49
|
# end
|
50
50
|
#
|
51
51
|
# # RSpec
|
52
|
-
# describe Person do
|
52
|
+
# RSpec.describe Person, type: :model do
|
53
53
|
# it do
|
54
54
|
# should belong_to(:family).
|
55
55
|
# conditions(everyone_is_perfect: false)
|
@@ -72,7 +72,7 @@ module Shoulda
|
|
72
72
|
# end
|
73
73
|
#
|
74
74
|
# # RSpec
|
75
|
-
# describe Person do
|
75
|
+
# RSpec.describe Person, type: :model do
|
76
76
|
# it { should belong_to(:previous_company).order('hired_on desc') }
|
77
77
|
# end
|
78
78
|
#
|
@@ -91,7 +91,7 @@ module Shoulda
|
|
91
91
|
# end
|
92
92
|
#
|
93
93
|
# # RSpec
|
94
|
-
# describe Person do
|
94
|
+
# RSpec.describe Person, type: :model do
|
95
95
|
# it { should belong_to(:ancient_city).class_name('City') }
|
96
96
|
# end
|
97
97
|
#
|
@@ -109,7 +109,7 @@ module Shoulda
|
|
109
109
|
# end
|
110
110
|
#
|
111
111
|
# # RSpec
|
112
|
-
# describe Person do
|
112
|
+
# RSpec.describe Person, type: :model do
|
113
113
|
# it do
|
114
114
|
# should belong_to(:great_country).
|
115
115
|
# with_primary_key('country_id')
|
@@ -131,7 +131,7 @@ module Shoulda
|
|
131
131
|
# end
|
132
132
|
#
|
133
133
|
# # RSpec
|
134
|
-
# describe Person do
|
134
|
+
# RSpec.describe Person, type: :model do
|
135
135
|
# it do
|
136
136
|
# should belong_to(:great_country).
|
137
137
|
# with_foreign_key('country_id')
|
@@ -153,7 +153,7 @@ module Shoulda
|
|
153
153
|
# end
|
154
154
|
#
|
155
155
|
# # RSpec
|
156
|
-
# describe Person do
|
156
|
+
# RSpec.describe Person, type: :model do
|
157
157
|
# it { should belong_to(:world).dependent(:destroy) }
|
158
158
|
# end
|
159
159
|
#
|
@@ -165,7 +165,7 @@ module Shoulda
|
|
165
165
|
# To assert that *any* `:dependent` option was specified, use `true`:
|
166
166
|
#
|
167
167
|
# # RSpec
|
168
|
-
# describe Person do
|
168
|
+
# RSpec.describe Person, type: :model do
|
169
169
|
# it { should belong_to(:world).dependent(true) }
|
170
170
|
# end
|
171
171
|
#
|
@@ -176,7 +176,7 @@ module Shoulda
|
|
176
176
|
# end
|
177
177
|
#
|
178
178
|
# # RSpec
|
179
|
-
# describe Person do
|
179
|
+
# RSpec.describe Person, type: :model do
|
180
180
|
# it { should belong_to(:company).dependent(false) }
|
181
181
|
# end
|
182
182
|
#
|
@@ -190,7 +190,7 @@ module Shoulda
|
|
190
190
|
# end
|
191
191
|
#
|
192
192
|
# # RSpec
|
193
|
-
# describe Person do
|
193
|
+
# RSpec.describe Person, type: :model do
|
194
194
|
# it { should belong_to(:organization).counter_cache(true) }
|
195
195
|
# end
|
196
196
|
#
|
@@ -208,7 +208,7 @@ module Shoulda
|
|
208
208
|
# end
|
209
209
|
#
|
210
210
|
# # RSpec
|
211
|
-
# describe Person do
|
211
|
+
# RSpec.describe Person, type: :model do
|
212
212
|
# it { should belong_to(:organization).touch(true) }
|
213
213
|
# end
|
214
214
|
#
|
@@ -217,7 +217,7 @@ module Shoulda
|
|
217
217
|
# should belong_to(:organization).touch(true)
|
218
218
|
# end
|
219
219
|
#
|
220
|
-
#
|
220
|
+
# ##### autosave
|
221
221
|
#
|
222
222
|
# Use `autosave` to assert that the `:autosave` option was specified.
|
223
223
|
#
|
@@ -226,7 +226,7 @@ module Shoulda
|
|
226
226
|
# end
|
227
227
|
#
|
228
228
|
# # RSpec
|
229
|
-
# describe Account do
|
229
|
+
# RSpec.describe Account, type: :model do
|
230
230
|
# it { should belong_to(:bank).autosave(true) }
|
231
231
|
# end
|
232
232
|
#
|
@@ -253,6 +253,73 @@ module Shoulda
|
|
253
253
|
# should belong_to(:organization).inverse_of(:employees)
|
254
254
|
# end
|
255
255
|
#
|
256
|
+
# ##### required
|
257
|
+
#
|
258
|
+
# Use `required` to assert that the association is not allowed to be nil.
|
259
|
+
# (Enabled by default in Rails 5+.)
|
260
|
+
#
|
261
|
+
# class Person < ActiveRecord::Base
|
262
|
+
# belongs_to :organization, required: true
|
263
|
+
# end
|
264
|
+
#
|
265
|
+
# # RSpec
|
266
|
+
# describe Person
|
267
|
+
# it { should belong_to(:organization).required }
|
268
|
+
# end
|
269
|
+
#
|
270
|
+
# # Minitest (Shoulda)
|
271
|
+
# class PersonTest < ActiveSupport::TestCase
|
272
|
+
# should belong_to(:organization).required
|
273
|
+
# end
|
274
|
+
#
|
275
|
+
# ##### without_validating_presence
|
276
|
+
#
|
277
|
+
# Use `without_validating_presence` with `belong_to` to prevent the
|
278
|
+
# matcher from checking whether the association disallows nil (Rails 5+
|
279
|
+
# only). This can be helpful if you have a custom hook that always sets
|
280
|
+
# the association to a meaningful value:
|
281
|
+
#
|
282
|
+
# class Person < ActiveRecord::Base
|
283
|
+
# belongs_to :organization
|
284
|
+
#
|
285
|
+
# before_validation :autoassign_organization
|
286
|
+
#
|
287
|
+
# private
|
288
|
+
#
|
289
|
+
# def autoassign_organization
|
290
|
+
# self.organization = Organization.create!
|
291
|
+
# end
|
292
|
+
# end
|
293
|
+
#
|
294
|
+
# # RSpec
|
295
|
+
# describe Person
|
296
|
+
# it { should belong_to(:organization).without_validating_presence }
|
297
|
+
# end
|
298
|
+
#
|
299
|
+
# # Minitest (Shoulda)
|
300
|
+
# class PersonTest < ActiveSupport::TestCase
|
301
|
+
# should belong_to(:organization).without_validating_presence
|
302
|
+
# end
|
303
|
+
#
|
304
|
+
# ##### optional
|
305
|
+
#
|
306
|
+
# Use `optional` to assert that the association is allowed to be nil.
|
307
|
+
# (Rails 5+ only.)
|
308
|
+
#
|
309
|
+
# class Person < ActiveRecord::Base
|
310
|
+
# belongs_to :organization, optional: true
|
311
|
+
# end
|
312
|
+
#
|
313
|
+
# # RSpec
|
314
|
+
# describe Person
|
315
|
+
# it { should belong_to(:organization).optional }
|
316
|
+
# end
|
317
|
+
#
|
318
|
+
# # Minitest (Shoulda)
|
319
|
+
# class PersonTest < ActiveSupport::TestCase
|
320
|
+
# should belong_to(:organization).optional
|
321
|
+
# end
|
322
|
+
#
|
256
323
|
# @return [AssociationMatcher]
|
257
324
|
#
|
258
325
|
def belong_to(name)
|
@@ -267,7 +334,7 @@ module Shoulda
|
|
267
334
|
# end
|
268
335
|
#
|
269
336
|
# # RSpec
|
270
|
-
# describe Person do
|
337
|
+
# RSpec.describe Person, type: :model do
|
271
338
|
# it { should have_many(:friends) }
|
272
339
|
# end
|
273
340
|
#
|
@@ -284,7 +351,7 @@ module Shoulda
|
|
284
351
|
# end
|
285
352
|
#
|
286
353
|
# # RSpec
|
287
|
-
# describe Person do
|
354
|
+
# RSpec.describe Person, type: :model do
|
288
355
|
# it { should have_many(:pictures) }
|
289
356
|
# end
|
290
357
|
#
|
@@ -305,7 +372,7 @@ module Shoulda
|
|
305
372
|
# end
|
306
373
|
#
|
307
374
|
# # RSpec
|
308
|
-
# describe Person do
|
375
|
+
# RSpec.describe Person, type: :model do
|
309
376
|
# it { should have_many(:coins).conditions(quality: 'mint') }
|
310
377
|
# end
|
311
378
|
#
|
@@ -324,7 +391,7 @@ module Shoulda
|
|
324
391
|
# end
|
325
392
|
#
|
326
393
|
# # RSpec
|
327
|
-
# describe Person do
|
394
|
+
# RSpec.describe Person, type: :model do
|
328
395
|
# it { should have_many(:shirts).order('color') }
|
329
396
|
# end
|
330
397
|
#
|
@@ -343,7 +410,7 @@ module Shoulda
|
|
343
410
|
# end
|
344
411
|
#
|
345
412
|
# # RSpec
|
346
|
-
# describe Person do
|
413
|
+
# RSpec.describe Person, type: :model do
|
347
414
|
# it { should have_many(:hopes).class_name('Dream') }
|
348
415
|
# end
|
349
416
|
#
|
@@ -361,7 +428,7 @@ module Shoulda
|
|
361
428
|
# end
|
362
429
|
#
|
363
430
|
# # RSpec
|
364
|
-
# describe Person do
|
431
|
+
# RSpec.describe Person, type: :model do
|
365
432
|
# it { should have_many(:worries).with_primary_key('worrier_id') }
|
366
433
|
# end
|
367
434
|
#
|
@@ -379,7 +446,7 @@ module Shoulda
|
|
379
446
|
# end
|
380
447
|
#
|
381
448
|
# # RSpec
|
382
|
-
# describe Person do
|
449
|
+
# RSpec.describe Person, type: :model do
|
383
450
|
# it { should have_many(:worries).with_foreign_key('worrier_id') }
|
384
451
|
# end
|
385
452
|
#
|
@@ -397,7 +464,7 @@ module Shoulda
|
|
397
464
|
# end
|
398
465
|
#
|
399
466
|
# # RSpec
|
400
|
-
# describe Person do
|
467
|
+
# RSpec.describe Person, type: :model do
|
401
468
|
# it { should have_many(:secret_documents).dependent(:destroy) }
|
402
469
|
# end
|
403
470
|
#
|
@@ -416,7 +483,7 @@ module Shoulda
|
|
416
483
|
# end
|
417
484
|
#
|
418
485
|
# # RSpec
|
419
|
-
# describe Person do
|
486
|
+
# RSpec.describe Person, type: :model do
|
420
487
|
# it { should have_many(:acquaintances).through(:friends) }
|
421
488
|
# end
|
422
489
|
#
|
@@ -435,7 +502,7 @@ module Shoulda
|
|
435
502
|
# end
|
436
503
|
#
|
437
504
|
# # RSpec
|
438
|
-
# describe Person do
|
505
|
+
# RSpec.describe Person, type: :model do
|
439
506
|
# it do
|
440
507
|
# should have_many(:job_offers).
|
441
508
|
# through(:friends).
|
@@ -459,7 +526,7 @@ module Shoulda
|
|
459
526
|
# end
|
460
527
|
#
|
461
528
|
# # RSpec
|
462
|
-
# describe Person do
|
529
|
+
# RSpec.describe Person, type: :model do
|
463
530
|
# it { should have_many(:ideas).validate(false) }
|
464
531
|
# end
|
465
532
|
#
|
@@ -468,7 +535,7 @@ module Shoulda
|
|
468
535
|
# should have_many(:ideas).validate(false)
|
469
536
|
# end
|
470
537
|
#
|
471
|
-
#
|
538
|
+
# ##### autosave
|
472
539
|
#
|
473
540
|
# Use `autosave` to assert that the `:autosave` option was specified.
|
474
541
|
#
|
@@ -477,7 +544,7 @@ module Shoulda
|
|
477
544
|
# end
|
478
545
|
#
|
479
546
|
# # RSpec
|
480
|
-
# describe Player do
|
547
|
+
# RSpec.describe Player, type: :model do
|
481
548
|
# it { should have_many(:games).autosave(true) }
|
482
549
|
# end
|
483
550
|
#
|
@@ -486,6 +553,43 @@ module Shoulda
|
|
486
553
|
# should have_many(:games).autosave(true)
|
487
554
|
# end
|
488
555
|
#
|
556
|
+
# ##### index_errors
|
557
|
+
#
|
558
|
+
# Use `index_errors` to assert that the `:index_errors` option was
|
559
|
+
# specified.
|
560
|
+
#
|
561
|
+
# class Player < ActiveRecord::Base
|
562
|
+
# has_many :games, index_errors: true
|
563
|
+
# end
|
564
|
+
#
|
565
|
+
# # RSpec
|
566
|
+
# RSpec.describe Player, type: :model do
|
567
|
+
# it { should have_many(:games).index_errors(true) }
|
568
|
+
# end
|
569
|
+
#
|
570
|
+
# # Minitest (Shoulda)
|
571
|
+
# class PlayerTest < ActiveSupport::TestCase
|
572
|
+
# should have_many(:games).index_errors(true)
|
573
|
+
# end
|
574
|
+
#
|
575
|
+
# ##### inverse_of
|
576
|
+
#
|
577
|
+
# Use `inverse_of` to assert that the `:inverse_of` option was specified.
|
578
|
+
#
|
579
|
+
# class Organization < ActiveRecord::Base
|
580
|
+
# has_many :employees, inverse_of: :company
|
581
|
+
# end
|
582
|
+
#
|
583
|
+
# # RSpec
|
584
|
+
# describe Organization
|
585
|
+
# it { should have_many(:employees).inverse_of(:company) }
|
586
|
+
# end
|
587
|
+
#
|
588
|
+
# # Minitest (Shoulda)
|
589
|
+
# class OrganizationTest < ActiveSupport::TestCase
|
590
|
+
# should have_many(:employees).inverse_of(:company)
|
591
|
+
# end
|
592
|
+
#
|
489
593
|
# @return [AssociationMatcher]
|
490
594
|
#
|
491
595
|
def have_many(name)
|
@@ -500,7 +604,7 @@ module Shoulda
|
|
500
604
|
# end
|
501
605
|
#
|
502
606
|
# # RSpec
|
503
|
-
# describe Person do
|
607
|
+
# RSpec.describe Person, type: :model do
|
504
608
|
# it { should have_one(:partner) }
|
505
609
|
# end
|
506
610
|
#
|
@@ -521,7 +625,7 @@ module Shoulda
|
|
521
625
|
# end
|
522
626
|
#
|
523
627
|
# # RSpec
|
524
|
-
# describe Person do
|
628
|
+
# RSpec.describe Person, type: :model do
|
525
629
|
# it { should have_one(:pet).conditions('weight < 80') }
|
526
630
|
# end
|
527
631
|
#
|
@@ -540,7 +644,7 @@ module Shoulda
|
|
540
644
|
# end
|
541
645
|
#
|
542
646
|
# # RSpec
|
543
|
-
# describe Person do
|
647
|
+
# RSpec.describe Person, type: :model do
|
544
648
|
# it { should have_one(:focus).order('priority desc') }
|
545
649
|
# end
|
546
650
|
#
|
@@ -559,7 +663,7 @@ module Shoulda
|
|
559
663
|
# end
|
560
664
|
#
|
561
665
|
# # RSpec
|
562
|
-
# describe Person do
|
666
|
+
# RSpec.describe Person, type: :model do
|
563
667
|
# it { should have_one(:chance).class_name('Opportunity') }
|
564
668
|
# end
|
565
669
|
#
|
@@ -577,7 +681,7 @@ module Shoulda
|
|
577
681
|
# end
|
578
682
|
#
|
579
683
|
# # RSpec
|
580
|
-
# describe Person do
|
684
|
+
# RSpec.describe Person, type: :model do
|
581
685
|
# it { should have_one(:contract).dependent(:nullify) }
|
582
686
|
# end
|
583
687
|
#
|
@@ -595,7 +699,7 @@ module Shoulda
|
|
595
699
|
# end
|
596
700
|
#
|
597
701
|
# # RSpec
|
598
|
-
# describe Person do
|
702
|
+
# RSpec.describe Person, type: :model do
|
599
703
|
# it { should have_one(:job).with_primary_key('worker_id') }
|
600
704
|
# end
|
601
705
|
#
|
@@ -613,7 +717,7 @@ module Shoulda
|
|
613
717
|
# end
|
614
718
|
#
|
615
719
|
# # RSpec
|
616
|
-
# describe Person do
|
720
|
+
# RSpec.describe Person, type: :model do
|
617
721
|
# it { should have_one(:job).with_foreign_key('worker_id') }
|
618
722
|
# end
|
619
723
|
#
|
@@ -632,7 +736,7 @@ module Shoulda
|
|
632
736
|
# end
|
633
737
|
#
|
634
738
|
# # RSpec
|
635
|
-
# describe Person do
|
739
|
+
# RSpec.describe Person, type: :model do
|
636
740
|
# it { should have_one(:life).through(:partner) }
|
637
741
|
# end
|
638
742
|
#
|
@@ -651,7 +755,7 @@ module Shoulda
|
|
651
755
|
# end
|
652
756
|
#
|
653
757
|
# # RSpec
|
654
|
-
# describe Person do
|
758
|
+
# RSpec.describe Person, type: :model do
|
655
759
|
# it { should have_one(:car).through(:partner).source(:vehicle) }
|
656
760
|
# end
|
657
761
|
#
|
@@ -669,7 +773,7 @@ module Shoulda
|
|
669
773
|
# end
|
670
774
|
#
|
671
775
|
# # RSpec
|
672
|
-
# describe Person do
|
776
|
+
# RSpec.describe Person, type: :model do
|
673
777
|
# it { should have_one(:parking_card).validate(false) }
|
674
778
|
# end
|
675
779
|
#
|
@@ -678,7 +782,7 @@ module Shoulda
|
|
678
782
|
# should have_one(:parking_card).validate(false)
|
679
783
|
# end
|
680
784
|
#
|
681
|
-
#
|
785
|
+
# ##### autosave
|
682
786
|
#
|
683
787
|
# Use `autosave` to assert that the `:autosave` option was specified.
|
684
788
|
#
|
@@ -687,7 +791,7 @@ module Shoulda
|
|
687
791
|
# end
|
688
792
|
#
|
689
793
|
# # RSpec
|
690
|
-
# describe Account do
|
794
|
+
# RSpec.describe Account, type: :model do
|
691
795
|
# it { should have_one(:bank).autosave(true) }
|
692
796
|
# end
|
693
797
|
#
|
@@ -696,6 +800,25 @@ module Shoulda
|
|
696
800
|
# should have_one(:bank).autosave(true)
|
697
801
|
# end
|
698
802
|
#
|
803
|
+
# ##### required
|
804
|
+
#
|
805
|
+
# Use `required` to assert that the association is not allowed to be nil.
|
806
|
+
# (Rails 5+ only.)
|
807
|
+
#
|
808
|
+
# class Person < ActiveRecord::Base
|
809
|
+
# has_one :brain, required: true
|
810
|
+
# end
|
811
|
+
#
|
812
|
+
# # RSpec
|
813
|
+
# describe Person
|
814
|
+
# it { should have_one(:brain).required }
|
815
|
+
# end
|
816
|
+
#
|
817
|
+
# # Minitest (Shoulda)
|
818
|
+
# class PersonTest < ActiveSupport::TestCase
|
819
|
+
# should have_one(:brain).required
|
820
|
+
# end
|
821
|
+
#
|
699
822
|
# @return [AssociationMatcher]
|
700
823
|
#
|
701
824
|
def have_one(name)
|
@@ -711,7 +834,7 @@ module Shoulda
|
|
711
834
|
# end
|
712
835
|
#
|
713
836
|
# # RSpec
|
714
|
-
# describe Person do
|
837
|
+
# RSpec.describe Person, type: :model do
|
715
838
|
# it { should have_and_belong_to_many(:awards) }
|
716
839
|
# end
|
717
840
|
#
|
@@ -732,7 +855,7 @@ module Shoulda
|
|
732
855
|
# end
|
733
856
|
#
|
734
857
|
# # RSpec
|
735
|
-
# describe Person do
|
858
|
+
# RSpec.describe Person, type: :model do
|
736
859
|
# it do
|
737
860
|
# should have_and_belong_to_many(:issues).
|
738
861
|
# conditions(difficulty: 'hard')
|
@@ -755,7 +878,7 @@ module Shoulda
|
|
755
878
|
# end
|
756
879
|
#
|
757
880
|
# # RSpec
|
758
|
-
# describe Person do
|
881
|
+
# RSpec.describe Person, type: :model do
|
759
882
|
# it do
|
760
883
|
# should have_and_belong_to_many(:projects).
|
761
884
|
# order('time_spent')
|
@@ -778,7 +901,7 @@ module Shoulda
|
|
778
901
|
# end
|
779
902
|
#
|
780
903
|
# # RSpec
|
781
|
-
# describe Person do
|
904
|
+
# RSpec.describe Person, type: :model do
|
782
905
|
# it do
|
783
906
|
# should have_and_belong_to_many(:places_visited).
|
784
907
|
# class_name('City')
|
@@ -797,21 +920,21 @@ module Shoulda
|
|
797
920
|
# asserts that the table you're referring to actually exists.
|
798
921
|
#
|
799
922
|
# class Person < ActiveRecord::Base
|
800
|
-
# has_and_belongs_to_many :issues, join_table:
|
923
|
+
# has_and_belongs_to_many :issues, join_table: :people_tickets
|
801
924
|
# end
|
802
925
|
#
|
803
926
|
# # RSpec
|
804
|
-
# describe Person do
|
927
|
+
# RSpec.describe Person, type: :model do
|
805
928
|
# it do
|
806
929
|
# should have_and_belong_to_many(:issues).
|
807
|
-
# join_table(
|
930
|
+
# join_table(:people_tickets)
|
808
931
|
# end
|
809
932
|
# end
|
810
933
|
#
|
811
934
|
# # Minitest (Shoulda)
|
812
935
|
# class PersonTest < ActiveSupport::TestCase
|
813
936
|
# should have_and_belong_to_many(:issues).
|
814
|
-
# join_table(
|
937
|
+
# join_table(:people_tickets)
|
815
938
|
# end
|
816
939
|
#
|
817
940
|
# ##### validate
|
@@ -823,7 +946,7 @@ module Shoulda
|
|
823
946
|
# end
|
824
947
|
#
|
825
948
|
# # RSpec
|
826
|
-
# describe Person do
|
949
|
+
# RSpec.describe Person, type: :model do
|
827
950
|
# it do
|
828
951
|
# should have_and_belong_to_many(:interviews).
|
829
952
|
# validate(false)
|
@@ -836,7 +959,7 @@ module Shoulda
|
|
836
959
|
# validate(false)
|
837
960
|
# end
|
838
961
|
#
|
839
|
-
#
|
962
|
+
# ##### autosave
|
840
963
|
#
|
841
964
|
# Use `autosave` to assert that the `:autosave` option was specified.
|
842
965
|
#
|
@@ -845,7 +968,7 @@ module Shoulda
|
|
845
968
|
# end
|
846
969
|
#
|
847
970
|
# # RSpec
|
848
|
-
# describe Publisher do
|
971
|
+
# RSpec.describe Publisher, type: :model do
|
849
972
|
# it { should have_and_belong_to_many(:advertisers).autosave(true) }
|
850
973
|
# end
|
851
974
|
#
|
@@ -862,6 +985,13 @@ module Shoulda
|
|
862
985
|
|
863
986
|
# @private
|
864
987
|
class AssociationMatcher
|
988
|
+
MACROS = {
|
989
|
+
'belongs_to' => 'belong to',
|
990
|
+
'has_many' => 'have many',
|
991
|
+
'has_one' => 'have one',
|
992
|
+
'has_and_belongs_to_many' => 'have and belong to many',
|
993
|
+
}.freeze
|
994
|
+
|
865
995
|
delegate :reflection, :model_class, :associated_class, :through?,
|
866
996
|
:polymorphic?, to: :reflector
|
867
997
|
|
@@ -873,42 +1003,63 @@ module Shoulda
|
|
873
1003
|
@options = {}
|
874
1004
|
@submatchers = []
|
875
1005
|
@missing = ''
|
1006
|
+
|
1007
|
+
if macro == :belongs_to
|
1008
|
+
required(belongs_to_required_by_default?)
|
1009
|
+
end
|
876
1010
|
end
|
877
1011
|
|
878
1012
|
def through(through)
|
879
|
-
|
880
|
-
|
1013
|
+
add_submatcher(
|
1014
|
+
AssociationMatchers::ThroughMatcher,
|
1015
|
+
through,
|
1016
|
+
name,
|
1017
|
+
)
|
881
1018
|
self
|
882
1019
|
end
|
883
1020
|
|
884
1021
|
def dependent(dependent)
|
885
|
-
|
886
|
-
|
1022
|
+
add_submatcher(
|
1023
|
+
AssociationMatchers::DependentMatcher,
|
1024
|
+
dependent,
|
1025
|
+
name,
|
1026
|
+
)
|
887
1027
|
self
|
888
1028
|
end
|
889
1029
|
|
890
1030
|
def order(order)
|
891
|
-
|
892
|
-
|
1031
|
+
add_submatcher(
|
1032
|
+
AssociationMatchers::OrderMatcher,
|
1033
|
+
order,
|
1034
|
+
name,
|
1035
|
+
)
|
893
1036
|
self
|
894
1037
|
end
|
895
1038
|
|
896
1039
|
def counter_cache(counter_cache = true)
|
897
|
-
|
898
|
-
|
1040
|
+
add_submatcher(
|
1041
|
+
AssociationMatchers::CounterCacheMatcher,
|
1042
|
+
counter_cache,
|
1043
|
+
name,
|
1044
|
+
)
|
899
1045
|
self
|
900
1046
|
end
|
901
1047
|
|
902
1048
|
def inverse_of(inverse_of)
|
903
|
-
|
904
|
-
AssociationMatchers::InverseOfMatcher
|
905
|
-
|
1049
|
+
add_submatcher(
|
1050
|
+
AssociationMatchers::InverseOfMatcher,
|
1051
|
+
inverse_of,
|
1052
|
+
name,
|
1053
|
+
)
|
906
1054
|
self
|
907
1055
|
end
|
908
1056
|
|
909
1057
|
def source(source)
|
910
|
-
|
911
|
-
|
1058
|
+
add_submatcher(
|
1059
|
+
AssociationMatchers::SourceMatcher,
|
1060
|
+
source,
|
1061
|
+
name,
|
1062
|
+
)
|
912
1063
|
self
|
913
1064
|
end
|
914
1065
|
|
@@ -922,6 +1073,11 @@ module Shoulda
|
|
922
1073
|
self
|
923
1074
|
end
|
924
1075
|
|
1076
|
+
def index_errors(index_errors)
|
1077
|
+
@options[:index_errors] = index_errors
|
1078
|
+
self
|
1079
|
+
end
|
1080
|
+
|
925
1081
|
def class_name(class_name)
|
926
1082
|
@options[:class_name] = class_name
|
927
1083
|
self
|
@@ -937,6 +1093,26 @@ module Shoulda
|
|
937
1093
|
self
|
938
1094
|
end
|
939
1095
|
|
1096
|
+
def required(required = true)
|
1097
|
+
remove_submatcher(AssociationMatchers::OptionalMatcher)
|
1098
|
+
add_submatcher(
|
1099
|
+
AssociationMatchers::RequiredMatcher,
|
1100
|
+
name,
|
1101
|
+
required,
|
1102
|
+
)
|
1103
|
+
self
|
1104
|
+
end
|
1105
|
+
|
1106
|
+
def optional(optional = true)
|
1107
|
+
remove_submatcher(AssociationMatchers::RequiredMatcher)
|
1108
|
+
add_submatcher(
|
1109
|
+
AssociationMatchers::OptionalMatcher,
|
1110
|
+
name,
|
1111
|
+
optional,
|
1112
|
+
)
|
1113
|
+
self
|
1114
|
+
end
|
1115
|
+
|
940
1116
|
def validate(validate = true)
|
941
1117
|
@options[:validate] = validate
|
942
1118
|
self
|
@@ -952,9 +1128,16 @@ module Shoulda
|
|
952
1128
|
self
|
953
1129
|
end
|
954
1130
|
|
1131
|
+
def without_validating_presence
|
1132
|
+
remove_submatcher(AssociationMatchers::RequiredMatcher)
|
1133
|
+
self
|
1134
|
+
end
|
1135
|
+
|
955
1136
|
def description
|
956
1137
|
description = "#{macro_description} #{name}"
|
957
|
-
|
1138
|
+
if options.key?(:class_name)
|
1139
|
+
description += " class_name => #{options[:class_name]}"
|
1140
|
+
end
|
958
1141
|
[description, submatchers.map(&:description)].flatten.join(' ')
|
959
1142
|
end
|
960
1143
|
|
@@ -970,12 +1153,14 @@ module Shoulda
|
|
970
1153
|
@subject = subject
|
971
1154
|
association_exists? &&
|
972
1155
|
macro_correct? &&
|
1156
|
+
validate_inverse_of_through_association &&
|
973
1157
|
(polymorphic? || class_exists?) &&
|
974
1158
|
foreign_key_exists? &&
|
975
1159
|
primary_key_exists? &&
|
976
1160
|
class_name_correct? &&
|
977
1161
|
join_table_correct? &&
|
978
1162
|
autosave_correct? &&
|
1163
|
+
index_errors_correct? &&
|
979
1164
|
conditions_correct? &&
|
980
1165
|
validate_correct? &&
|
981
1166
|
touch_correct? &&
|
@@ -987,7 +1172,8 @@ module Shoulda
|
|
987
1172
|
end
|
988
1173
|
|
989
1174
|
def option_verifier
|
990
|
-
@
|
1175
|
+
@_option_verifier ||=
|
1176
|
+
AssociationMatchers::OptionVerifier.new(reflector)
|
991
1177
|
end
|
992
1178
|
|
993
1179
|
protected
|
@@ -995,44 +1181,49 @@ module Shoulda
|
|
995
1181
|
attr_reader :submatchers, :missing, :subject, :macro
|
996
1182
|
|
997
1183
|
def reflector
|
998
|
-
@
|
1184
|
+
@_reflector ||= AssociationMatchers::ModelReflector.new(subject, name)
|
999
1185
|
end
|
1000
1186
|
|
1001
|
-
def add_submatcher(
|
1002
|
-
|
1187
|
+
def add_submatcher(matcher_class, *args)
|
1188
|
+
remove_submatcher(matcher_class)
|
1189
|
+
submatchers << matcher_class.new(*args)
|
1003
1190
|
end
|
1004
1191
|
|
1005
|
-
def
|
1006
|
-
|
1007
|
-
|
1008
|
-
'belong to'
|
1009
|
-
when 'has_many'
|
1010
|
-
'have many'
|
1011
|
-
when 'has_one'
|
1012
|
-
'have one'
|
1013
|
-
when 'has_and_belongs_to_many'
|
1014
|
-
'have and belong to many'
|
1192
|
+
def remove_submatcher(matcher_class)
|
1193
|
+
submatchers.delete_if do |submatcher|
|
1194
|
+
submatcher.is_a?(matcher_class)
|
1015
1195
|
end
|
1016
1196
|
end
|
1017
1197
|
|
1198
|
+
def macro_description
|
1199
|
+
MACROS[macro.to_s]
|
1200
|
+
end
|
1201
|
+
|
1018
1202
|
def expectation
|
1019
|
-
|
1203
|
+
expectation =
|
1204
|
+
"#{model_class.name} to have a #{macro} association called #{name}"
|
1205
|
+
|
1206
|
+
if through?
|
1207
|
+
expectation << " through #{reflector.has_and_belongs_to_many_name}"
|
1208
|
+
end
|
1209
|
+
|
1210
|
+
expectation
|
1020
1211
|
end
|
1021
1212
|
|
1022
1213
|
def missing_options
|
1023
1214
|
missing_options = [missing, missing_options_for_failing_submatchers]
|
1024
|
-
missing_options.flatten.
|
1215
|
+
missing_options.flatten.select(&:present?).join(', ')
|
1025
1216
|
end
|
1026
1217
|
|
1027
1218
|
def failing_submatchers
|
1028
|
-
@
|
1219
|
+
@_failing_submatchers ||= submatchers.reject do |matcher|
|
1029
1220
|
matcher.matches?(subject)
|
1030
1221
|
end
|
1031
1222
|
end
|
1032
1223
|
|
1033
1224
|
def missing_options_for_failing_submatchers
|
1034
|
-
if defined?(@
|
1035
|
-
@
|
1225
|
+
if defined?(@_failing_submatchers)
|
1226
|
+
@_failing_submatchers.map(&:missing_option)
|
1036
1227
|
else
|
1037
1228
|
[]
|
1038
1229
|
end
|
@@ -1059,6 +1250,14 @@ module Shoulda
|
|
1059
1250
|
end
|
1060
1251
|
end
|
1061
1252
|
|
1253
|
+
def validate_inverse_of_through_association
|
1254
|
+
reflector.validate_inverse_of_through_association!
|
1255
|
+
true
|
1256
|
+
rescue ::ActiveRecord::ActiveRecordError => e
|
1257
|
+
@missing = e.message
|
1258
|
+
false
|
1259
|
+
end
|
1260
|
+
|
1062
1261
|
def macro_supports_primary_key?
|
1063
1262
|
macro == :belongs_to ||
|
1064
1263
|
([:has_many, :has_one].include?(macro) && !through?)
|
@@ -1084,10 +1283,14 @@ module Shoulda
|
|
1084
1283
|
|
1085
1284
|
def class_name_correct?
|
1086
1285
|
if options.key?(:class_name)
|
1087
|
-
if option_verifier.correct_for_constant?(
|
1286
|
+
if option_verifier.correct_for_constant?(
|
1287
|
+
:class_name,
|
1288
|
+
options[:class_name],
|
1289
|
+
)
|
1088
1290
|
true
|
1089
1291
|
else
|
1090
|
-
@missing = "#{name} should resolve to #{options[:class_name]}
|
1292
|
+
@missing = "#{name} should resolve to #{options[:class_name]}"\
|
1293
|
+
' for class_name'
|
1091
1294
|
false
|
1092
1295
|
end
|
1093
1296
|
else
|
@@ -1096,7 +1299,10 @@ module Shoulda
|
|
1096
1299
|
end
|
1097
1300
|
|
1098
1301
|
def join_table_correct?
|
1099
|
-
if
|
1302
|
+
if (
|
1303
|
+
macro != :has_and_belongs_to_many ||
|
1304
|
+
join_table_matcher.matches?(@subject)
|
1305
|
+
)
|
1100
1306
|
true
|
1101
1307
|
else
|
1102
1308
|
@missing = join_table_matcher.failure_message
|
@@ -1105,8 +1311,10 @@ module Shoulda
|
|
1105
1311
|
end
|
1106
1312
|
|
1107
1313
|
def join_table_matcher
|
1108
|
-
@
|
1109
|
-
|
1314
|
+
@_join_table_matcher ||= AssociationMatchers::JoinTableMatcher.new(
|
1315
|
+
self,
|
1316
|
+
reflector,
|
1317
|
+
)
|
1110
1318
|
end
|
1111
1319
|
|
1112
1320
|
def class_exists?
|
@@ -1119,10 +1327,14 @@ module Shoulda
|
|
1119
1327
|
|
1120
1328
|
def autosave_correct?
|
1121
1329
|
if options.key?(:autosave)
|
1122
|
-
if option_verifier.correct_for_boolean?(
|
1330
|
+
if option_verifier.correct_for_boolean?(
|
1331
|
+
:autosave,
|
1332
|
+
options[:autosave],
|
1333
|
+
)
|
1123
1334
|
true
|
1124
1335
|
else
|
1125
|
-
@missing = "#{name} should have autosave set to
|
1336
|
+
@missing = "#{name} should have autosave set to"\
|
1337
|
+
" #{options[:autosave]}"
|
1126
1338
|
false
|
1127
1339
|
end
|
1128
1340
|
else
|
@@ -1130,12 +1342,32 @@ module Shoulda
|
|
1130
1342
|
end
|
1131
1343
|
end
|
1132
1344
|
|
1345
|
+
def index_errors_correct?
|
1346
|
+
return true unless options.key?(:index_errors)
|
1347
|
+
|
1348
|
+
if option_verifier.correct_for_boolean?(
|
1349
|
+
:index_errors,
|
1350
|
+
options[:index_errors],
|
1351
|
+
)
|
1352
|
+
true
|
1353
|
+
else
|
1354
|
+
@missing =
|
1355
|
+
"#{name} should have index_errors set to " +
|
1356
|
+
options[:index_errors].to_s
|
1357
|
+
false
|
1358
|
+
end
|
1359
|
+
end
|
1360
|
+
|
1133
1361
|
def conditions_correct?
|
1134
1362
|
if options.key?(:conditions)
|
1135
|
-
if option_verifier.correct_for_relation_clause?(
|
1363
|
+
if option_verifier.correct_for_relation_clause?(
|
1364
|
+
:conditions,
|
1365
|
+
options[:conditions],
|
1366
|
+
)
|
1136
1367
|
true
|
1137
1368
|
else
|
1138
|
-
@missing = "#{name} should have the following conditions:
|
1369
|
+
@missing = "#{name} should have the following conditions:" +
|
1370
|
+
" #{options[:conditions]}"
|
1139
1371
|
false
|
1140
1372
|
end
|
1141
1373
|
else
|
@@ -1162,24 +1394,49 @@ module Shoulda
|
|
1162
1394
|
end
|
1163
1395
|
|
1164
1396
|
def class_has_foreign_key?(klass)
|
1165
|
-
|
1166
|
-
|
1397
|
+
@missing = validate_foreign_key(klass)
|
1398
|
+
|
1399
|
+
@missing.nil?
|
1400
|
+
end
|
1401
|
+
|
1402
|
+
def validate_foreign_key(klass)
|
1403
|
+
if options.key?(:foreign_key) && !foreign_key_correct?
|
1404
|
+
foreign_key_failure_message(klass, options[:foreign_key])
|
1405
|
+
elsif !has_column?(klass, actual_foreign_key)
|
1406
|
+
foreign_key_failure_message(klass, actual_foreign_key)
|
1407
|
+
end
|
1408
|
+
end
|
1409
|
+
|
1410
|
+
def has_column?(klass, column)
|
1411
|
+
case column
|
1412
|
+
when Array
|
1413
|
+
column.all? { |c| has_column?(klass, c.to_s) }
|
1167
1414
|
else
|
1168
|
-
|
1169
|
-
true
|
1170
|
-
else
|
1171
|
-
@missing = "#{klass} does not have a #{foreign_key} foreign key."
|
1172
|
-
false
|
1173
|
-
end
|
1415
|
+
column_names_for(klass).include?(column.to_s)
|
1174
1416
|
end
|
1175
1417
|
end
|
1176
1418
|
|
1419
|
+
def foreign_key_correct?
|
1420
|
+
option_verifier.correct_for_string?(
|
1421
|
+
:foreign_key,
|
1422
|
+
options[:foreign_key],
|
1423
|
+
)
|
1424
|
+
end
|
1425
|
+
|
1426
|
+
def foreign_key_failure_message(klass, foreign_key)
|
1427
|
+
"#{klass} does not have a #{foreign_key} foreign key."
|
1428
|
+
end
|
1429
|
+
|
1177
1430
|
def primary_key_correct?(klass)
|
1178
1431
|
if options.key?(:primary_key)
|
1179
|
-
if option_verifier.correct_for_string?(
|
1432
|
+
if option_verifier.correct_for_string?(
|
1433
|
+
:primary_key,
|
1434
|
+
options[:primary_key],
|
1435
|
+
)
|
1180
1436
|
true
|
1181
1437
|
else
|
1182
|
-
@missing = "#{klass} does not have a #{options[:primary_key]}
|
1438
|
+
@missing = "#{klass} does not have a #{options[:primary_key]}"\
|
1439
|
+
' primary key'
|
1183
1440
|
false
|
1184
1441
|
end
|
1185
1442
|
else
|
@@ -1187,19 +1444,27 @@ module Shoulda
|
|
1187
1444
|
end
|
1188
1445
|
end
|
1189
1446
|
|
1190
|
-
def
|
1191
|
-
|
1192
|
-
|
1193
|
-
|
1194
|
-
|
1195
|
-
|
1196
|
-
|
1447
|
+
def actual_foreign_key
|
1448
|
+
return unless foreign_key_reflection
|
1449
|
+
|
1450
|
+
if foreign_key_reflection.options[:foreign_key]
|
1451
|
+
foreign_key_reflection.options[:foreign_key]
|
1452
|
+
elsif foreign_key_reflection.respond_to?(:foreign_key)
|
1453
|
+
foreign_key_reflection.foreign_key
|
1454
|
+
else
|
1455
|
+
foreign_key_reflection.primary_key_name
|
1197
1456
|
end
|
1198
1457
|
end
|
1199
1458
|
|
1200
1459
|
def foreign_key_reflection
|
1201
|
-
if
|
1202
|
-
|
1460
|
+
if (
|
1461
|
+
[:has_one, :has_many].include?(macro) &&
|
1462
|
+
reflection.options.include?(:inverse_of) &&
|
1463
|
+
reflection.options[:inverse_of] != false
|
1464
|
+
)
|
1465
|
+
associated_class.reflect_on_association(
|
1466
|
+
reflection.options[:inverse_of],
|
1467
|
+
)
|
1203
1468
|
else
|
1204
1469
|
reflection
|
1205
1470
|
end
|
@@ -1208,6 +1473,16 @@ module Shoulda
|
|
1208
1473
|
def submatchers_match?
|
1209
1474
|
failing_submatchers.empty?
|
1210
1475
|
end
|
1476
|
+
|
1477
|
+
def column_names_for(klass)
|
1478
|
+
klass.column_names
|
1479
|
+
rescue ::ActiveRecord::StatementInvalid
|
1480
|
+
[]
|
1481
|
+
end
|
1482
|
+
|
1483
|
+
def belongs_to_required_by_default?
|
1484
|
+
::ActiveRecord::Base.belongs_to_required_by_default
|
1485
|
+
end
|
1211
1486
|
end
|
1212
1487
|
end
|
1213
1488
|
end
|