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
@@ -1,1242 +0,0 @@
1
- require 'unit_spec_helper'
2
-
3
- describe Shoulda::Matchers::ActiveRecord::AssociationMatcher, type: :model do
4
- context 'belong_to' do
5
- it 'accepts a good association with the default foreign key' do
6
- expect(belonging_to_parent).to belong_to(:parent)
7
- end
8
-
9
- it 'rejects a nonexistent association' do
10
- expect(define_model(:child).new).not_to belong_to(:parent)
11
- end
12
-
13
- it 'rejects an association of the wrong type' do
14
- define_model :parent, child_id: :integer
15
- expect(define_model(:child) { has_one :parent }.new).not_to belong_to(:parent)
16
- end
17
-
18
- it 'rejects an association that has a nonexistent foreign key' do
19
- define_model :parent
20
- expect(define_model(:child) { belongs_to :parent }.new).not_to belong_to(:parent)
21
- end
22
-
23
- it 'accepts an association with an existing custom foreign key' do
24
- define_model :parent
25
- define_model :child, guardian_id: :integer do
26
- belongs_to :parent, foreign_key: 'guardian_id'
27
- end
28
-
29
- expect(Child.new).to belong_to(:parent)
30
- end
31
-
32
- it 'accepts an association using an existing custom primary key' do
33
- define_model :parent
34
- define_model :child, parent_id: :integer, custom_primary_key: :integer do
35
- belongs_to :parent, primary_key: :custom_primary_key
36
- end
37
- expect(Child.new).to belong_to(:parent).with_primary_key(:custom_primary_key)
38
- end
39
-
40
- it 'rejects an association with a bad :primary_key option' do
41
- matcher = belong_to(:parent).with_primary_key(:custom_primary_key)
42
-
43
- expect(belonging_to_parent).not_to matcher
44
-
45
- expect(matcher.failure_message).to match(/Child does not have a custom_primary_key primary key/)
46
- end
47
-
48
- it 'accepts a polymorphic association' do
49
- define_model :child, parent_type: :string, parent_id: :integer do
50
- belongs_to :parent, polymorphic: true
51
- end
52
-
53
- expect(Child.new).to belong_to(:parent)
54
- end
55
-
56
- it 'accepts an association with a valid :dependent option' do
57
- expect(belonging_to_parent(dependent: :destroy)).
58
- to belong_to(:parent).dependent(:destroy)
59
- end
60
-
61
- it 'rejects an association with a bad :dependent option' do
62
- expect(belonging_to_parent).not_to belong_to(:parent).dependent(:destroy)
63
- end
64
-
65
- it 'accepts an association with a valid :counter_cache option' do
66
- expect(belonging_to_parent(counter_cache: :attribute_count)).
67
- to belong_to(:parent).counter_cache(:attribute_count)
68
- end
69
-
70
- it 'defaults :counter_cache to true' do
71
- expect(belonging_to_parent(counter_cache: true)).
72
- to belong_to(:parent).counter_cache
73
- end
74
-
75
- it 'rejects an association with a bad :counter_cache option' do
76
- expect(belonging_to_parent(counter_cache: :attribute_count)).
77
- not_to belong_to(:parent).counter_cache(true)
78
- end
79
-
80
- it 'rejects an association that has no :counter_cache option' do
81
- expect(belonging_to_parent).not_to belong_to(:parent).counter_cache
82
- end
83
-
84
- it 'accepts an association with a valid :inverse_of option' do
85
- expect(belonging_to_parent(inverse_of: :children))
86
- .to belong_to(:parent).inverse_of(:children)
87
- end
88
-
89
- it 'rejects an association with a bad :inverse_of option' do
90
- expect(belonging_to_parent(inverse_of: :other_children))
91
- .not_to belong_to(:parent).inverse_of(:children)
92
- end
93
-
94
- it 'rejects an association that has no :inverse_of option' do
95
- expect(belonging_to_parent)
96
- .not_to belong_to(:parent).inverse_of(:children)
97
- end
98
-
99
- it 'accepts an association with a valid :conditions option' do
100
- define_model :parent, adopter: :boolean
101
- define_model(:child, parent_id: :integer).tap do |model|
102
- define_association_with_conditions(model, :belongs_to, :parent, adopter: true)
103
- end
104
-
105
- expect(Child.new).to belong_to(:parent).conditions(adopter: true)
106
- end
107
-
108
- it 'rejects an association with a bad :conditions option' do
109
- define_model :parent, adopter: :boolean
110
- define_model :child, parent_id: :integer do
111
- belongs_to :parent
112
- end
113
-
114
- expect(Child.new).not_to belong_to(:parent).conditions(adopter: true)
115
- end
116
-
117
- it 'accepts an association without a :class_name option' do
118
- expect(belonging_to_parent).to belong_to(:parent).class_name('Parent')
119
- end
120
-
121
- it 'accepts an association with a valid :class_name option' do
122
- define_model :tree_parent
123
- define_model :child, parent_id: :integer do
124
- belongs_to :parent, class_name: 'TreeParent'
125
- end
126
-
127
- expect(Child.new).to belong_to(:parent).class_name('TreeParent')
128
- end
129
-
130
- it 'rejects an association with a bad :class_name option' do
131
- expect(belonging_to_parent).not_to belong_to(:parent).class_name('TreeChild')
132
- end
133
-
134
- it 'rejects an association with non-existent implicit class name' do
135
- expect(belonging_to_non_existent_class(:child, :parent)).not_to belong_to(:parent)
136
- end
137
-
138
- it 'rejects an association with non-existent explicit class name' do
139
- expect(belonging_to_non_existent_class(:child, :parent, class_name: 'Parent')).not_to belong_to(:parent)
140
- end
141
-
142
- it 'adds error message when rejecting an association with non-existent class' do
143
- message = 'Expected Child to have a belongs_to association called parent (Parent2 does not exist)'
144
- expect {
145
- expect(belonging_to_non_existent_class(:child, :parent, class_name: 'Parent2')).to belong_to(:parent)
146
- }.to fail_with_message(message)
147
- end
148
-
149
- it 'accepts an association with a namespaced class name' do
150
- define_module 'Models'
151
- define_model 'Models::Organization'
152
- user_model = define_model 'Models::User', organization_id: :integer do
153
- belongs_to :organization, class_name: 'Organization'
154
- end
155
-
156
- expect(user_model.new).
157
- to belong_to(:organization).
158
- class_name('Organization')
159
- end
160
-
161
- it 'resolves class_name within the context of the namespace before the global namespace' do
162
- define_module 'Models'
163
- define_model 'Organization'
164
- define_model 'Models::Organization'
165
- user_model = define_model 'Models::User', organization_id: :integer do
166
- belongs_to :organization, class_name: 'Organization'
167
- end
168
-
169
- expect(user_model.new).
170
- to belong_to(:organization).
171
- class_name('Organization')
172
- end
173
-
174
- it 'accepts an association with a matching :autosave option' do
175
- define_model :parent, adopter: :boolean
176
- define_model :child, parent_id: :integer do
177
- belongs_to :parent, autosave: true
178
- end
179
- expect(Child.new).to belong_to(:parent).autosave(true)
180
- end
181
-
182
- it 'rejects an association with a non-matching :autosave option with the correct message' do
183
- define_model :parent, adopter: :boolean
184
- define_model :child, parent_id: :integer do
185
- belongs_to :parent, autosave: false
186
- end
187
-
188
- message = 'Expected Child to have a belongs_to association called parent (parent should have autosave set to true)'
189
- expect {
190
- expect(Child.new).to belong_to(:parent).autosave(true)
191
- }.to fail_with_message(message)
192
- end
193
-
194
- context 'an association with a :validate option' do
195
- [false, true].each do |validate_value|
196
- context "when the model has validate: #{validate_value}" do
197
- it 'accepts a matching validate option' do
198
- expect(belonging_to_parent(validate: validate_value)).
199
- to belong_to(:parent).validate(validate_value)
200
- end
201
-
202
- it 'rejects a non-matching validate option' do
203
- expect(belonging_to_parent(validate: validate_value)).
204
- not_to belong_to(:parent).validate(!validate_value)
205
- end
206
-
207
- it 'defaults to validate(true)' do
208
- if validate_value
209
- expect(belonging_to_parent(validate: validate_value)).
210
- to belong_to(:parent).validate
211
- else
212
- expect(belonging_to_parent(validate: validate_value)).
213
- not_to belong_to(:parent).validate
214
- end
215
- end
216
-
217
- it 'will not break matcher when validate option is unspecified' do
218
- expect(belonging_to_parent(validate: validate_value)).to belong_to(:parent)
219
- end
220
- end
221
- end
222
- end
223
-
224
- context 'an association without a :validate option' do
225
- it 'accepts validate(false)' do
226
- expect(belonging_to_parent).to belong_to(:parent).validate(false)
227
- end
228
-
229
- it 'rejects validate(true)' do
230
- expect(belonging_to_parent).not_to belong_to(:parent).validate(true)
231
- end
232
-
233
- it 'rejects validate()' do
234
- expect(belonging_to_parent).not_to belong_to(:parent).validate
235
- end
236
- end
237
-
238
- context 'an association with a :touch option' do
239
- [false, true].each do |touch_value|
240
- context "when the model has touch: #{touch_value}" do
241
- it 'accepts a matching touch option' do
242
- expect(belonging_to_parent(touch: touch_value)).
243
- to belong_to(:parent).touch(touch_value)
244
- end
245
-
246
- it 'rejects a non-matching touch option' do
247
- expect(belonging_to_parent(touch: touch_value)).
248
- not_to belong_to(:parent).touch(!touch_value)
249
- end
250
-
251
- it 'defaults to touch(true)' do
252
- if touch_value
253
- expect(belonging_to_parent(touch: touch_value)).
254
- to belong_to(:parent).touch
255
- else
256
- expect(belonging_to_parent(touch: touch_value)).
257
- not_to belong_to(:parent).touch
258
- end
259
- end
260
-
261
- it 'will not break matcher when touch option is unspecified' do
262
- expect(belonging_to_parent(touch: touch_value)).to belong_to(:parent)
263
- end
264
- end
265
- end
266
- end
267
-
268
- context 'an association without a :touch option' do
269
- it 'accepts touch(false)' do
270
- expect(belonging_to_parent).to belong_to(:parent).touch(false)
271
- end
272
-
273
- it 'rejects touch(true)' do
274
- expect(belonging_to_parent).not_to belong_to(:parent).touch(true)
275
- end
276
-
277
- it 'rejects touch()' do
278
- expect(belonging_to_parent).not_to belong_to(:parent).touch
279
- end
280
- end
281
-
282
- def belonging_to_parent(options = {})
283
- define_model :parent
284
- define_model :child, parent_id: :integer do
285
- belongs_to :parent, options
286
- end.new
287
- end
288
-
289
- def belonging_to_non_existent_class(model_name, assoc_name, options = {})
290
- define_model model_name, "#{assoc_name}_id" => :integer do
291
- belongs_to assoc_name, options
292
- end.new
293
- end
294
- end
295
-
296
- context 'have_many' do
297
- it 'accepts a valid association without any options' do
298
- expect(having_many_children).to have_many(:children)
299
- end
300
-
301
- it 'accepts a valid association with a :through option' do
302
- define_model :child
303
- define_model :conception, child_id: :integer,
304
- parent_id: :integer do
305
- belongs_to :child
306
- end
307
- define_model :parent do
308
- has_many :conceptions
309
- has_many :children, through: :conceptions
310
- end
311
- expect(Parent.new).to have_many(:children)
312
- end
313
-
314
- it 'accepts a valid association with an :as option' do
315
- define_model :child, guardian_type: :string, guardian_id: :integer
316
- define_model :parent do
317
- has_many :children, as: :guardian
318
- end
319
-
320
- expect(Parent.new).to have_many(:children)
321
- end
322
-
323
- it 'rejects an association that has a nonexistent foreign key' do
324
- define_model :child
325
- define_model :parent do
326
- has_many :children
327
- end
328
-
329
- expect(Parent.new).not_to have_many(:children)
330
- end
331
-
332
- it 'accepts an association using an existing custom primary key' do
333
- define_model :child, parent_id: :integer
334
- define_model :parent, custom_primary_key: :integer do
335
- has_many :children, primary_key: :custom_primary_key
336
- end
337
- expect(Parent.new).to have_many(:children).with_primary_key(:custom_primary_key)
338
- end
339
-
340
- it 'rejects an association with a bad :primary_key option' do
341
- matcher = have_many(:children).with_primary_key(:custom_primary_key)
342
-
343
- expect(having_many_children).not_to matcher
344
-
345
- expect(matcher.failure_message).to match(/Parent does not have a custom_primary_key primary key/)
346
- end
347
-
348
- it 'rejects an association with a bad :as option' do
349
- define_model :child, caretaker_type: :string,
350
- caretaker_id: :integer
351
- define_model :parent do
352
- has_many :children, as: :guardian
353
- end
354
-
355
- expect(Parent.new).not_to have_many(:children)
356
- end
357
-
358
- it 'rejects an association that has a bad :through option' do
359
- matcher = have_many(:children).through(:conceptions)
360
-
361
- expect(matcher.matches?(having_many_children)).to eq false
362
-
363
- expect(matcher.failure_message).to match(/does not have any relationship to conceptions/)
364
- end
365
-
366
- it 'rejects an association that has the wrong :through option' do
367
- define_model :child
368
-
369
- define_model :conception, child_id: :integer,
370
- parent_id: :integer do
371
- belongs_to :child
372
- end
373
-
374
- define_model :parent do
375
- has_many :conceptions
376
- has_many :relationships
377
- has_many :children, through: :conceptions
378
- end
379
-
380
- matcher = have_many(:children).through(:relationships)
381
- expect(matcher.matches?(Parent.new)).to eq false
382
- expect(matcher.failure_message).to match(/through relationships, but got it through conceptions/)
383
- end
384
-
385
- it 'produces a failure message without exception when association is missing :through option' do
386
- define_model :child
387
- define_model :parent
388
- matcher = have_many(:children).through(:relationships).source(:child)
389
- failure_message = 'Expected Parent to have a has_many association called children (no association called children)'
390
-
391
- matcher.matches?(Parent.new)
392
- expect(matcher.failure_message).to eq failure_message
393
- end
394
-
395
- it 'accepts an association with a valid :dependent option' do
396
- expect(having_many_children(dependent: :destroy)).
397
- to have_many(:children).dependent(:destroy)
398
- end
399
-
400
- it 'rejects an association with a bad :dependent option' do
401
- matcher = have_many(:children).dependent(:destroy)
402
-
403
- expect(having_many_children).not_to matcher
404
-
405
- expect(matcher.failure_message).to match(/children should have destroy dependency/)
406
- end
407
-
408
- it 'accepts an association with a valid :source option' do
409
- expect(having_many_children(source: :user)).
410
- to have_many(:children).source(:user)
411
- end
412
-
413
- it 'rejects an association with a bad :source option' do
414
- matcher = have_many(:children).source(:user)
415
-
416
- expect(having_many_children).not_to matcher
417
-
418
- expect(matcher.failure_message).to match(/children should have user as source option/)
419
- end
420
-
421
- it 'accepts an association with a valid :order option' do
422
- expect(having_many_children(order: :id)).
423
- to have_many(:children).order(:id)
424
- end
425
-
426
- it 'rejects an association with a bad :order option' do
427
- matcher = have_many(:children).order(:id)
428
-
429
- expect(having_many_children).not_to matcher
430
-
431
- expect(matcher.failure_message).to match(/children should be ordered by id/)
432
- end
433
-
434
- it 'accepts an association with a valid :conditions option' do
435
- define_model :child, parent_id: :integer, adopted: :boolean
436
- define_model(:parent).tap do |model|
437
- define_association_with_conditions(model, :has_many, :children, adopted: true)
438
- end
439
-
440
- expect(Parent.new).to have_many(:children).conditions(adopted: true)
441
- end
442
-
443
- it 'rejects an association with a bad :conditions option' do
444
- define_model :child, parent_id: :integer, adopted: :boolean
445
- define_model :parent do
446
- has_many :children
447
- end
448
-
449
- expect(Parent.new).not_to have_many(:children).conditions(adopted: true)
450
- end
451
-
452
- it 'accepts an association without a :class_name option' do
453
- expect(having_many_children).to have_many(:children).class_name('Child')
454
- end
455
-
456
- it 'accepts an association with a valid :class_name option' do
457
- define_model :node, parent_id: :integer
458
- define_model :parent do
459
- has_many :children, class_name: 'Node'
460
- end
461
-
462
- expect(Parent.new).to have_many(:children).class_name('Node')
463
- end
464
-
465
- it 'rejects an association with a bad :class_name option' do
466
- expect(having_many_children).not_to have_many(:children).class_name('Node')
467
- end
468
-
469
- it 'rejects an association with non-existent implicit class name' do
470
- expect(having_many_non_existent_class(:parent, :children)).not_to have_many(:children)
471
- end
472
-
473
- it 'rejects an association with non-existent explicit class name' do
474
- expect(having_many_non_existent_class(:parent, :children, class_name: 'Child')).not_to have_many(:children)
475
- end
476
-
477
- it 'adds error message when rejecting an association with non-existent class' do
478
- message = 'Expected Parent to have a has_many association called children (Child2 does not exist)'
479
- expect {
480
- expect(having_many_non_existent_class(:parent, :children, class_name: 'Child2')).to have_many(:children)
481
- }.to fail_with_message(message)
482
- end
483
-
484
- it 'accepts an association with a namespaced class name' do
485
- define_module 'Models'
486
- define_model 'Models::Friend', user_id: :integer
487
- friend_model = define_model 'Models::User' do
488
- has_many :friends, class_name: 'Friend'
489
- end
490
-
491
- expect(friend_model.new).
492
- to have_many(:friends).
493
- class_name('Friend')
494
- end
495
-
496
- it 'resolves class_name within the context of the namespace before the global namespace' do
497
- define_module 'Models'
498
- define_model 'Friend'
499
- define_model 'Models::Friend', user_id: :integer
500
- friend_model = define_model 'Models::User' do
501
- has_many :friends, class_name: 'Friend'
502
- end
503
-
504
- expect(friend_model.new).
505
- to have_many(:friends).
506
- class_name('Friend')
507
- end
508
-
509
- it 'accepts an association with a matching :autosave option' do
510
- define_model :child, parent_id: :integer
511
- define_model :parent do
512
- has_many :children, autosave: true
513
- end
514
- expect(Parent.new).to have_many(:children).autosave(true)
515
- end
516
-
517
- it 'rejects an association with a non-matching :autosave option with the correct message' do
518
- define_model :child, parent_id: :integer
519
- define_model :parent do
520
- has_many :children, autosave: false
521
- end
522
-
523
- message = 'Expected Parent to have a has_many association called children (children should have autosave set to true)'
524
- expect {
525
- expect(Parent.new).to have_many(:children).autosave(true)
526
- }.to fail_with_message(message)
527
- end
528
-
529
- context 'validate' do
530
- it 'accepts when the :validate option matches' do
531
- expect(having_many_children(validate: false)).to have_many(:children).validate(false)
532
- end
533
-
534
- it 'rejects when the :validate option does not match' do
535
- expect(having_many_children(validate: true)).not_to have_many(:children).validate(false)
536
- end
537
-
538
- it 'assumes validate() means validate(true)' do
539
- expect(having_many_children(validate: false)).not_to have_many(:children).validate
540
- end
541
-
542
- it 'matches validate(false) to having no validate option specified' do
543
- expect(having_many_children).to have_many(:children).validate(false)
544
- end
545
- end
546
-
547
- it 'accepts an association with a nonstandard reverse foreign key, using :inverse_of' do
548
- define_model :child, ancestor_id: :integer do
549
- belongs_to :ancestor, inverse_of: :children, class_name: :Parent
550
- end
551
-
552
- define_model :parent do
553
- has_many :children, inverse_of: :ancestor
554
- end
555
-
556
- expect(Parent.new).to have_many(:children)
557
- end
558
-
559
- it 'rejects an association with a nonstandard reverse foreign key, if :inverse_of is not correct' do
560
- define_model :child, mother_id: :integer do
561
- belongs_to :mother, inverse_of: :children, class_name: :Parent
562
- end
563
-
564
- define_model :parent do
565
- has_many :children, inverse_of: :ancestor
566
- end
567
-
568
- expect(Parent.new).not_to have_many(:children)
569
- end
570
-
571
- def having_many_children(options = {})
572
- define_model :child, parent_id: :integer
573
- define_model(:parent).tap do |model|
574
- if options.key?(:order)
575
- order = options.delete(:order)
576
- define_association_with_order(model, :has_many, :children, order, options)
577
- else
578
- model.has_many :children, options
579
- end
580
- end.new
581
- end
582
-
583
- def having_many_non_existent_class(model_name, assoc_name, options = {})
584
- define_model model_name do
585
- has_many assoc_name, options
586
- end.new
587
- end
588
- end
589
-
590
- context 'have_one' do
591
- it 'accepts a valid association without any options' do
592
- expect(having_one_detail).to have_one(:detail)
593
- end
594
-
595
- it 'accepts a valid association with an :as option' do
596
- define_model :detail, detailable_id: :integer,
597
- detailable_type: :string
598
- define_model :person do
599
- has_one :detail, as: :detailable
600
- end
601
-
602
- expect(Person.new).to have_one(:detail)
603
- end
604
-
605
- it 'rejects an association that has a nonexistent foreign key' do
606
- define_model :detail
607
- define_model :person do
608
- has_one :detail
609
- end
610
-
611
- expect(Person.new).not_to have_one(:detail)
612
- end
613
-
614
- it 'accepts an association with an existing custom foreign key' do
615
- define_model :detail, detailed_person_id: :integer
616
- define_model :person do
617
- has_one :detail, foreign_key: :detailed_person_id
618
- end
619
- expect(Person.new).to have_one(:detail).with_foreign_key(:detailed_person_id)
620
- end
621
-
622
- it 'accepts an association using an existing custom primary key' do
623
- define_model :detail, person_id: :integer
624
- define_model :person, custom_primary_key: :integer do
625
- has_one :detail, primary_key: :custom_primary_key
626
- end
627
- expect(Person.new).to have_one(:detail).with_primary_key(:custom_primary_key)
628
- end
629
-
630
- it 'rejects an association with a bad :primary_key option' do
631
- matcher = have_one(:detail).with_primary_key(:custom_primary_key)
632
-
633
- expect(having_one_detail).not_to matcher
634
-
635
- expect(matcher.failure_message).to match(/Person does not have a custom_primary_key primary key/)
636
- end
637
-
638
- it 'rejects an association with a bad :as option' do
639
- define_model :detail, detailable_id: :integer,
640
- detailable_type: :string
641
- define_model :person do
642
- has_one :detail, as: :describable
643
- end
644
-
645
- expect(Person.new).not_to have_one(:detail)
646
- end
647
-
648
- it 'accepts an association with a valid :dependent option' do
649
- dependent_options.each do |option|
650
- expect(having_one_detail(dependent: option)).
651
- to have_one(:detail).dependent(option)
652
- end
653
- end
654
-
655
- it 'accepts any dependent option if true' do
656
- dependent_options.each do |option|
657
- expect(having_one_detail(dependent: option)).
658
- to have_one(:detail).dependent(true)
659
- end
660
- end
661
-
662
- it 'rejects any dependent options if false' do
663
- dependent_options.each do |option|
664
- expect(having_one_detail(dependent: option)).
665
- to_not have_one(:detail).dependent(false)
666
- end
667
- end
668
-
669
- it 'accepts a nil dependent option if false' do
670
- expect(having_one_detail).to have_one(:detail).dependent(false)
671
- end
672
-
673
- it 'rejects an association with a bad :dependent option' do
674
- matcher = have_one(:detail).dependent(:destroy)
675
-
676
- expect(having_one_detail).not_to matcher
677
-
678
- expect(matcher.failure_message).to match(/detail should have destroy dependency/)
679
- end
680
-
681
- it 'accepts an association with a valid :order option' do
682
- expect(having_one_detail(order: :id)).to have_one(:detail).order(:id)
683
- end
684
-
685
- it 'rejects an association with a bad :order option' do
686
- matcher = have_one(:detail).order(:id)
687
-
688
- expect(having_one_detail).not_to matcher
689
-
690
- expect(matcher.failure_message).to match(/detail should be ordered by id/)
691
- end
692
-
693
- it 'accepts an association with a valid :conditions option' do
694
- define_model :detail, person_id: :integer, disabled: :boolean
695
- define_model(:person).tap do |model|
696
- define_association_with_conditions(model, :has_one, :detail, disabled: true)
697
- end
698
-
699
- expect(Person.new).to have_one(:detail).conditions(disabled: true)
700
- end
701
-
702
- it 'rejects an association with a bad :conditions option' do
703
- define_model :detail, person_id: :integer, disabled: :boolean
704
- define_model :person do
705
- has_one :detail
706
- end
707
-
708
- expect(Person.new).not_to have_one(:detail).conditions(disabled: true)
709
- end
710
-
711
- it 'accepts an association without a :class_name option' do
712
- expect(having_one_detail).to have_one(:detail).class_name('Detail')
713
- end
714
-
715
- it 'accepts an association with a valid :class_name option' do
716
- define_model :person_detail, person_id: :integer
717
- define_model :person do
718
- has_one :detail, class_name: 'PersonDetail'
719
- end
720
-
721
- expect(Person.new).to have_one(:detail).class_name('PersonDetail')
722
- end
723
-
724
- it 'rejects an association with a bad :class_name option' do
725
- expect(having_one_detail).not_to have_one(:detail).class_name('NotSet')
726
- end
727
-
728
- it 'rejects an association with non-existent implicit class name' do
729
- expect(having_one_non_existent(:pserson, :detail)).not_to have_one(:detail)
730
- end
731
-
732
- it 'rejects an association with non-existent explicit class name' do
733
- expect(having_one_non_existent(:person, :detail, class_name: 'Detail')).not_to have_one(:detail)
734
- end
735
-
736
- it 'adds error message when rejecting an association with non-existent class' do
737
- message = 'Expected Person to have a has_one association called detail (Detail2 does not exist)'
738
- expect {
739
- expect(having_one_non_existent(:person, :detail, class_name: 'Detail2')).to have_one(:detail)
740
- }.to fail_with_message(message)
741
- end
742
-
743
- it 'accepts an association with a namespaced class name' do
744
- define_module 'Models'
745
- define_model 'Models::Account', user_id: :integer
746
- user_model = define_model 'Models::User' do
747
- has_one :account, class_name: 'Account'
748
- end
749
-
750
- expect(user_model.new).
751
- to have_one(:account).
752
- class_name('Account')
753
- end
754
-
755
- it 'resolves class_name within the context of the namespace before the global namespace' do
756
- define_module 'Models'
757
- define_model 'Account'
758
- define_model 'Models::Account', user_id: :integer
759
- user_model = define_model 'Models::User' do
760
- has_one :account, class_name: 'Account'
761
- end
762
-
763
- expect(user_model.new).
764
- to have_one(:account).
765
- class_name('Account')
766
- end
767
-
768
- it 'accepts an association with a matching :autosave option' do
769
- define_model :detail, person_id: :integer, disabled: :boolean
770
- define_model :person do
771
- has_one :detail, autosave: true
772
- end
773
- expect(Person.new).to have_one(:detail).autosave(true)
774
- end
775
-
776
- it 'rejects an association with a non-matching :autosave option with the correct message' do
777
- define_model :detail, person_id: :integer, disabled: :boolean
778
- define_model :person do
779
- has_one :detail, autosave: false
780
- end
781
-
782
- message = 'Expected Person to have a has_one association called detail (detail should have autosave set to true)'
783
- expect {
784
- expect(Person.new).to have_one(:detail).autosave(true)
785
- }.to fail_with_message(message)
786
- end
787
-
788
-
789
- it 'accepts an association with a through' do
790
- define_model :detail
791
-
792
- define_model :account do
793
- has_one :detail
794
- end
795
-
796
- define_model :person do
797
- has_one :account
798
- has_one :detail, through: :account
799
- end
800
-
801
- expect(Person.new).to have_one(:detail).through(:account)
802
- end
803
-
804
- it 'rejects an association with a bad through' do
805
- expect(having_one_detail).not_to have_one(:detail).through(:account)
806
- end
807
-
808
- context 'validate' do
809
- it 'accepts when the :validate option matches' do
810
- expect(having_one_detail(validate: false)).
811
- to have_one(:detail).validate(false)
812
- end
813
-
814
- it 'rejects when the :validate option does not match' do
815
- expect(having_one_detail(validate: true)).
816
- not_to have_one(:detail).validate(false)
817
- end
818
-
819
- it 'assumes validate() means validate(true)' do
820
- expect(having_one_detail(validate: false)).
821
- not_to have_one(:detail).validate
822
- end
823
-
824
- it 'matches validate(false) to having no validate option specified' do
825
- expect(having_one_detail).to have_one(:detail).validate(false)
826
- end
827
- end
828
-
829
- def having_one_detail(options = {})
830
- define_model :detail, person_id: :integer
831
- define_model(:person).tap do |model|
832
- if options.key?(:order)
833
- order = options.delete(:order)
834
- define_association_with_order(model, :has_one, :detail, order, options)
835
- else
836
- model.has_one :detail, options
837
- end
838
- end.new
839
- end
840
-
841
- def having_one_non_existent(model_name, assoc_name, options = {})
842
- define_model model_name do
843
- has_one assoc_name, options
844
- end.new
845
- end
846
- end
847
-
848
- context 'have_and_belong_to_many' do
849
- it 'accepts a valid association' do
850
- expect(having_and_belonging_to_many_relatives).
851
- to have_and_belong_to_many(:relatives)
852
- end
853
-
854
- it 'rejects a nonexistent association' do
855
- define_model :relative
856
- define_model :person
857
- define_model :people_relative, id: false, person_id: :integer,
858
- relative_id: :integer
859
-
860
- expect(Person.new).not_to have_and_belong_to_many(:relatives)
861
- end
862
-
863
- it 'rejects an association with a nonexistent join table' do
864
- define_model :relative
865
- define_model :person do
866
- has_and_belongs_to_many :relatives
867
- end
868
-
869
- expected_failure_message = "join table people_relatives doesn't exist"
870
-
871
- expect do
872
- expect(Person.new).to have_and_belong_to_many(:relatives)
873
- end.to fail_with_message_including(expected_failure_message)
874
- end
875
-
876
- it 'rejects an association with a join table with incorrect columns' do
877
- define_model :relative
878
- define_model :person do
879
- has_and_belongs_to_many :relatives
880
- end
881
-
882
- define_model :people_relative, id: false, some_crazy_id: :integer
883
-
884
- expect do
885
- expect(Person.new).to have_and_belong_to_many(:relatives)
886
- end.to fail_with_message_including('missing columns: person_id, relative_id')
887
- end
888
-
889
- context 'when the association is declared with a :join_table option' do
890
- it 'accepts when testing with the same :join_table option' do
891
- join_table_name = 'people_and_their_families'
892
-
893
- define_model :relative
894
-
895
- define_model :person do
896
- has_and_belongs_to_many(:relatives, join_table: join_table_name)
897
- end
898
-
899
- create_table(join_table_name, id: false) do |t|
900
- t.references :person
901
- t.references :relative
902
- end
903
-
904
- expect(Person.new).
905
- to have_and_belong_to_many(:relatives).
906
- join_table(join_table_name)
907
- end
908
-
909
- it 'accepts even when not explicitly testing with a :join_table option' do
910
- join_table_name = 'people_and_their_families'
911
-
912
- define_model :relative
913
-
914
- define_model :person do
915
- has_and_belongs_to_many(:relatives,
916
- join_table: join_table_name
917
- )
918
- end
919
-
920
- create_table(join_table_name, id: false) do |t|
921
- t.references :person
922
- t.references :relative
923
- end
924
-
925
- expect(Person.new).to have_and_belong_to_many(:relatives)
926
- end
927
-
928
- it 'rejects when testing with a different :join_table option' do
929
- join_table_name = 'people_and_their_families'
930
-
931
- define_model :relative
932
-
933
- define_model :person do
934
- has_and_belongs_to_many(
935
- :relatives,
936
- join_table: join_table_name
937
- )
938
- end
939
-
940
- create_table(join_table_name, id: false) do |t|
941
- t.references :person
942
- t.references :relative
943
- end
944
-
945
- assertion = lambda do
946
- expect(Person.new).
947
- to have_and_belong_to_many(:relatives).
948
- join_table('family_tree')
949
- end
950
-
951
- expect(&assertion).to fail_with_message_including(
952
- "relatives should use 'family_tree' for :join_table option"
953
- )
954
- end
955
- end
956
-
957
- context 'when the association is not declared with a :join_table option' do
958
- it 'rejects when testing with a :join_table option' do
959
- define_model :relative
960
-
961
- define_model :person do
962
- has_and_belongs_to_many(:relatives)
963
- end
964
-
965
- create_table('people_relatives', id: false) do |t|
966
- t.references :person
967
- t.references :relative
968
- end
969
-
970
- assertion = lambda do
971
- expect(Person.new).
972
- to have_and_belong_to_many(:relatives).
973
- join_table('family_tree')
974
- end
975
-
976
- expect(&assertion).to fail_with_message_including(
977
- "relatives should use 'family_tree' for :join_table option"
978
- )
979
- end
980
- end
981
-
982
- context 'using a custom foreign key' do
983
- it 'rejects an association with a join table with incorrect columns' do
984
- define_model :relative
985
- define_model :person do
986
- has_and_belongs_to_many :relatives,
987
- foreign_key: :custom_foreign_key_id
988
- end
989
-
990
- define_model :people_relative,
991
- id: false,
992
- custom_foreign_key_id: :integer,
993
- some_crazy_id: :integer
994
-
995
- expect do
996
- expect(Person.new).to have_and_belong_to_many(:relatives)
997
- end.to fail_with_message_including('missing column: relative_id')
998
- end
999
- end
1000
-
1001
- context 'using a custom association foreign key' do
1002
- it 'rejects an association with a join table with incorrect columns' do
1003
- define_model :relative
1004
- define_model :person do
1005
- has_and_belongs_to_many :relatives,
1006
- association_foreign_key: :custom_association_foreign_key_id
1007
- end
1008
-
1009
- define_model :people_relative,
1010
- id: false,
1011
- custom_association_foreign_key_id: :integer,
1012
- some_crazy_id: :integer
1013
-
1014
- expect do
1015
- expect(Person.new).to have_and_belong_to_many(:relatives)
1016
- end.to fail_with_message_including('missing column: person_id')
1017
- end
1018
-
1019
- it 'accepts foreign keys when they are symbols' do
1020
- define_model :relative
1021
- define_model :person do
1022
- has_and_belongs_to_many :relatives,
1023
- foreign_key: :some_foreign_key_id,
1024
- association_foreign_key: :custom_association_foreign_key_id
1025
- end
1026
-
1027
- define_model :people_relative,
1028
- id: false,
1029
- custom_association_foreign_key_id: :integer,
1030
- some_foreign_key_id: :integer
1031
-
1032
- expect(Person.new).to have_and_belong_to_many(:relatives)
1033
-
1034
- end
1035
-
1036
- end
1037
-
1038
- it 'rejects an association of the wrong type' do
1039
- define_model :relative, person_id: :integer
1040
- define_model :person do
1041
- has_many :relatives
1042
- end
1043
-
1044
- expect(Person.new).not_to have_and_belong_to_many(:relatives)
1045
- end
1046
-
1047
- it 'accepts an association with a valid :conditions option' do
1048
- define_model :relative, adopted: :boolean
1049
- define_model(:person).tap do |model|
1050
- define_association_with_conditions(model, :has_and_belongs_to_many, :relatives, adopted: true)
1051
- end
1052
- define_model :people_relative, id: false, person_id: :integer,
1053
- relative_id: :integer
1054
-
1055
- expect(Person.new).to have_and_belong_to_many(:relatives).conditions(adopted: true)
1056
- end
1057
-
1058
- it 'rejects an association with a bad :conditions option' do
1059
- define_model :relative, adopted: :boolean
1060
- define_model :person do
1061
- has_and_belongs_to_many :relatives
1062
- end
1063
- define_model :people_relative, id: false, person_id: :integer,
1064
- relative_id: :integer
1065
-
1066
- expect(Person.new).not_to have_and_belong_to_many(:relatives).conditions(adopted: true)
1067
- end
1068
-
1069
- it 'accepts an association without a :class_name option' do
1070
- expect(having_and_belonging_to_many_relatives).
1071
- to have_and_belong_to_many(:relatives).class_name('Relative')
1072
- end
1073
-
1074
- it 'accepts an association with a valid :class_name option' do
1075
- define_model :person_relative, adopted: :boolean
1076
- define_model :person do
1077
- has_and_belongs_to_many :relatives, class_name: 'PersonRelative'
1078
- end
1079
-
1080
- define_model :people_person_relative, person_id: :integer,
1081
- person_relative_id: :integer
1082
-
1083
- expect(Person.new).to have_and_belong_to_many(:relatives).class_name('PersonRelative')
1084
- end
1085
-
1086
- it 'rejects an association with a bad :class_name option' do
1087
- expect(having_and_belonging_to_many_relatives).
1088
- not_to have_and_belong_to_many(:relatives).class_name('PersonRelatives')
1089
- end
1090
-
1091
- it 'rejects an association with non-existent implicit class name' do
1092
- expect(having_and_belonging_to_many_non_existent_class(:person, :relatives)).
1093
- not_to have_and_belong_to_many(:relatives)
1094
- end
1095
-
1096
- it 'rejects an association with non-existent explicit class name' do
1097
- expect(having_and_belonging_to_many_non_existent_class(:person, :relatives, class_name: 'Relative')).
1098
- not_to have_and_belong_to_many(:relatives)
1099
- end
1100
-
1101
- it 'adds error message when rejecting an association with non-existent class' do
1102
- message = 'Expected Person to have a has_and_belongs_to_many association called relatives (Relative2 does not exist)'
1103
- expect {
1104
- expect(having_and_belonging_to_many_non_existent_class(:person, :relatives, class_name: 'Relative2')).
1105
- to have_and_belong_to_many(:relatives)
1106
- }.to fail_with_message(message)
1107
- end
1108
-
1109
- it 'accepts an association with a namespaced class name' do
1110
- possible_join_table_names = [:groups_users, :models_groups_users, :groups_models_users]
1111
- possible_join_table_names.each do |join_table_name|
1112
- create_table join_table_name, id: false do |t|
1113
- t.integer :group_id
1114
- t.integer :user_id
1115
- end
1116
- end
1117
- define_module 'Models'
1118
- define_model 'Models::Group'
1119
- user_model = define_model 'Models::User' do
1120
- has_and_belongs_to_many :groups, class_name: 'Group'
1121
- end
1122
-
1123
- expect(user_model.new).
1124
- to have_and_belong_to_many(:groups).
1125
- class_name('Group')
1126
- end
1127
-
1128
- it 'resolves class_name within the context of the namespace before the global namespace' do
1129
- possible_join_table_names = [:groups_users, :models_groups_users, :groups_models_users]
1130
- possible_join_table_names.each do |join_table_name|
1131
- create_table join_table_name, id: false do |t|
1132
- t.integer :group_id
1133
- t.integer :user_id
1134
- end
1135
- end
1136
- define_module 'Models'
1137
- define_model 'Group'
1138
- define_model 'Models::Group'
1139
- user_model = define_model 'Models::User' do
1140
- has_and_belongs_to_many :groups, class_name: 'Group'
1141
- end
1142
-
1143
- expect(user_model.new).
1144
- to have_and_belong_to_many(:groups).
1145
- class_name('Group')
1146
- end
1147
-
1148
- it 'accepts an association with a matching :autosave option' do
1149
- define_model :relatives, adopted: :boolean
1150
- define_model :person do
1151
- has_and_belongs_to_many :relatives, autosave: true
1152
- end
1153
- define_model :people_relative, person_id: :integer,
1154
- relative_id: :integer
1155
- expect(Person.new).to have_and_belong_to_many(:relatives).autosave(true)
1156
- end
1157
-
1158
- it 'rejects an association with a non-matching :autosave option with the correct message' do
1159
- define_model :relatives, adopted: :boolean
1160
- define_model :person do
1161
- has_and_belongs_to_many :relatives
1162
- end
1163
- define_model :people_relative, person_id: :integer,
1164
- relative_id: :integer
1165
-
1166
- message = 'Expected Person to have a has_and_belongs_to_many association called relatives (relatives should have autosave set to true)'
1167
- expect {
1168
- expect(Person.new).to have_and_belong_to_many(:relatives).autosave(true)
1169
- }.to fail_with_message(message)
1170
- end
1171
-
1172
- context 'validate' do
1173
- it 'accepts when the :validate option matches' do
1174
- expect(having_and_belonging_to_many_relatives(validate: false)).
1175
- to have_and_belong_to_many(:relatives).validate(false)
1176
- end
1177
-
1178
- it 'rejects when the :validate option does not match' do
1179
- expect(having_and_belonging_to_many_relatives(validate: true)).
1180
- to have_and_belong_to_many(:relatives).validate(false)
1181
- end
1182
-
1183
- it 'assumes validate() means validate(true)' do
1184
- expect(having_and_belonging_to_many_relatives(validate: false)).
1185
- not_to have_and_belong_to_many(:relatives).validate
1186
- end
1187
-
1188
- it 'matches validate(false) to having no validate option specified' do
1189
- expect(having_and_belonging_to_many_relatives).
1190
- to have_and_belong_to_many(:relatives).validate(false)
1191
- end
1192
- end
1193
-
1194
- def having_and_belonging_to_many_relatives(options = {})
1195
- define_model :relative
1196
- define_model :people_relative, id: false, person_id: :integer,
1197
- relative_id: :integer
1198
- define_model :person do
1199
- has_and_belongs_to_many :relatives
1200
- end.new
1201
- end
1202
-
1203
- def having_and_belonging_to_many_non_existent_class(model_name, assoc_name, options = {})
1204
- define_model model_name do
1205
- has_and_belongs_to_many assoc_name, options
1206
- end.new
1207
- end
1208
- end
1209
-
1210
- def define_association_with_conditions(model, macro, name, conditions, other_options={})
1211
- args = []
1212
- options = {}
1213
- if Shoulda::Matchers::RailsShim.active_record_major_version == 4
1214
- args << proc { where(conditions) }
1215
- else
1216
- options[:conditions] = conditions
1217
- end
1218
- args << options
1219
- model.__send__(macro, name, *args)
1220
- end
1221
-
1222
- def define_association_with_order(model, macro, name, order, other_options={})
1223
- args = []
1224
- options = {}
1225
- if Shoulda::Matchers::RailsShim.active_record_major_version == 4
1226
- args << proc { order(order) }
1227
- else
1228
- options[:order] = order
1229
- end
1230
- args << options
1231
- model.__send__(macro, name, *args)
1232
- end
1233
-
1234
- def dependent_options
1235
- case Rails.version
1236
- when /\A3/
1237
- [:destroy, :delete, :nullify, :restrict]
1238
- when /\A4/
1239
- [:destroy, :delete, :nullify, :restrict_with_exception, :restrict_with_error]
1240
- end
1241
- end
1242
- end