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.
Files changed (288) hide show
  1. checksums.yaml +5 -5
  2. data/{MIT-LICENSE → LICENSE} +1 -1
  3. data/README.md +407 -232
  4. data/docs/errors/NonCaseSwappableValueError.md +2 -2
  5. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +7 -80
  6. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +4 -3
  7. data/lib/shoulda/matchers/action_controller/flash_store.rb +2 -4
  8. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +36 -30
  9. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +8 -10
  10. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +7 -9
  11. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +18 -15
  12. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +3 -2
  13. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +3 -3
  14. data/lib/shoulda/matchers/action_controller/route_matcher.rb +88 -29
  15. data/lib/shoulda/matchers/action_controller/route_params.rb +2 -2
  16. data/lib/shoulda/matchers/action_controller/set_flash_matcher.rb +4 -4
  17. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +3 -3
  18. data/lib/shoulda/matchers/action_controller/set_session_or_flash_matcher.rb +19 -13
  19. data/lib/shoulda/matchers/action_controller.rb +2 -0
  20. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +1 -1
  21. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +5 -9
  22. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +2 -2
  23. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +1 -1
  24. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +1 -1
  25. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +42 -39
  26. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +1 -1
  27. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +52 -26
  28. data/lib/shoulda/matchers/active_model/helpers.rb +2 -2
  29. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +32 -30
  30. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +2 -1
  31. data/lib/shoulda/matchers/active_model/qualifiers/allow_blank.rb +26 -0
  32. data/lib/shoulda/matchers/active_model/qualifiers/allow_nil.rb +26 -0
  33. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +1 -1
  34. data/lib/shoulda/matchers/active_model/qualifiers.rb +2 -0
  35. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +30 -6
  36. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +8 -3
  37. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +31 -16
  38. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +52 -16
  39. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +137 -84
  40. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +159 -46
  41. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +130 -66
  42. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +251 -24
  43. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +12 -9
  44. data/lib/shoulda/matchers/active_model/validation_matcher.rb +38 -6
  45. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +2 -4
  46. data/lib/shoulda/matchers/active_model/validator.rb +4 -9
  47. data/lib/shoulda/matchers/active_model.rb +3 -5
  48. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +10 -7
  49. data/lib/shoulda/matchers/active_record/association_matcher.rb +386 -111
  50. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +5 -2
  51. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -4
  52. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +1 -1
  53. data/lib/shoulda/matchers/active_record/association_matchers/join_table_matcher.rb +11 -6
  54. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +14 -15
  55. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +30 -8
  56. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +34 -11
  57. data/lib/shoulda/matchers/active_record/association_matchers/optional_matcher.rb +69 -0
  58. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +1 -1
  59. data/lib/shoulda/matchers/active_record/association_matchers/required_matcher.rb +74 -0
  60. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +3 -2
  61. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +7 -5
  62. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +458 -42
  63. data/lib/shoulda/matchers/active_record/have_attached_matcher.rb +185 -0
  64. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +63 -23
  65. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +164 -48
  66. data/lib/shoulda/matchers/active_record/have_implicit_order_column.rb +106 -0
  67. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +13 -11
  68. data/lib/shoulda/matchers/active_record/have_rich_text_matcher.rb +83 -0
  69. data/lib/shoulda/matchers/active_record/have_secure_token_matcher.rb +132 -0
  70. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +18 -18
  71. data/lib/shoulda/matchers/active_record/uniqueness/test_model_creator.rb +1 -3
  72. data/lib/shoulda/matchers/active_record/uniqueness/test_models.rb +0 -2
  73. data/lib/shoulda/matchers/active_record/uniqueness.rb +1 -1
  74. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +430 -200
  75. data/lib/shoulda/matchers/active_record.rb +28 -20
  76. data/lib/shoulda/matchers/configuration.rb +12 -1
  77. data/lib/shoulda/matchers/doublespeak/double.rb +1 -1
  78. data/lib/shoulda/matchers/doublespeak/double_collection.rb +3 -3
  79. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +8 -5
  80. data/lib/shoulda/matchers/doublespeak/object_double.rb +6 -2
  81. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +1 -5
  82. data/lib/shoulda/matchers/doublespeak/world.rb +2 -2
  83. data/lib/shoulda/matchers/doublespeak.rb +2 -1
  84. data/lib/shoulda/matchers/error.rb +1 -1
  85. data/lib/shoulda/matchers/independent/delegate_method_matcher.rb +109 -29
  86. data/lib/shoulda/matchers/independent.rb +2 -2
  87. data/lib/shoulda/matchers/integrations/configuration.rb +8 -4
  88. data/lib/shoulda/matchers/integrations/libraries/action_controller.rb +1 -1
  89. data/lib/shoulda/matchers/integrations/libraries/rails.rb +2 -2
  90. data/lib/shoulda/matchers/integrations/test_frameworks/active_support_test_case.rb +1 -1
  91. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_4.rb +1 -1
  92. data/lib/shoulda/matchers/integrations/test_frameworks/minitest_5.rb +1 -1
  93. data/lib/shoulda/matchers/integrations/test_frameworks/missing_test_framework.rb +1 -1
  94. data/lib/shoulda/matchers/integrations/test_frameworks/test_unit.rb +1 -1
  95. data/lib/shoulda/matchers/rails_shim.rb +172 -51
  96. data/lib/shoulda/matchers/routing.rb +2 -2
  97. data/lib/shoulda/matchers/util/word_wrap.rb +17 -12
  98. data/lib/shoulda/matchers/util.rb +39 -5
  99. data/lib/shoulda/matchers/version.rb +1 -1
  100. data/lib/shoulda/matchers/warn.rb +4 -3
  101. data/shoulda-matchers.gemspec +33 -15
  102. metadata +31 -338
  103. data/.gitignore +0 -12
  104. data/.hound.yml +0 -3
  105. data/.hound_config/ruby.yml +0 -12
  106. data/.travis.yml +0 -19
  107. data/.yardopts +0 -10
  108. data/Appraisals +0 -73
  109. data/CONTRIBUTING.md +0 -101
  110. data/Gemfile +0 -15
  111. data/Gemfile.lock +0 -70
  112. data/NEWS.md +0 -986
  113. data/Rakefile +0 -39
  114. data/custom_plan.rb +0 -88
  115. data/doc_config/gh-pages/index.html.erb +0 -9
  116. data/doc_config/yard/setup.rb +0 -22
  117. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +0 -5967
  118. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +0 -12
  119. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +0 -62
  120. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +0 -69
  121. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +0 -312
  122. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +0 -32
  123. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +0 -1
  124. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +0 -8
  125. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +0 -298
  126. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +0 -1
  127. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +0 -289
  128. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +0 -6
  129. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +0 -8
  130. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +0 -14
  131. data/doc_config/yard/templates/default/layout/html/fonts.erb +0 -1
  132. data/doc_config/yard/templates/default/layout/html/footer.erb +0 -6
  133. data/doc_config/yard/templates/default/layout/html/layout.erb +0 -23
  134. data/doc_config/yard/templates/default/layout/html/search.erb +0 -13
  135. data/doc_config/yard/templates/default/layout/html/setup.rb +0 -40
  136. data/doc_config/yard/templates/default/method_details/html/source.erb +0 -10
  137. data/doc_config/yard/templates/default/module/html/box_info.erb +0 -31
  138. data/gemfiles/4.0.0.gemfile +0 -38
  139. data/gemfiles/4.0.0.gemfile.lock +0 -223
  140. data/gemfiles/4.0.1.gemfile +0 -38
  141. data/gemfiles/4.0.1.gemfile.lock +0 -225
  142. data/gemfiles/4.1.gemfile +0 -38
  143. data/gemfiles/4.1.gemfile.lock +0 -220
  144. data/gemfiles/4.2.gemfile +0 -38
  145. data/gemfiles/4.2.gemfile.lock +0 -243
  146. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +0 -159
  147. data/lib/shoulda/matchers/independent/delegate_method_matcher/stubbed_target.rb +0 -37
  148. data/script/SUPPORTED_VERSIONS +0 -1
  149. data/script/install_gems_in_all_appraisals +0 -14
  150. data/script/run_all_tests +0 -14
  151. data/script/update_gem_in_all_appraisals +0 -15
  152. data/script/update_gems_in_all_appraisals +0 -14
  153. data/spec/acceptance/active_model_integration_spec.rb +0 -23
  154. data/spec/acceptance/independent_matchers_spec.rb +0 -125
  155. data/spec/acceptance/multiple_libraries_integration_spec.rb +0 -55
  156. data/spec/acceptance/rails_integration_spec.rb +0 -156
  157. data/spec/acceptance_spec_helper.rb +0 -23
  158. data/spec/doublespeak_spec_helper.rb +0 -2
  159. data/spec/report_warnings.rb +0 -7
  160. data/spec/spec_helper.rb +0 -21
  161. data/spec/support/acceptance/adds_shoulda_matchers_to_project.rb +0 -133
  162. data/spec/support/acceptance/helpers/active_model_helpers.rb +0 -11
  163. data/spec/support/acceptance/helpers/array_helpers.rb +0 -13
  164. data/spec/support/acceptance/helpers/base_helpers.rb +0 -19
  165. data/spec/support/acceptance/helpers/command_helpers.rb +0 -55
  166. data/spec/support/acceptance/helpers/file_helpers.rb +0 -19
  167. data/spec/support/acceptance/helpers/gem_helpers.rb +0 -31
  168. data/spec/support/acceptance/helpers/minitest_helpers.rb +0 -11
  169. data/spec/support/acceptance/helpers/n_unit_helpers.rb +0 -25
  170. data/spec/support/acceptance/helpers/pluralization_helpers.rb +0 -13
  171. data/spec/support/acceptance/helpers/rails_version_helpers.rb +0 -11
  172. data/spec/support/acceptance/helpers/rspec_helpers.rb +0 -24
  173. data/spec/support/acceptance/helpers/ruby_version_helpers.rb +0 -9
  174. data/spec/support/acceptance/helpers/step_helpers.rb +0 -127
  175. data/spec/support/acceptance/helpers.rb +0 -31
  176. data/spec/support/acceptance/matchers/have_output.rb +0 -31
  177. data/spec/support/acceptance/matchers/indicate_number_of_tests_was_run_matcher.rb +0 -55
  178. data/spec/support/acceptance/matchers/indicate_that_tests_were_run_matcher.rb +0 -103
  179. data/spec/support/tests/bundle.rb +0 -94
  180. data/spec/support/tests/command_runner.rb +0 -230
  181. data/spec/support/tests/current_bundle.rb +0 -61
  182. data/spec/support/tests/database.rb +0 -28
  183. data/spec/support/tests/database_adapters/postgresql.rb +0 -25
  184. data/spec/support/tests/database_adapters/sqlite3.rb +0 -26
  185. data/spec/support/tests/database_configuration.rb +0 -33
  186. data/spec/support/tests/database_configuration_registry.rb +0 -28
  187. data/spec/support/tests/filesystem.rb +0 -100
  188. data/spec/support/tests/version.rb +0 -45
  189. data/spec/support/unit/active_record/create_table.rb +0 -54
  190. data/spec/support/unit/attribute.rb +0 -47
  191. data/spec/support/unit/capture.rb +0 -40
  192. data/spec/support/unit/change_value.rb +0 -111
  193. data/spec/support/unit/create_model_arguments/basic.rb +0 -135
  194. data/spec/support/unit/create_model_arguments/has_many.rb +0 -15
  195. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +0 -74
  196. data/spec/support/unit/helpers/active_model_helpers.rb +0 -27
  197. data/spec/support/unit/helpers/active_model_versions.rb +0 -28
  198. data/spec/support/unit/helpers/active_record_versions.rb +0 -24
  199. data/spec/support/unit/helpers/active_resource_builder.rb +0 -27
  200. data/spec/support/unit/helpers/allow_value_matcher_helpers.rb +0 -15
  201. data/spec/support/unit/helpers/class_builder.rb +0 -90
  202. data/spec/support/unit/helpers/column_type_helpers.rb +0 -26
  203. data/spec/support/unit/helpers/confirmation_matcher_helpers.rb +0 -17
  204. data/spec/support/unit/helpers/controller_builder.rb +0 -63
  205. data/spec/support/unit/helpers/database_helpers.rb +0 -20
  206. data/spec/support/unit/helpers/i18n_faker.rb +0 -15
  207. data/spec/support/unit/helpers/mailer_builder.rb +0 -12
  208. data/spec/support/unit/helpers/model_builder.rb +0 -114
  209. data/spec/support/unit/helpers/rails_versions.rb +0 -28
  210. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +0 -44
  211. data/spec/support/unit/i18n.rb +0 -7
  212. data/spec/support/unit/load_environment.rb +0 -12
  213. data/spec/support/unit/matchers/deprecate.rb +0 -60
  214. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +0 -51
  215. data/spec/support/unit/matchers/fail_with_message_matcher.rb +0 -62
  216. data/spec/support/unit/matchers/print_warning_including.rb +0 -59
  217. data/spec/support/unit/model_creation_strategies/active_model.rb +0 -111
  218. data/spec/support/unit/model_creation_strategies/active_record.rb +0 -77
  219. data/spec/support/unit/model_creators/active_model.rb +0 -39
  220. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +0 -95
  221. data/spec/support/unit/model_creators/active_record/has_many.rb +0 -67
  222. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +0 -42
  223. data/spec/support/unit/model_creators/active_record.rb +0 -43
  224. data/spec/support/unit/model_creators/basic.rb +0 -97
  225. data/spec/support/unit/model_creators.rb +0 -19
  226. data/spec/support/unit/rails_application.rb +0 -126
  227. data/spec/support/unit/record_builder_with_i18n_validation_message.rb +0 -69
  228. data/spec/support/unit/record_validating_confirmation_builder.rb +0 -51
  229. data/spec/support/unit/record_with_different_error_attribute_builder.rb +0 -92
  230. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +0 -79
  231. data/spec/support/unit/shared_examples/numerical_submatcher.rb +0 -17
  232. data/spec/support/unit/shared_examples/set_session_or_flash.rb +0 -360
  233. data/spec/support/unit/validation_matcher_scenario.rb +0 -62
  234. data/spec/unit/shoulda/matchers/action_controller/callback_matcher_spec.rb +0 -82
  235. data/spec/unit/shoulda/matchers/action_controller/filter_param_matcher_spec.rb +0 -28
  236. data/spec/unit/shoulda/matchers/action_controller/permit_matcher_spec.rb +0 -592
  237. data/spec/unit/shoulda/matchers/action_controller/redirect_to_matcher_spec.rb +0 -42
  238. data/spec/unit/shoulda/matchers/action_controller/render_template_matcher_spec.rb +0 -76
  239. data/spec/unit/shoulda/matchers/action_controller/render_with_layout_matcher_spec.rb +0 -62
  240. data/spec/unit/shoulda/matchers/action_controller/rescue_from_matcher_spec.rb +0 -90
  241. data/spec/unit/shoulda/matchers/action_controller/respond_with_matcher_spec.rb +0 -31
  242. data/spec/unit/shoulda/matchers/action_controller/route_matcher_spec.rb +0 -330
  243. data/spec/unit/shoulda/matchers/action_controller/route_params_spec.rb +0 -30
  244. data/spec/unit/shoulda/matchers/action_controller/set_flash_matcher_spec.rb +0 -67
  245. data/spec/unit/shoulda/matchers/action_controller/set_session_matcher_spec.rb +0 -17
  246. data/spec/unit/shoulda/matchers/action_controller/set_session_or_flash_matcher_spec.rb +0 -562
  247. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +0 -115
  248. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +0 -823
  249. data/spec/unit/shoulda/matchers/active_model/disallow_value_matcher_spec.rb +0 -86
  250. data/spec/unit/shoulda/matchers/active_model/have_secure_password_matcher_spec.rb +0 -20
  251. data/spec/unit/shoulda/matchers/active_model/helpers_spec.rb +0 -162
  252. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +0 -266
  253. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +0 -91
  254. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +0 -149
  255. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +0 -207
  256. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +0 -1015
  257. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +0 -288
  258. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +0 -1837
  259. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +0 -380
  260. data/spec/unit/shoulda/matchers/active_record/accept_nested_attributes_for_matcher_spec.rb +0 -107
  261. data/spec/unit/shoulda/matchers/active_record/association_matcher_spec.rb +0 -1242
  262. data/spec/unit/shoulda/matchers/active_record/association_matchers/model_reflection_spec.rb +0 -251
  263. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +0 -168
  264. data/spec/unit/shoulda/matchers/active_record/have_db_column_matcher_spec.rb +0 -111
  265. data/spec/unit/shoulda/matchers/active_record/have_db_index_matcher_spec.rb +0 -85
  266. data/spec/unit/shoulda/matchers/active_record/have_readonly_attributes_matcher_spec.rb +0 -41
  267. data/spec/unit/shoulda/matchers/active_record/serialize_matcher_spec.rb +0 -86
  268. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +0 -1418
  269. data/spec/unit/shoulda/matchers/doublespeak/double_collection_spec.rb +0 -190
  270. data/spec/unit/shoulda/matchers/doublespeak/double_implementation_registry_spec.rb +0 -21
  271. data/spec/unit/shoulda/matchers/doublespeak/double_spec.rb +0 -271
  272. data/spec/unit/shoulda/matchers/doublespeak/object_double_spec.rb +0 -77
  273. data/spec/unit/shoulda/matchers/doublespeak/proxy_implementation_spec.rb +0 -72
  274. data/spec/unit/shoulda/matchers/doublespeak/stub_implementation_spec.rb +0 -101
  275. data/spec/unit/shoulda/matchers/doublespeak/world_spec.rb +0 -80
  276. data/spec/unit/shoulda/matchers/doublespeak_spec.rb +0 -27
  277. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher/stubbed_target_spec.rb +0 -43
  278. data/spec/unit/shoulda/matchers/independent/delegate_method_matcher_spec.rb +0 -517
  279. data/spec/unit/shoulda/matchers/routing/route_matcher_spec.rb +0 -242
  280. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +0 -252
  281. data/spec/unit_spec_helper.rb +0 -46
  282. data/spec/warnings_spy/filesystem.rb +0 -45
  283. data/spec/warnings_spy/partitioner.rb +0 -36
  284. data/spec/warnings_spy/reader.rb +0 -53
  285. data/spec/warnings_spy/reporter.rb +0 -88
  286. data/spec/warnings_spy.rb +0 -64
  287. data/tasks/documentation.rb +0 -199
  288. 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
- # #### autosave
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
- # #### autosave
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
- # #### autosave
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: 'people_tickets'
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('people_tickets')
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('people_tickets')
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
- # #### autosave
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
- through_matcher = AssociationMatchers::ThroughMatcher.new(through, name)
880
- add_submatcher(through_matcher)
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
- dependent_matcher = AssociationMatchers::DependentMatcher.new(dependent, name)
886
- add_submatcher(dependent_matcher)
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
- order_matcher = AssociationMatchers::OrderMatcher.new(order, name)
892
- add_submatcher(order_matcher)
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
- counter_cache_matcher = AssociationMatchers::CounterCacheMatcher.new(counter_cache, name)
898
- add_submatcher(counter_cache_matcher)
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
- inverse_of_matcher =
904
- AssociationMatchers::InverseOfMatcher.new(inverse_of, name)
905
- add_submatcher(inverse_of_matcher)
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
- source_matcher = AssociationMatchers::SourceMatcher.new(source, name)
911
- add_submatcher(source_matcher)
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
- description += " class_name => #{options[:class_name]}" if options.key?(:class_name)
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
- @option_verifier ||= AssociationMatchers::OptionVerifier.new(reflector)
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
- @reflector ||= AssociationMatchers::ModelReflector.new(subject, name)
1184
+ @_reflector ||= AssociationMatchers::ModelReflector.new(subject, name)
999
1185
  end
1000
1186
 
1001
- def add_submatcher(matcher)
1002
- @submatchers << matcher
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 macro_description
1006
- case macro.to_s
1007
- when 'belongs_to'
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
- "#{model_class.name} to have a #{macro} association called #{name}"
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.compact.join(', ')
1215
+ missing_options.flatten.select(&:present?).join(', ')
1025
1216
  end
1026
1217
 
1027
1218
  def failing_submatchers
1028
- @failing_submatchers ||= submatchers.reject do |matcher|
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?(@failing_submatchers)
1035
- @failing_submatchers.map(&:missing_option)
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?(:class_name, options[:class_name])
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]} for 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 macro != :has_and_belongs_to_many || join_table_matcher.matches?(@subject)
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
- @join_table_matcher ||=
1109
- AssociationMatchers::JoinTableMatcher.new(self, reflector)
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?(:autosave, options[:autosave])
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 #{options[:autosave]}"
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?(:conditions, options[:conditions])
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: #{options[: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
- if options.key?(:foreign_key)
1166
- option_verifier.correct_for_string?(:foreign_key, options[:foreign_key])
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
- if klass.column_names.include?(foreign_key)
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?(:primary_key, options[:primary_key])
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]} 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 foreign_key
1191
- if foreign_key_reflection
1192
- if foreign_key_reflection.respond_to?(:foreign_key)
1193
- foreign_key_reflection.foreign_key.to_s
1194
- else
1195
- foreign_key_reflection.primary_key_name.to_s
1196
- end
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 [:has_one, :has_many].include?(macro) && reflection.options.include?(:inverse_of)
1202
- associated_class.reflect_on_association(reflection.options[:inverse_of])
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