shoulda-matchers 2.6.1 → 2.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +9 -0
  4. data/.yardopts +8 -0
  5. data/Appraisals +82 -33
  6. data/Gemfile +18 -2
  7. data/Gemfile.lock +13 -1
  8. data/NEWS.md +27 -2
  9. data/README.md +83 -1329
  10. data/Rakefile +118 -1
  11. data/cucumber.yml +1 -0
  12. data/doc_config/gh-pages/index.html.erb +9 -0
  13. data/doc_config/yard/setup.rb +22 -0
  14. data/doc_config/yard/templates/default/fulldoc/html/css/bootstrap.css +5967 -0
  15. data/doc_config/yard/templates/default/fulldoc/html/css/full_list.css +12 -0
  16. data/doc_config/yard/templates/default/fulldoc/html/css/global.css +45 -0
  17. data/doc_config/yard/templates/default/fulldoc/html/css/solarized.css +69 -0
  18. data/doc_config/yard/templates/default/fulldoc/html/css/style.css +283 -0
  19. data/doc_config/yard/templates/default/fulldoc/html/full_list.erb +32 -0
  20. data/doc_config/yard/templates/default/fulldoc/html/full_list_class.erb +1 -0
  21. data/doc_config/yard/templates/default/fulldoc/html/full_list_method.erb +8 -0
  22. data/doc_config/yard/templates/default/fulldoc/html/js/app.js +298 -0
  23. data/doc_config/yard/templates/default/fulldoc/html/js/full_list.js +1 -0
  24. data/doc_config/yard/templates/default/fulldoc/html/js/jquery.stickyheaders.js +289 -0
  25. data/doc_config/yard/templates/default/fulldoc/html/js/underscore.min.js +6 -0
  26. data/doc_config/yard/templates/default/fulldoc/html/setup.rb +8 -0
  27. data/doc_config/yard/templates/default/layout/html/breadcrumb.erb +14 -0
  28. data/doc_config/yard/templates/default/layout/html/fonts.erb +1 -0
  29. data/doc_config/yard/templates/default/layout/html/layout.erb +23 -0
  30. data/doc_config/yard/templates/default/layout/html/search.erb +13 -0
  31. data/doc_config/yard/templates/default/layout/html/setup.rb +40 -0
  32. data/doc_config/yard/templates/default/method_details/html/source.erb +10 -0
  33. data/doc_config/yard/templates/default/module/html/box_info.erb +31 -0
  34. data/docs.watchr +5 -0
  35. data/features/rails_integration.feature +32 -0
  36. data/features/step_definitions/rails_steps.rb +55 -9
  37. data/features/support/env.rb +1 -0
  38. data/gemfiles/3.0.gemfile +13 -1
  39. data/gemfiles/3.0.gemfile.lock +13 -1
  40. data/gemfiles/3.1.gemfile +17 -2
  41. data/gemfiles/3.1.gemfile.lock +31 -2
  42. data/gemfiles/3.1_1.9.2.gemfile +33 -0
  43. data/gemfiles/3.1_1.9.2.gemfile.lock +203 -0
  44. data/gemfiles/3.2.gemfile +18 -2
  45. data/gemfiles/3.2.gemfile.lock +32 -2
  46. data/gemfiles/3.2_1.9.2.gemfile +32 -0
  47. data/gemfiles/3.2_1.9.2.gemfile.lock +200 -0
  48. data/gemfiles/4.0.0.gemfile +20 -1
  49. data/gemfiles/4.0.0.gemfile.lock +46 -2
  50. data/gemfiles/4.0.1.gemfile +20 -1
  51. data/gemfiles/4.0.1.gemfile.lock +46 -2
  52. data/gemfiles/4.1.gemfile +21 -2
  53. data/gemfiles/4.1.gemfile.lock +47 -4
  54. data/lib/shoulda/matchers/action_controller.rb +0 -20
  55. data/lib/shoulda/matchers/action_controller/callback_matcher.rb +119 -28
  56. data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +22 -6
  57. data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +43 -10
  58. data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +40 -13
  59. data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +63 -11
  60. data/lib/shoulda/matchers/action_controller/rescue_from_matcher.rb +34 -1
  61. data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +84 -15
  62. data/lib/shoulda/matchers/action_controller/route_matcher.rb +84 -28
  63. data/lib/shoulda/matchers/action_controller/route_params.rb +4 -3
  64. data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +76 -13
  65. data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +147 -13
  66. data/lib/shoulda/matchers/action_controller/strong_parameters_matcher.rb +148 -2
  67. data/lib/shoulda/matchers/active_model.rb +0 -25
  68. data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +66 -9
  69. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +161 -19
  70. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +5 -5
  71. data/lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb +92 -13
  72. data/lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb +218 -16
  73. data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +198 -32
  74. data/lib/shoulda/matchers/active_model/errors.rb +5 -2
  75. data/lib/shoulda/matchers/active_model/exception_message_finder.rb +1 -1
  76. data/lib/shoulda/matchers/active_model/have_secure_password_matcher.rb +29 -8
  77. data/lib/shoulda/matchers/active_model/helpers.rb +20 -8
  78. data/lib/shoulda/matchers/active_model/numericality_matchers.rb +9 -0
  79. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +4 -6
  80. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +4 -3
  81. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +3 -2
  82. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +4 -3
  83. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +4 -3
  84. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +52 -14
  85. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +51 -13
  86. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +53 -7
  87. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +275 -19
  88. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +84 -14
  89. data/lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb +170 -41
  90. data/lib/shoulda/matchers/active_model/validation_matcher.rb +20 -15
  91. data/lib/shoulda/matchers/active_model/validation_message_finder.rb +1 -2
  92. data/lib/shoulda/matchers/active_record.rb +1 -12
  93. data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +89 -15
  94. data/lib/shoulda/matchers/active_record/association_matcher.rb +726 -70
  95. data/lib/shoulda/matchers/active_record/association_matchers.rb +9 -0
  96. data/lib/shoulda/matchers/active_record/association_matchers/counter_cache_matcher.rb +4 -3
  97. data/lib/shoulda/matchers/active_record/association_matchers/dependent_matcher.rb +4 -3
  98. data/lib/shoulda/matchers/active_record/association_matchers/inverse_of_matcher.rb +4 -3
  99. data/lib/shoulda/matchers/active_record/association_matchers/model_reflection.rb +2 -1
  100. data/lib/shoulda/matchers/active_record/association_matchers/model_reflector.rb +4 -3
  101. data/lib/shoulda/matchers/active_record/association_matchers/option_verifier.rb +4 -5
  102. data/lib/shoulda/matchers/active_record/association_matchers/order_matcher.rb +4 -3
  103. data/lib/shoulda/matchers/active_record/association_matchers/source_matcher.rb +4 -3
  104. data/lib/shoulda/matchers/active_record/association_matchers/through_matcher.rb +4 -3
  105. data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +79 -15
  106. data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +64 -15
  107. data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +21 -7
  108. data/lib/shoulda/matchers/active_record/serialize_matcher.rb +85 -10
  109. data/lib/shoulda/matchers/assertion_error.rb +7 -1
  110. data/lib/shoulda/matchers/doublespeak.rb +2 -1
  111. data/lib/shoulda/matchers/doublespeak/double.rb +3 -1
  112. data/lib/shoulda/matchers/doublespeak/double_collection.rb +2 -1
  113. data/lib/shoulda/matchers/doublespeak/double_implementation_registry.rb +1 -0
  114. data/lib/shoulda/matchers/doublespeak/object_double.rb +2 -1
  115. data/lib/shoulda/matchers/doublespeak/proxy_implementation.rb +2 -1
  116. data/lib/shoulda/matchers/doublespeak/structs.rb +2 -0
  117. data/lib/shoulda/matchers/doublespeak/stub_implementation.rb +2 -1
  118. data/lib/shoulda/matchers/doublespeak/world.rb +3 -4
  119. data/lib/shoulda/matchers/error.rb +1 -0
  120. data/lib/shoulda/matchers/independent/delegate_matcher.rb +108 -20
  121. data/lib/shoulda/matchers/independent/delegate_matcher/stubbed_target.rb +4 -3
  122. data/lib/shoulda/matchers/integrations/nunit_test_case_detection.rb +3 -0
  123. data/lib/shoulda/matchers/rails_shim.rb +3 -2
  124. data/lib/shoulda/matchers/version.rb +2 -1
  125. data/lib/shoulda/matchers/warn.rb +1 -0
  126. data/script/SUPPORTED_VERSIONS +1 -0
  127. data/script/install_gems_in_all_appraisals +14 -0
  128. data/script/run_all_tests +14 -0
  129. data/shoulda-matchers.gemspec +0 -10
  130. data/spec/report_warnings.rb +7 -0
  131. data/spec/shoulda/matchers/action_controller/route_matcher_spec.rb +1 -1
  132. data/spec/shoulda/matchers/action_controller/strong_parameters_matcher_spec.rb +9 -0
  133. data/spec/shoulda/matchers/active_model/validate_uniqueness_of_matcher_spec.rb +0 -36
  134. data/spec/shoulda/matchers/active_model/validation_message_finder_spec.rb +2 -2
  135. data/spec/shoulda/matchers/doublespeak/double_spec.rb +1 -1
  136. data/spec/shoulda/matchers/doublespeak/world_spec.rb +11 -29
  137. data/spec/shoulda/matchers/doublespeak_spec.rb +3 -3
  138. data/spec/spec_helper.rb +17 -0
  139. data/spec/support/class_builder.rb +4 -0
  140. data/spec/support/test_application.rb +1 -1
  141. data/spec/warnings_spy.rb +64 -0
  142. data/spec/warnings_spy/filesystem.rb +45 -0
  143. data/spec/warnings_spy/partitioner.rb +29 -0
  144. data/spec/warnings_spy/reader.rb +64 -0
  145. data/spec/warnings_spy/reporter.rb +87 -0
  146. metadata +49 -134
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b85c41db70063753c27b74688e7f408a7029b260
4
- data.tar.gz: 91b6b554334647019c6d128c91185c82c16fc7c6
3
+ metadata.gz: 8ff48aa28034edc27f14e97808a24f0e777cf3ab
4
+ data.tar.gz: 6432f92a9497036932281d941a437b40f5636e06
5
5
  SHA512:
6
- metadata.gz: a2c0632389bba8f78c1aa1064a02fdcf30aad6265c05f19fa0de73ed4b510bb8a1a29e7b5848fbbbadece76474f33603025d7ab9ed145a081fcb1e068a046b16
7
- data.tar.gz: 3abc44fa128068136b1674fb922bb0468993f8f76f4d047bffe8833cb94e41c5ce6e8379337eb86c5cf991369b8dadf4baf0dc84fc57663b2eb41c361cf123cb
6
+ metadata.gz: 7f64a534e64d8f070d5e5d524bb9b21df80fa2afe93f4be3cf7b44e6ecb7a33fff7c91b87756194548fb0670548d0302467ce2d83e1371c42bf80f7283c1673b
7
+ data.tar.gz: 940a2d667949ef94d42ada95554fda4a288af2d8cfa95f307900a3e345f46d867ca9cae347758e1f3bf2782e482397cc83a109aeb7359fbb3c69406f0abb0523
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  *.swo
3
3
  *.swp
4
4
  .bundle
5
+ .gh-pages
5
6
  .svn/
6
7
  .yardoc
7
8
  coverage
data/.travis.yml CHANGED
@@ -16,6 +16,10 @@ matrix:
16
16
  - rvm: rbx-19mode
17
17
  - rvm: jruby-19mode
18
18
  include:
19
+ - rvm: 1.9.2
20
+ gemfile: gemfiles/3.1_1.9.2.gemfile
21
+ - rvm: 1.9.2
22
+ gemfile: gemfiles/3.2_1.9.2.gemfile
19
23
  - rvm: 1.9.3
20
24
  gemfile: gemfiles/4.0.0.gemfile
21
25
  - rvm: 1.9.3
@@ -34,3 +38,8 @@ matrix:
34
38
  gemfile: gemfiles/3.2.gemfile
35
39
  - rvm: jruby-19mode
36
40
  gemfile: gemfiles/3.2.gemfile
41
+ exclude:
42
+ - rvm: 1.9.2
43
+ gemfile: gemfiles/3.1.gemfile
44
+ - rvm: 1.9.2
45
+ gemfile: gemfiles/3.2.gemfile
data/.yardopts ADDED
@@ -0,0 +1,8 @@
1
+ --no-private
2
+ --protected
3
+ --readme README.md
4
+ --files lib/**/*.rb
5
+ --markup markdown
6
+ --hide-tag return
7
+ --hide-tag param
8
+ -e ./doc_config/yard/setup.rb
data/Appraisals CHANGED
@@ -1,5 +1,42 @@
1
- rails_4_0 = proc do
1
+ ruby_version = Gem::Version.new(RUBY_VERSION + '')
2
+
3
+ spring = proc do
4
+ gem 'spring'
5
+ gem 'spring-commands-rspec'
6
+ end
7
+
8
+ rails_3 = proc do
9
+ gem 'strong_parameters'
10
+ end
11
+
12
+ rails_3_1 = proc do
13
+ instance_eval(&rails_3)
14
+ gem 'rails', '~> 3.1.8'
15
+ gem 'bcrypt-ruby', '~> 3.0.0'
16
+ gem 'jquery-rails'
17
+ gem 'sass-rails', '~> 3.1.5'
18
+ gem 'coffee-rails', '~> 3.1.1'
19
+ gem 'uglifier', '>= 1.0.3'
20
+ end
21
+
22
+ rails_3_2 = proc do
23
+ instance_eval(&rails_3)
24
+ gem 'rails', '~> 3.2.13'
25
+ gem 'bcrypt-ruby', '~> 3.0.0'
26
+ gem 'jquery-rails'
27
+ gem 'sass-rails', '~> 3.2.3'
28
+ gem 'coffee-rails', '~> 3.2.1'
29
+ gem 'uglifier', '>= 1.0.3'
30
+ end
31
+
32
+ rails_4 = proc do
33
+ instance_eval(&spring)
34
+ gem 'uglifier', '>= 1.3.0'
35
+ gem 'coffee-rails', '~> 4.0.0'
2
36
  gem 'jquery-rails'
37
+ gem 'turbolinks'
38
+ gem 'jbuilder', '~> 1.2'
39
+ gem 'sdoc'
3
40
  gem 'activeresource', '4.0.0'
4
41
  # Test suite makes heavy use of attr_accessible
5
42
  gem 'protected_attributes'
@@ -7,47 +44,59 @@ end
7
44
 
8
45
  #---
9
46
 
10
- if RUBY_VERSION < '2.0'
47
+ if Gem::Requirement.new('< 2').satisfied_by?(ruby_version)
11
48
  appraise '3.0' do
49
+ instance_eval(&rails_3)
12
50
  gem 'rails', '~> 3.0.17'
13
- gem 'strong_parameters'
14
51
  end
15
52
 
16
- appraise '3.1' do
17
- gem 'rails', '~> 3.1.8'
18
- gem 'bcrypt-ruby', '~> 3.0.0'
19
- gem 'jquery-rails'
20
- gem 'sass-rails'
21
- gem 'strong_parameters'
53
+ if Gem::Requirement.new('= 1.9.2').satisfied_by?(ruby_version)
54
+ appraise '3.1-1.9.2' do
55
+ instance_eval(&rails_3_1)
56
+ gem 'turn', '0.8.2'
57
+ end
58
+ else
59
+ appraise '3.1' do
60
+ instance_eval(&rails_3_1)
61
+ gem 'turn', '~> 0.8.3'
62
+ end
22
63
  end
23
64
  end
24
65
 
25
- appraise '3.2' do
26
- gem 'rails', '~> 3.2.13'
27
- gem 'bcrypt-ruby', '~> 3.0.0'
28
- gem 'jquery-rails'
29
- gem 'sass-rails'
30
- gem 'strong_parameters'
66
+ if Gem::Requirement.new('= 1.9.2').satisfied_by?(ruby_version)
67
+ appraise '3.2-1.9.2' do
68
+ instance_eval(&rails_3_2)
69
+ end
70
+ else
71
+ appraise '3.2' do
72
+ instance_eval(&rails_3_2)
73
+ instance_eval(&spring)
74
+ end
31
75
  end
32
76
 
33
- appraise '4.0.0' do
34
- instance_eval(&rails_4_0)
35
- gem 'rails', '4.0.0'
36
- gem 'sass-rails', '4.0.0'
37
- gem 'bcrypt-ruby', '~> 3.0.0'
38
- end
77
+ if Gem::Requirement.new('> 1.9.2').satisfied_by?(ruby_version)
78
+ appraise '4.0.0' do
79
+ instance_eval(&rails_4)
80
+ gem 'rails', '4.0.0'
81
+ gem 'sass-rails', '~> 4.0.0'
82
+ gem 'bcrypt-ruby', '~> 3.0.0'
83
+ end
39
84
 
40
- appraise '4.0.1' do
41
- instance_eval(&rails_4_0)
42
- gem 'rails', '4.0.1'
43
- gem 'sass-rails', '4.0.1'
44
- gem 'bcrypt-ruby', '~> 3.1.2'
45
- end
85
+ appraise '4.0.1' do
86
+ instance_eval(&rails_4)
87
+ gem 'rails', '4.0.1'
88
+ gem 'sass-rails', '~> 4.0.0'
89
+ gem 'bcrypt-ruby', '~> 3.1.2'
90
+ end
46
91
 
47
- appraise '4.1' do
48
- instance_eval(&rails_4_0)
49
- gem 'rails', '~> 4.1.0'
50
- gem 'sass-rails', '4.0.3'
51
- gem 'bcrypt-ruby', '~> 3.1.2'
52
- gem "protected_attributes", '~> 1.0.6'
92
+ appraise '4.1' do
93
+ instance_eval(&rails_4)
94
+ gem 'rails', '~> 4.1.0'
95
+ gem 'jbuilder', '~> 2.0'
96
+ gem 'sass-rails', '~> 4.0.3'
97
+ gem 'sdoc', '~> 0.4.0'
98
+ gem 'bcrypt', '~> 3.1.7'
99
+ gem 'protected_attributes', "~> 1.0.6"
100
+ gem 'spring'
101
+ end
53
102
  end
data/Gemfile CHANGED
@@ -2,12 +2,28 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'appraisal', '~> 1.0.0.beta2'
6
+ gem 'aruba'
7
+ gem 'bourne', '~> 1.3'
8
+ gem 'bundler', '~> 1.1'
9
+ gem 'cucumber', '~> 1.1'
10
+ gem 'pry'
11
+ gem 'rails', '~> 3.0'
12
+ gem 'rake', '>= 0.9.2'
13
+ gem 'rspec-rails', '>= 2.13.1', '< 3'
14
+
15
+ # YARD
16
+ gem 'yard'
17
+ gem 'redcarpet'
18
+ gem 'pygments.rb'
19
+ gem 'watchr'
20
+
5
21
  # For test Rails application
6
22
  gem 'shoulda-context', '~> 1.2.0'
7
23
  gem 'sqlite3', :platform => :ruby
8
24
 
9
- # Can't wrap in platform :jruby do...end block because appraisal doesn't support
10
- # it
25
+ # Can't wrap in platform :jruby do...end block because appraisal doesn't
26
+ # support it
11
27
  gem 'activerecord-jdbc-adapter', :platform => :jruby
12
28
  gem 'activerecord-jdbcsqlite3-adapter', :platform => :jruby
13
29
  gem 'jdbc-sqlite3', :platform => :jruby
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- shoulda-matchers (2.6.1)
4
+ shoulda-matchers (2.6.2)
5
5
  activesupport (>= 3.0.0)
6
6
 
7
7
  GEM
@@ -75,10 +75,14 @@ GEM
75
75
  multi_json (1.8.4)
76
76
  multi_test (0.0.3)
77
77
  polyglot (0.3.3)
78
+ posix-spawn (0.3.8)
78
79
  pry (0.9.12.6)
79
80
  coderay (~> 1.0)
80
81
  method_source (~> 0.8)
81
82
  slop (~> 3.4)
83
+ pygments.rb (0.3.7)
84
+ posix-spawn (~> 0.3.6)
85
+ yajl-ruby (~> 1.1.0)
82
86
  rack (1.4.5)
83
87
  rack-cache (1.2)
84
88
  rack (>= 0.4)
@@ -104,6 +108,7 @@ GEM
104
108
  rake (10.1.1)
105
109
  rdoc (3.12.2)
106
110
  json (~> 1.4)
111
+ redcarpet (3.0.0)
107
112
  rspec-core (2.14.7)
108
113
  rspec-expectations (2.14.4)
109
114
  diff-lcs (>= 1.1.3, < 2.0)
@@ -130,6 +135,9 @@ GEM
130
135
  polyglot
131
136
  polyglot (>= 0.3.1)
132
137
  tzinfo (0.3.38)
138
+ watchr (0.7)
139
+ yajl-ruby (1.1.0)
140
+ yard (0.8.7.3)
133
141
 
134
142
  PLATFORMS
135
143
  ruby
@@ -145,10 +153,14 @@ DEPENDENCIES
145
153
  jdbc-sqlite3
146
154
  jruby-openssl
147
155
  pry
156
+ pygments.rb
148
157
  rails (~> 3.0)
149
158
  rake (>= 0.9.2)
159
+ redcarpet
150
160
  rspec-rails (>= 2.13.1, < 3)
151
161
  shoulda-context (~> 1.2.0)
152
162
  shoulda-matchers!
153
163
  sqlite3
154
164
  therubyrhino
165
+ watchr
166
+ yard
data/NEWS.md CHANGED
@@ -1,12 +1,37 @@
1
+ # HEAD
2
+
3
+ # 2.6.2
4
+
5
+ ### Bug fixes
6
+
7
+ * If you have a Rails >= 4.1 project and you are running tests using Spring,
8
+ matchers that depend on assertions within Rails' testing layer (e.g.
9
+ `render_template` and `route`) will no longer fail.
10
+
11
+ * Fix `permit` so that it can be used more than once in the same test.
12
+
13
+ * Revert change to `validate_uniqueness_of` made in 2.6.0 so that it no longer
14
+ provides default values for non-primary, non-nullable columns. This approach
15
+ was causing test failures because it makes the assumption that none of these
16
+ columns allow only specific values, which is not true. If you get an error
17
+ from `validate_uniqueness_of`, your best bet continues to be creating a record
18
+ manually and calling `validate_uniqueness_of` on that instead.
19
+
20
+ ### Other changes
21
+
22
+ * The majority of warnings that the gem produced have been removed. The gem
23
+ still produces warnings under Ruby 1.9.3; we will address this in a future
24
+ release.
25
+
1
26
  # 2.6.1
2
27
 
3
- ## Features
28
+ ### Features
4
29
 
5
30
  * Teach `with_message` qualifier on `allow_value` to accept a hash of i18n
6
31
  interpolation values:
7
32
  `allow_value('foo').for(:attr).with_message(:greater_than, values: { count: 20 })`.
8
33
 
9
- ## Bug fixes
34
+ ### Bug fixes
10
35
 
11
36
  * Revert changes to `validate_numericality_of` made in the last release, which
12
37
  made it so that comparison qualifiers specified on the validation are tested
data/README.md CHANGED
@@ -6,28 +6,92 @@ shoulda-matchers provides Test::Unit- and RSpec-compatible one-liners that test
6
6
  common Rails functionality. These tests would otherwise be much longer, more
7
7
  complex, and error-prone.
8
8
 
9
+ ### ActiveModel Matchers
10
+
11
+ * **[allow_mass_assignment_of](lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb)**
12
+ tests usage of Rails 3's `attr_accessible` and `attr_protected` macros.
13
+ * **[allow_value](lib/shoulda/matchers/active_model/allow_value_matcher.rb)** tests usage of
14
+ the `validates_format_of` validation.
15
+ * **[ensure_inclusion_of](lib/shoulda/matchers/active_model/ensure_inclusion_of_matcher.rb)** tests
16
+ usage of `validates_inclusion_of`.
17
+ * **[ensure_exclusion_of](lib/shoulda/matchers/active_model/ensure_exclusion_of_matcher.rb)** tests
18
+ usage of `validates_exclusion_of`.
19
+ * **[ensure_length_of](lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb)** tests usage
20
+ of `validates_length_of`.
21
+ * **[have_secure_password](lib/shoulda/matchers/active_model/have_secure_password_matcher.rb)** tests
22
+ usage of `has_secure_password`.
23
+ * **[validate_confirmation_of](lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb)**
24
+ tests usage of `validates_confirmation_of`.
25
+ * **[validate_numericality_of](lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb)**
26
+ tests usage of `validates_numericality_of`.
27
+ * **[validate_presence_of](lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb)** tests
28
+ usage of `validates_presence_of`.
29
+ * **[validate_uniqueness_of](lib/shoulda/matchers/active_model/validate_uniqueness_of_matcher.rb)** tests
30
+ usage of `validates_uniqueness_of`.
31
+
32
+ ### ActiveRecord Matchers
33
+
34
+ * **[accept_nested_attributes_for](lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb)**
35
+ tests usage of the `accepts_nested_attributes_for` macro.
36
+ * **[belong_to](lib/shoulda/matchers/active_record/association_matcher.rb)** tests
37
+ your `belongs_to` associations.
38
+ * **[have_many](lib/shoulda/matchers/active_record/association_matcher.rb)** tests
39
+ your `has_many` associations.
40
+ * **[have_one](lib/shoulda/matchers/active_record/association_matcher.rb)** tests your
41
+ `has_one` associations.
42
+ * **[have_and_belong_to_many](lib/shoulda/matchers/active_record/association_matcher.rb)**
43
+ tests your `has_and_belongs_to_many` associations.
44
+ * **[have_db_column](lib/shoulda/matchers/active_record/have_db_column_matcher.rb)** tests that
45
+ the table that backs your model has a specific column.
46
+ * **[have_db_index](lib/shoulda/matchers/active_record/have_db_index_matcher.rb)** tests that the
47
+ table that backs your model has an index on a specific column.
48
+ * **[have_readonly_attribute](lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb)**
49
+ tests usage of the `attr_readonly` macro.
50
+ * **[serialize](lib/shoulda/matchers/active_record/serialize_matcher.rb)** tests usage of the
51
+ `serialize` macro.
52
+
53
+ ### ActionController Matchers
54
+
55
+ * **[filter_param](lib/shoulda/matchers/action_controller/filter_param_matcher.rb)** tests
56
+ parameter filtering configuration.
57
+ * **[redirect_to](lib/shoulda/matchers/action_controller/redirect_to_matcher.rb)** tests that
58
+ an action redirects to a certain location.
59
+ * **[render_template](lib/shoulda/matchers/action_controller/render_template_matcher.rb)** tests
60
+ that an action renders a template.
61
+ * **[render_with_layout](lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb)** tests
62
+ that an action is rendereed with a certain layout.
63
+ * **[rescue_from](lib/shoulda/matchers/action_controller/rescue_from_matcher.rb)** tests usage
64
+ of the `rescue_from` macro.
65
+ * **[respond_with](lib/shoulda/matchers/action_controller/respond_with_matcher.rb)** tests that
66
+ an action responds with a certain status code.
67
+ * **[route](lib/shoulda/matchers/action_controller/route_matcher.rb)** tests your routes.
68
+ * **[set_session](lib/shoulda/matchers/action_controller/set_session_matcher.rb)** makes
69
+ assertions on the `session` hash.
70
+ * **[set_the_flash](lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb)** makes
71
+ assertions on the `flash` hash.
72
+
73
+ ### Independent Matchers
74
+
75
+ * **[delegate_matcher](lib/shoulda/matchers/independent/delegate_matcher.rb)**
76
+ tests that an object forwards messages to other, internal objects by way of
77
+ delegation.
78
+
9
79
  ## Installation
10
80
 
11
81
  ### RSpec
12
82
 
13
83
  Include the gem in your Gemfile:
14
84
 
15
- ```ruby
85
+ ``` ruby
16
86
  group :test do
17
- gem 'shoulda-matchers'
87
+ gem 'shoulda-matchers', require: false
18
88
  end
19
89
  ```
20
90
 
21
- Note that if you're using a Rails preloader like Spring, you'll need to manually
22
- require shoulda-matchers in your spec_helper after you require RSpec:
23
-
24
- ```ruby
25
- # Gemfile
26
- group :test do
27
- gem 'shoulda-matchers', require: false
28
- end
91
+ Then require the gem following rspec-rails in your rails_helper (or spec_helper
92
+ if you're using RSpec 2.x):
29
93
 
30
- # spec_helper
94
+ ``` ruby
31
95
  require 'rspec/rails'
32
96
  require 'shoulda/matchers'
33
97
  ```
@@ -72,1329 +136,19 @@ gem 'shoulda-matchers'
72
136
  gem 'activemodel'
73
137
  ```
74
138
 
75
- ## Usage
76
-
77
- Different matchers apply to different parts of Rails:
78
-
79
- * [ActiveModel](#activemodel-matchers)
80
- * [ActiveRecord](#activerecord-matchers)
81
- * [ActionController](#actioncontroller-matchers)
82
-
83
- ### ActiveModel Matchers
84
-
85
- *Jump to: [allow_mass_assignment_of](#allow_mass_assignment_of), [allow_value](#allow_value), [ensure_inclusion_of](#ensure_inclusion_of), [ensure_exclusion_of](#ensure_exclusion_of), [ensure_length_of](#ensure_length_of), [have_secure_password](#have_secure_password), [validate_absence_of](#validate_absence_of), [validate_acceptance_of](#validate_acceptance_of), [validate_confirmation_of](#validate_confirmation_of), [validate_numericality_of](#validate_numericality_of), [validate_presence_of](#validate_presence_of), [validate_uniqueness_of](#validate_uniqueness_of)*
86
-
87
- Note that all of the examples in this section are based on an ActiveRecord
88
- model for simplicity, but these matchers will work just as well using an
89
- ActiveModel model.
90
-
91
- #### allow_mass_assignment_of
92
-
93
- The `allow_mass_assignment_of` matcher tests usage of Rails 3's
94
- `attr_accessible` and `attr_protected` macros, asserting that attributes can or
95
- cannot be mass-assigned on a record.
96
-
97
- ```ruby
98
- class Post < ActiveRecord::Base
99
- attr_accessible :title
100
- attr_accessible :published_status, as: :admin
101
- end
102
-
103
- class User < ActiveRecord::Base
104
- attr_protected :encrypted_password
105
- end
106
-
107
- # RSpec
108
- describe Post do
109
- it { should allow_mass_assignment_of(:title) }
110
- it { should allow_mass_assignment_of(:published_status).as(:admin) }
111
- end
112
-
113
- describe User do
114
- it { should_not allow_mass_assignment_of(:encrypted_password) }
115
- end
116
-
117
- # Test::Unit
118
- class PostTest < ActiveSupport::TestCase
119
- should allow_mass_assignment_of(:title)
120
- should allow_mass_assignment_of(:published_status).as(:admin)
121
- end
122
-
123
- class UserTest < ActiveSupport::TestCase
124
- should_not allow_mass_assignment_of(:encrypted_password)
125
- end
126
- ```
127
-
128
- #### allow_value
129
-
130
- The `allow_value` matcher tests usage of the `validates_format_of` validation.
131
- It asserts that an attribute can be set to one or more values, succeeding if
132
- none of the values cause the record to be invalid.
133
-
134
- ```ruby
135
- class UserProfile < ActiveRecord::Base
136
- validates_format_of :website_url, with: URI.regexp
137
-
138
- validates_format_of :birthday_as_string,
139
- with: /^(\d+)-(\d+)-(\d+)$/,
140
- on: :create
141
-
142
- validates_format_of :state,
143
- with: /^(open|closed)$/,
144
- message: 'State must be open or closed'
145
- end
146
-
147
- # RSpec
148
- describe UserProfile do
149
- it { should allow_value('http://foo.com', 'http://bar.com/baz').for(:website_url) }
150
- it { should_not allow_value('asdfjkl').for(:website_url) }
151
-
152
- it do
153
- should allow_value('2013-01-01').
154
- for(:birthday_as_string).
155
- on(:create)
156
- end
157
-
158
- it do
159
- should allow_value('open', 'closed').
160
- for(:state).
161
- with_message('State must be open or closed')
162
- end
163
- end
164
-
165
- # Test::Unit
166
- class UserProfileTest < ActiveSupport::TestCase
167
- should allow_value('http://foo.com', 'http://bar.com/baz').for(:website_url)
168
- should_not allow_value('asdfjkl').for(:website_url)
169
-
170
- should allow_value('2013-01-01').
171
- for(:birthday_as_string).
172
- on(:create)
173
-
174
- should allow_value('open', 'closed').
175
- for(:state).
176
- with_message('State must be open or closed')
177
- end
178
- ```
179
-
180
- **PLEASE NOTE:** Using `should_not` with `allow_value` completely negates the
181
- assertion. This means that if multiple values are given to `allow_value`, the
182
- matcher succeeds once it sees the *first* value that will cause the record to be
183
- invalid:
184
-
185
- ```ruby
186
- describe User do
187
- # 'b' and 'c' will not be tested
188
- it { should_not allow_value('a', 'b', 'c').for(:website_url) }
189
- end
190
- ```
191
-
192
- #### ensure_inclusion_of
193
-
194
- The `ensure_inclusion_of` matcher tests usage of the `validates_inclusion_of`
195
- validation, asserting that an attribute can take a set of values and cannot
196
- take values outside of this set.
197
-
198
- ```ruby
199
- class Issue < ActiveRecord::Base
200
- validates_inclusion_of :state, in: %w(open resolved unresolved)
201
- validates_inclusion_of :priority, in: 1..5
202
-
203
- validates_inclusion_of :severity,
204
- in: %w(low medium high),
205
- message: 'Severity must be low, medium, or high'
206
- end
207
-
208
- # RSpec
209
- describe Issue do
210
- it { should ensure_inclusion_of(:state).in_array(%w(open resolved unresolved)) }
211
- it { should ensure_inclusion_of(:priority).in_range(1..5) }
212
-
213
- it do
214
- should ensure_inclusion_of(:severity).
215
- in_array(%w(low medium high)).
216
- with_message('Severity must be low, medium, or high')
217
- end
218
- end
219
-
220
- # Test::Unit
221
- class IssueTest < ActiveSupport::TestCase
222
- should ensure_inclusion_of(:state).in_array(%w(open resolved unresolved))
223
- should ensure_inclusion_of(:priority).in_range(1..5)
224
-
225
- should ensure_inclusion_of(:severity).
226
- in_array(%w(low medium high)).
227
- with_message('Severity must be low, medium, or high')
228
- end
229
- ```
230
-
231
- #### ensure_exclusion_of
232
-
233
- The `ensure_exclusion_of` matcher tests usage of the `validates_exclusion_of`
234
- validation, asserting that an attribute cannot take a set of values.
235
-
236
- ```ruby
237
- class Game < ActiveRecord::Base
238
- validates_exclusion_of :supported_os, in: ['Mac', 'Linux']
239
- validates_exclusion_of :floors_with_enemies, in: 5..8
240
-
241
- validates_exclusion_of :weapon,
242
- in: ['pistol', 'paintball gun', 'stick'],
243
- message: 'You chose a puny weapon'
244
- end
245
-
246
- # RSpec
247
- describe Game do
248
- it { should ensure_exclusion_of(:supported_os).in_array(['Mac', 'Linux']) }
249
- it { should ensure_exclusion_of(:floors_with_enemies).in_range(5..8) }
250
-
251
- it do
252
- should ensure_exclusion_of(:weapon).
253
- in_array(['pistol', 'paintball gun', 'stick']).
254
- with_message('You chose a puny weapon')
255
- end
256
- end
257
-
258
- # Test::Unit
259
- class GameTest < ActiveSupport::TestCase
260
- should ensure_exclusion_of(:supported_os).in_array(['Mac', 'Linux'])
261
- should ensure_exclusion_of(:floors_with_enemies).in_range(5..8)
262
-
263
- should ensure_exclusion_of(:weapon).
264
- in_array(['pistol', 'paintball gun', 'stick']).
265
- with_message('You chose a puny weapon')
266
- end
267
- ```
268
-
269
- #### ensure_length_of
270
-
271
- The `ensure_length_of` matcher tests usage of the `validates_length_of` matcher.
272
-
273
- ```ruby
274
- class User < ActiveRecord::Base
275
- validates_length_of :bio, minimum: 15
276
- validates_length_of :favorite_superhero, is: 6
277
- validates_length_of :status_update, maximum: 140
278
- validates_length_of :password, in: 5..30
279
-
280
- validates_length_of :api_token,
281
- in: 10..20,
282
- message: 'API token must be in between 10 and 20 characters'
283
-
284
- validates_length_of :secret_key, in: 15..100,
285
- too_short: 'Secret key must be more than 15 characters',
286
- too_long: 'Secret key cannot be more than 100 characters'
287
- end
288
-
289
- # RSpec
290
- describe User do
291
- it { should ensure_length_of(:bio).is_at_least(15) }
292
- it { should ensure_length_of(:favorite_superhero).is_equal_to(6) }
293
- it { should ensure_length_of(:status_update).is_at_most(140) }
294
- it { should ensure_length_of(:password).is_at_least(5).is_at_most(30) }
295
-
296
- it do
297
- should ensure_length_of(:api_token).
298
- is_at_least(10).
299
- is_at_most(20).
300
- with_message('Password must be in between 10 and 20 characters')
301
- end
302
-
303
- it do
304
- should ensure_length_of(:secret_key).
305
- is_at_least(15).
306
- is_at_most(100).
307
- with_short_message('Secret key must be more than 15 characters').
308
- with_long_message('Secret key cannot be more than 100 characters')
309
- end
310
- end
311
-
312
- # Test::Unit
313
- class UserTest < ActiveSupport::TestCase
314
- should ensure_length_of(:bio).is_at_least(15)
315
- should ensure_length_of(:favorite_superhero).is_equal_to(6)
316
- should ensure_length_of(:status_update).is_at_most(140)
317
- should ensure_length_of(:password).is_at_least(5).is_at_most(30)
318
-
319
- should ensure_length_of(:api_token).
320
- is_at_least(15).
321
- is_at_most(20).
322
- with_message('Password must be in between 15 and 20 characters')
323
-
324
- should ensure_length_of(:secret_key).
325
- is_at_least(15).
326
- is_at_most(100).
327
- with_short_message('Secret key must be more than 15 characters').
328
- with_long_message('Secret key cannot be more than 100 characters')
329
- end
330
- ```
331
-
332
- #### have_secure_password
333
-
334
- The `have_secure_password` matcher tests usage of the `has_secure_password`
335
- macro.
336
-
337
- ```ruby
338
- class User < ActiveRecord::Base
339
- has_secure_password
340
- end
341
-
342
- # RSpec
343
- describe User do
344
- it { should have_secure_password }
345
- end
346
-
347
- # Test::Unit
348
- class UserTest < ActiveSupport::TestCase
349
- should have_secure_password
350
- end
351
- ```
352
-
353
- #### validate_absence_of
354
-
355
- The `validate_absence_of` matcher tests the usage of the
356
- `validates_absence_of` validation.
357
-
358
- ```ruby
359
- class Tank
360
- include ActiveModel::Model
361
-
362
- validates_absence_of :arms
363
- validates_absence_of :legs,
364
- message: "Tanks don't have legs."
365
- end
366
-
367
- # RSpec
368
- describe Tank do
369
- it { should validate_absence_of(:arms) }
370
-
371
- it do
372
- should validate_absence_of(:legs).
373
- with_message("Tanks don't have legs.")
374
- end
375
- end
376
-
377
- # Test::Unit
378
- class TankTest < ActiveSupport::TestCase
379
- should validate_absence_of(:arms)
380
-
381
- should validate_absence_of(:legs).
382
- with_message("Tanks don't have legs.")
383
- end
384
- ```
385
-
386
- #### validate_acceptance_of
387
-
388
- The `validate_acceptance_of` matcher tests usage of the
389
- `validates_acceptance_of` validation.
390
-
391
- ```ruby
392
- class Registration < ActiveRecord::Base
393
- validates_acceptance_of :eula
394
- validates_acceptance_of :terms_of_service,
395
- message: 'You must accept the terms of service'
396
- end
397
-
398
- # RSpec
399
- describe Registration do
400
- it { should validate_acceptance_of(:eula) }
401
-
402
- it do
403
- should validate_acceptance_of(:terms_of_service).
404
- with_message('You must accept the terms of service')
405
- end
406
- end
407
-
408
- # Test::Unit
409
- class RegistrationTest < ActiveSupport::TestCase
410
- should validate_acceptance_of(:eula)
411
-
412
- should validate_acceptance_of(:terms_of_service).
413
- with_message('You must accept the terms of service')
414
- end
415
- ```
416
-
417
- #### validate_confirmation_of
418
-
419
- The `validate_confirmation_of` matcher tests usage of the
420
- `validates_confirmation_of` validation.
421
-
422
- ```ruby
423
- class User < ActiveRecord::Base
424
- validates_confirmation_of :email
425
- validates_confirmation_of :password, message: 'Please re-enter your password'
426
- end
427
-
428
- # RSpec
429
- describe User do
430
- it do
431
- should validate_confirmation_of(:email)
432
- end
433
-
434
- it do
435
- should validate_confirmation_of(:password).
436
- with_message('Please re-enter your password')
437
- end
438
- end
439
-
440
- # Test::Unit
441
- class UserTest < ActiveSupport::TestCase
442
- should validate_confirmation_of(:email)
443
-
444
- should validate_confirmation_of(:password).
445
- with_message('Please re-enter your password')
446
- end
447
- ```
448
-
449
- #### validate_numericality_of
450
-
451
- The `validate_numericality_of` matcher tests usage of the
452
- `validates_numericality_of` validation.
453
-
454
- ```ruby
455
- class Person < ActiveRecord::Base
456
- validates_numericality_of :gpa
457
- validates_numericality_of :age, only_integer: true
458
- validates_numericality_of :legal_age, greater_than: 21
459
- validates_numericality_of :height, greater_than_or_equal_to: 55
460
- validates_numericality_of :weight, equal_to: 150
461
- validates_numericality_of :number_of_cars, less_than: 2
462
- validates_numericality_of :birth_year, less_than_or_equal_to: 1987
463
- validates_numericality_of :birth_day, odd: true
464
- validates_numericality_of :birth_month, even: true
465
- validates_numericality_of :rank, less_than_or_equal_to: 10, allow_nil: true
466
-
467
- validates_numericality_of :number_of_dependents,
468
- message: 'Number of dependents must be a number'
469
- end
470
-
471
- # RSpec
472
- describe Person do
473
- it { should validate_numericality_of(:gpa) }
474
- it { should validate_numericality_of(:age).only_integer }
475
- it { should validate_numericality_of(:legal_age).is_greater_than(21) }
476
- it { should validate_numericality_of(:height).is_greater_than_or_equal_to(55) }
477
- it { should validate_numericality_of(:weight).is_equal_to(150) }
478
- it { should validate_numericality_of(:number_of_cars).is_less_than(2) }
479
- it { should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987) }
480
- it { should validate_numericality_of(:birth_day).odd }
481
- it { should validate_numericality_of(:birth_month).even }
482
-
483
- it do
484
- should validate_numericality_of(:number_of_dependents).
485
- with_message('Number of dependents must be a number')
486
- end
487
- end
488
-
489
- # Test::Unit
490
- class PersonTest < ActiveSupport::TestCase
491
- should validate_numericality_of(:gpa)
492
- should validate_numericality_of(:age).only_integer
493
- should validate_numericality_of(:legal_age).is_greater_than(21)
494
- should validate_numericality_of(:height).is_greater_than_or_equal_to(55)
495
- should validate_numericality_of(:weight).is_equal_to(150)
496
- should validate_numericality_of(:number_of_cars).is_less_than(2)
497
- should validate_numericality_of(:birth_year).is_less_than_or_equal_to(1987)
498
- should validate_numericality_of(:birth_day).odd
499
- should validate_numericality_of(:birth_month).even
500
-
501
- should validate_numericality_of(:number_of_dependents).
502
- with_message('Number of dependents must be a number')
503
- end
504
- ```
505
-
506
- #### validate_presence_of
507
-
508
- The `validate_presence_of` matcher tests usage of the `validates_presence_of`
509
- matcher.
510
-
511
- ```ruby
512
- class Robot < ActiveRecord::Base
513
- validates_presence_of :arms
514
- validates_presence_of :legs, message: 'Robot has no legs'
515
- end
516
-
517
- # RSpec
518
- describe Robot do
519
- it { should validate_presence_of(:arms) }
520
- it { should validate_presence_of(:legs).with_message('Robot has no legs') }
521
- end
522
-
523
- # Test::Unit
524
- class RobotTest < ActiveSupport::TestCase
525
- should validate_presence_of(:arms)
526
- should validate_presence_of(:legs).with_message('Robot has no legs')
527
- end
528
- ```
529
-
530
- #### validate_uniqueness_of
531
-
532
- The `validate_uniqueness_of` matcher tests usage of the
533
- `validates_uniqueness_of` validation.
534
-
535
- ```ruby
536
- class Post < ActiveRecord::Base
537
- validates_uniqueness_of :permalink
538
- validates_uniqueness_of :slug, scope: :user_id
539
- validates_uniqueness_of :key, case_insensitive: true
540
- validates_uniqueness_of :author_id, allow_nil: true
541
-
542
- validates_uniqueness_of :title, message: 'Please choose another title'
543
- end
544
-
545
- # RSpec
546
- describe Post do
547
- it { should validate_uniqueness_of(:permalink) }
548
- it { should validate_uniqueness_of(:slug).scoped_to(:user_id) }
549
- it { should validate_uniqueness_of(:key).case_insensitive }
550
- it { should validate_uniqueness_of(:author_id).allow_nil }
551
-
552
- it do
553
- should validate_uniqueness_of(:title).
554
- with_message('Please choose another title')
555
- end
556
- end
557
-
558
- # Test::Unit
559
- class PostTest < ActiveSupport::TestCase
560
- should validate_uniqueness_of(:permalink)
561
- should validate_uniqueness_of(:slug).scoped_to(:user_id)
562
- should validate_uniqueness_of(:key).case_insensitive
563
- should validate_uniqueness_of(:author_id).allow_nil
564
-
565
- should validate_uniqueness_of(:title).
566
- with_message('Please choose another title')
567
- end
568
- ```
569
-
570
- **PLEASE NOTE:** This matcher works differently from other validation matchers.
571
- Since the very concept of uniqueness depends on checking against a pre-existing
572
- record in the database, this matcher will first use the model you're testing to
573
- query for such a record, and if it can't find an existing one, it will create
574
- one itself. Sometimes this step fails, especially if you have other validations
575
- on the attribute you're testing (or, if you have database-level restrictions on
576
- any attributes). In this case, the solution is to create a record before you use
577
- `validate_uniqueness_of`.
578
-
579
- For example, if you have this model:
580
-
581
- ```ruby
582
- class Post < ActiveRecord::Base
583
- validates_presence_of :permalink
584
- validates_uniqueness_of :permalink
585
- end
586
- ```
587
-
588
- then you will need to test it like this:
589
-
590
- ```ruby
591
- describe Post do
592
- it do
593
- Post.create!(title: 'This is the title')
594
- should validate_uniqueness_of(:permalink)
595
- end
596
- end
597
- ```
598
-
599
- ### ActiveRecord Matchers
600
-
601
- *Jump to: [accept_nested_attributes_for](#accept_nested_attributes_for), [belong_to](#belong_to), [have_many](#have_many), [have_one](#have_one), [have_and_belong_to_many](#have_and_belong_to_many), [have_db_column](#have_db_column), [have_db_index](#have_db_index), [have_readonly_attribute](#have_readonly_attribute), [serialize](#serialize)*
602
-
603
- #### accept_nested_attributes_for
604
-
605
- The `accept_nested_attributes_for` matcher tests usage of the
606
- `accepts_nested_attributes_for` macro.
607
-
608
- ```ruby
609
- class Car < ActiveRecord::Base
610
- accept_nested_attributes_for :doors
611
- accept_nested_attributes_for :mirrors, allow_destroy: true
612
- accept_nested_attributes_for :windows, limit: 3
613
- accept_nested_attributes_for :engine, update_only: true
614
- end
615
-
616
- # RSpec
617
- describe Car do
618
- it { should accept_nested_attributes_for(:doors) }
619
- it { should accept_nested_attributes_for(:mirrors).allow_destroy(true) }
620
- it { should accept_nested_attributes_for(:windows).limit(3) }
621
- it { should accept_nested_attributes_for(:engine).update_only(true) }
622
- end
623
-
624
- # Test::Unit (using Shoulda)
625
- class CarTest < ActiveSupport::TestCase
626
- should accept_nested_attributes_for(:doors)
627
- should accept_nested_attributes_for(:mirrors).allow_destroy(true)
628
- should accept_nested_attributes_for(:windows).limit(3)
629
- should accept_nested_attributes_for(:engine).update_only(true)
630
- end
631
- ```
632
-
633
- #### belong_to
634
-
635
- The `belong_to` matcher tests your `belongs_to` associations.
636
-
637
- ```ruby
638
- class Person < ActiveRecord::Base
639
- belongs_to :organization
640
- belongs_to :family, -> { where(everyone_is_perfect: false) }
641
- belongs_to :previous_company, -> { order('hired_on desc') }
642
- belongs_to :ancient_city, class_name: 'City'
643
- belongs_to :great_country, foreign_key: 'country_id'
644
- belongs_to :mental_institution, touch: true
645
- belongs_to :world, dependent: :destroy
646
- end
647
-
648
- # RSpec
649
- describe Person do
650
- it { should belong_to(:organization) }
651
- it { should belong_to(:family).conditions(everyone_is_perfect: false) }
652
- it { should belong_to(:previous_company).order('hired_on desc') }
653
- it { should belong_to(:ancient_city).class_name('City') }
654
- it { should belong_to(:great_country).with_foreign_key('country_id') }
655
- it { should belong_to(:mental_institution).touch(true) }
656
- it { should belong_to(:world).dependent(:destroy) }
657
- end
658
-
659
- # Test::Unit
660
- class PersonTest < ActiveSupport::TestCase
661
- should belong_to(:organization)
662
- should belong_to(:family).conditions(everyone_is_perfect: false)
663
- should belong_to(:previous_company).order('hired_on desc')
664
- should belong_to(:ancient_city).class_name('City')
665
- should belong_to(:great_country).with_foreign_key('country_id')
666
- should belong_to(:mental_institution).touch(true)
667
- should belong_to(:world).dependent(:destroy)
668
- end
669
- ```
670
-
671
- #### have_many
672
-
673
- The `have_many` matcher tests your `has_many` and `has_many :through` associations.
674
-
675
- ```ruby
676
- class Person < ActiveRecord::Base
677
- has_many :friends
678
- has_many :acquaintances, through: :friends
679
- has_many :job_offers, through: :friends, source: :opportunities
680
- has_many :coins, -> { where(condition: 'mint') }
681
- has_many :shirts, -> { order('color') }
682
- has_many :hopes, class_name: 'Dream'
683
- has_many :worries, foreign_key: 'worrier_id'
684
- has_many :distractions, counter_cache: true
685
- has_many :ideas, validate: false
686
- has_many :topics_of_interest, touch: true
687
- has_many :secret_documents, dependent: :destroy
688
- end
689
-
690
- # RSpec
691
- describe Person do
692
- it { should have_many(:friends) }
693
- it { should have_many(:acquaintances).through(:friends) }
694
- it { should have_many(:job_offers).through(:friends).source(:opportunities) }
695
- it { should have_many(:coins).conditions(condition: 'mint') }
696
- it { should have_many(:shirts).order('color') }
697
- it { should have_many(:hopes).class_name('Dream') }
698
- it { should have_many(:worries).with_foreign_key('worrier_id') }
699
- it { should have_many(:ideas).validate(false) }
700
- it { should have_many(:distractions).counter_cache(true) }
701
- it { should have_many(:topics_of_interest).touch(true) }
702
- it { should have_many(:secret_documents).dependent(:destroy) }
703
- end
704
-
705
- # Test::Unit
706
- class PersonTest < ActiveSupport::TestCase
707
- should have_many(:friends)
708
- should have_many(:acquaintances).through(:friends)
709
- should have_many(:job_offers).through(:friends).source(:opportunities)
710
- should have_many(:coins).conditions(condition: 'mint')
711
- should have_many(:shirts).order('color')
712
- should have_many(:hopes).class_name('Dream')
713
- should have_many(:worries).with_foreign_key('worrier_id')
714
- should have_many(:ideas).validate(false)
715
- should have_many(:distractions).counter_cache(true)
716
- should have_many(:topics_of_interest).touch(true)
717
- should have_many(:secret_documents).dependent(:destroy)
718
- end
719
- ```
720
-
721
- #### have_one
722
-
723
- The `have_one` matcher tests your `has_one` and `has_one :through` associations.
724
-
725
- ```ruby
726
- class Person < ActiveRecord::Base
727
- has_one :partner
728
- has_one :life, through: :partner
729
- has_one :car, through: :partner, source: :vehicle
730
- has_one :pet, -> { where('weight < 80') }
731
- has_one :focus, -> { order('priority desc') }
732
- has_one :chance, class_name: 'Opportunity'
733
- has_one :job, foreign_key: 'worker_id'
734
- has_one :parking_card, validate: false
735
- has_one :contract, dependent: :nullify
736
- end
737
-
738
- # RSpec
739
- describe Person do
740
- it { should have_one(:partner) }
741
- it { should have_one(:life).through(:partner) }
742
- it { should have_one(:car).through(:partner).source(:vehicle) }
743
- it { should have_one(:pet).conditions('weight < 80') }
744
- it { should have_one(:focus).order('priority desc') }
745
- it { should have_one(:chance).class_name('Opportunity') }
746
- it { should have_one(:job).with_foreign_key('worker_id') }
747
- it { should have_one(:parking_card).validate(false) }
748
- it { should have_one(:contract).dependent(:nullify) }
749
- end
750
-
751
- # Test::Unit
752
- class PersonTest < ActiveSupport::TestCase
753
- should have_one(:partner)
754
- should have_one(:life).through(:partner)
755
- should have_one(:car).through(:partner).source(:vehicle)
756
- should have_one(:pet).conditions('weight < 80')
757
- should have_one(:focus).order('priority desc')
758
- should have_one(:chance).class_name('Opportunity')
759
- should have_one(:job).with_foreign_key('worker_id')
760
- should have_one(:parking_card).validate(false)
761
- should have_one(:contract).dependent(:nullify)
762
- end
763
- ```
764
-
765
- #### have_and_belong_to_many
766
-
767
- The `have_and_belong_to_many` matcher tests your `has_and_belongs_to_many`
768
- associations.
769
-
770
- ```ruby
771
- class Person < ActiveRecord::Base
772
- has_and_belongs_to_many :awards
773
- has_and_belongs_to_many :issues, -> { where(difficulty: 'hard') }
774
- has_and_belongs_to_many :projects, -> { order('time_spent') }
775
- has_and_belongs_to_many :places_visited, class_name: 'City'
776
- has_and_belongs_to_many :interviews, validate: false
777
- end
778
-
779
- # RSpec
780
- describe Person do
781
- it { should have_and_belong_to_many(:awards) }
782
- it { should have_and_belong_to_many(:issues).conditions(difficulty: 'hard') }
783
- it { should have_and_belong_to_many(:projects).order('time_spent') }
784
- it { should have_and_belong_to_many(:places_visited).class_name('City') }
785
- it { should have_and_belong_to_many(:interviews).validate(false) }
786
- end
787
-
788
- # Test::Unit
789
- class PersonTest < ActiveSupport::TestCase
790
- should have_and_belong_to_many(:awards)
791
- should have_and_belong_to_many(:issues).conditions(difficulty: 'hard')
792
- should have_and_belong_to_many(:projects).order('time_spent')
793
- should have_and_belong_to_many(:places_visited).class_name('City')
794
- should have_and_belong_to_many(:interviews).validate(false)
795
- end
796
- ```
797
-
798
- #### have_db_column
799
-
800
- The `have_db_column` matcher tests that the table that backs your model
801
- has a specific column.
802
-
803
- ```ruby
804
- class CreatePhones < ActiveRecord::Migration
805
- def change
806
- create_table :phones do |t|
807
- t.decimal :supported_ios_version
808
- t.string :model, null: false
809
- t.decimal :camera_aperture, precision: 1
810
- end
811
- end
812
- end
813
-
814
- # RSpec
815
- describe Phone do
816
- it { should have_db_column(:supported_ios_version) }
817
- it { should have_db_column(:model).with_options(null: false) }
818
-
819
- it do
820
- should have_db_column(:camera_aperture).
821
- of_type(:decimal).
822
- with_options(precision: 1)
823
- end
824
- end
825
-
826
- # Test::Unit
827
- class PhoneTest < ActiveSupport::TestCase
828
- should have_db_column(:supported_ios_version)
829
- should have_db_column(:model).with_options(null: false)
830
-
831
- should have_db_column(:camera_aperture).
832
- of_type(:decimal).
833
- with_options(precision: 1)
834
- end
835
- ```
836
-
837
- #### have_db_index
838
-
839
- The `have_db_index` matcher tests that the table that backs your model has a
840
- index on a specific column.
841
-
842
- ```ruby
843
- class CreateBlogs < ActiveRecord::Migration
844
- def change
845
- create_table :blogs do |t|
846
- t.integer :user_id, null: false
847
- t.string :name, null: false
848
- end
849
-
850
- add_index :blogs, :user_id
851
- add_index :blogs, :name, unique: true
852
- end
853
- end
854
-
855
- # RSpec
856
- describe Blog do
857
- it { should have_db_index(:user_id) }
858
- it { should have_db_index(:name).unique(true) }
859
- end
860
-
861
- # Test::Unit
862
- class BlogTest < ActiveSupport::TestCase
863
- should have_db_index(:user_id)
864
- should have_db_index(:name).unique(true)
865
- end
866
- ```
867
-
868
- #### have_readonly_attribute
869
-
870
- The `have_readonly_attribute` matcher tests usage of the `attr_readonly` macro.
871
-
872
- ```ruby
873
- class User < ActiveRecord::Base
874
- attr_readonly :password
875
- end
876
-
877
- # RSpec
878
- describe User do
879
- it { should have_readonly_attribute(:password) }
880
- end
881
-
882
- # Test::Unit
883
- class UserTest < ActiveSupport::TestCase
884
- should have_readonly_attribute(:password)
885
- end
886
- ```
887
-
888
- #### serialize
889
-
890
- The `serialize` matcher tests usage of the `serialize` macro.
891
-
892
- ```ruby
893
- class ProductOptionsSerializer
894
- def load(string)
895
- # ...
896
- end
897
-
898
- def dump(options)
899
- # ...
900
- end
901
- end
902
-
903
- class Product < ActiveRecord::Base
904
- serialize :customizations
905
- serialize :specifications, ProductSpecsSerializer
906
- serialize :options, ProductOptionsSerializer.new
907
- end
908
-
909
- # RSpec
910
- describe Product do
911
- it { should serialize(:customizations) }
912
- it { should serialize(:specifications).as(ProductSpecsSerializer) }
913
- it { should serialize(:options).as_instance_of(ProductOptionsSerializer) }
914
- end
915
-
916
- # Test::Unit
917
- class ProductTest < ActiveSupport::TestCase
918
- should serialize(:customizations)
919
- should serialize(:specifications).as(ProductSpecsSerializer)
920
- should serialize(:options).as_instance_of(ProductOptionsSerializer)
921
- end
922
- ```
923
-
924
- ### ActionController Matchers
925
-
926
- *Jump to: [filter_param](#filter_param), [permit](#permit), [redirect_to](#redirect_to), [render_template](#render_template), [render_with_layout](#render_with_layout), [rescue_from](#rescue_from), [respond_with](#respond_with), [route](#route), [set_session](#set_session), [set_the_flash](#set_the_flash), [use_after_filter / use_after_action](#use_after_filter--use_after_action), [use_around_filter / use_around_action](#use_around_filter--use_around_action), [use_before_filter / use_around_action](#use_before_filter--use_before_action)*
927
-
928
- #### filter_param
929
-
930
- The `filter_param` matcher tests parameter filtering configuration.
931
-
932
- ```ruby
933
- class MyApplication < Rails::Application
934
- config.filter_parameters << :secret_key
935
- end
936
-
937
- # RSpec
938
- describe ApplicationController do
939
- it { should filter_param(:secret_key) }
940
- end
941
-
942
- # Test::Unit
943
- class ApplicationControllerTest < ActionController::TestCase
944
- should filter_param(:secret_key)
945
- end
946
- ```
947
-
948
- #### permit
949
-
950
- The `permit` matcher tests that only whitelisted parameters are permitted.
951
-
952
- ```ruby
953
- class UserController < ActionController::Base
954
- def create
955
- User.create(user_params)
956
- end
957
-
958
- private
959
-
960
- def user_params
961
- params.require(:user).permit(:email)
962
- end
963
- end
964
-
965
- # RSpec
966
- describe UserController do
967
- it { should permit(:email).for(:create) }
968
- end
969
-
970
- # Test::Unit
971
- class UserControllerTest < ActionController::TestCase
972
- should permit(:email).for(:create)
973
- end
974
- ```
975
-
976
- #### redirect_to
977
-
978
- The `redirect_to` matcher tests that an action redirects to a certain location.
979
- In a test suite using RSpec, it is very similar to rspec-rails's `redirect_to`
980
- matcher. In a test suite using Test::Unit / Shoulda, it provides a more
981
- expressive syntax over `assert_redirected_to`.
982
-
983
- ```ruby
984
- class PostsController < ApplicationController
985
- def show
986
- redirect_to :index
987
- end
988
- end
989
-
990
- # RSpec
991
- describe PostsController do
992
- describe 'GET #list' do
993
- before { get :list }
994
-
995
- it { should redirect_to(posts_path) }
996
- end
997
- end
998
-
999
- # Test::Unit
1000
- class PostsControllerTest < ActionController::TestCase
1001
- context 'GET #list' do
1002
- setup { get :list }
1003
-
1004
- should redirect_to { posts_path }
1005
- end
1006
- end
1007
- ```
1008
-
1009
- #### render_template
1010
-
1011
- The `render_template` matcher tests that an action renders a template.
1012
- In RSpec, it is very similar to rspec-rails's `render_template` matcher.
1013
- In Test::Unit, it provides a more expressive syntax over `assert_template`.
1014
-
1015
- ```ruby
1016
- class PostsController < ApplicationController
1017
- def show
1018
- end
1019
- end
1020
-
1021
- # RSpec
1022
- describe PostsController do
1023
- describe 'GET #show' do
1024
- before { get :show }
1025
-
1026
- it { should render_template('show') }
1027
- end
1028
- end
1029
-
1030
- # Test::Unit
1031
- class PostsControllerTest < ActionController::TestCase
1032
- context 'GET #show' do
1033
- setup { get :show }
1034
-
1035
- should render_template('show')
1036
- end
1037
- end
1038
- ```
1039
-
1040
- #### render_with_layout
1041
-
1042
- The `render_with_layout` matcher tests that an action is rendered with a certain
1043
- layout.
1044
-
1045
- ```ruby
1046
- class PostsController < ApplicationController
1047
- def show
1048
- render layout: 'posts'
1049
- end
1050
- end
1051
-
1052
- # RSpec
1053
- describe PostsController do
1054
- describe 'GET #show' do
1055
- before { get :show }
1056
-
1057
- it { should render_with_layout('posts') }
1058
- end
1059
- end
1060
-
1061
- # Test::Unit
1062
- class PostsControllerTest < ActionController::TestCase
1063
- context 'GET #show' do
1064
- setup { get :show }
1065
-
1066
- should render_with_layout('posts')
1067
- end
1068
- end
1069
- ```
1070
-
1071
- #### rescue_from
1072
-
1073
- The `rescue_from` matcher tests usage of the `rescue_from` macro.
1074
-
1075
- ```ruby
1076
- class ApplicationController < ActionController::Base
1077
- rescue_from ActiveRecord::RecordNotFound, with: :handle_not_found
1078
-
1079
- private
1080
-
1081
- def handle_not_found
1082
- # ...
1083
- end
1084
- end
1085
-
1086
- # RSpec
1087
- describe ApplicationController do
1088
- it do
1089
- should rescue_from(ActiveRecord::RecordNotFound).
1090
- with(:handle_not_found)
1091
- end
1092
- end
1093
-
1094
- # Test::Unit
1095
- class ApplicationControllerTest < ActionController::TestCase
1096
- should rescue_from(ActiveRecord::RecordNotFound).
1097
- with(:handle_not_found)
1098
- end
1099
- ```
1100
-
1101
- #### respond_with
1102
-
1103
- The `respond_with` matcher tests that an action responds with a certain status
1104
- code.
1105
-
1106
- ```ruby
1107
- class PostsController < ApplicationController
1108
- def index
1109
- render status: 403
1110
- end
1111
-
1112
- def show
1113
- render status: :locked
1114
- end
1115
-
1116
- def destroy
1117
- render status: 508
1118
- end
1119
- end
1120
-
1121
- # RSpec
1122
- describe PostsController do
1123
- describe 'GET #index' do
1124
- before { get :index }
1125
-
1126
- it { should respond_with(403) }
1127
- end
1128
-
1129
- describe 'GET #show' do
1130
- before { get :show }
1131
-
1132
- it { should respond_with(:locked) }
1133
- end
1134
-
1135
- describe 'DELETE #destroy' do
1136
- before { delete :destroy }
1137
-
1138
- it { should respond_with(500..600) }
1139
- end
1140
- end
1141
-
1142
- # Test::Unit
1143
- class PostsControllerTest < ActionController::TestCase
1144
- context 'GET #index' do
1145
- setup { get :index }
1146
-
1147
- should respond_with(403)
1148
- end
1149
-
1150
- context 'GET #show' do
1151
- setup { get :show }
1152
-
1153
- should respond_with(:locked)
1154
- end
1155
-
1156
- context 'DELETE #destroy' do
1157
- setup { delete :destroy }
1158
-
1159
- should respond_with(500..600)
1160
- end
1161
- end
1162
- ```
1163
-
1164
- #### route
1165
-
1166
- The `route` matcher tests that a route resolves to a controller, action, and
1167
- params; and that the controller, action, and params generates the same route. For
1168
- an RSpec suite, this is like using a combination of `route_to` and
1169
- `be_routable`. For a Test::Unit suite, it provides a more expressive syntax
1170
- over `assert_routing`.
1171
-
1172
- ```ruby
1173
- My::Application.routes.draw do
1174
- get '/posts', controller: 'posts', action: 'index'
1175
- get '/posts/:id' => 'posts#show'
1176
- end
1177
-
1178
- # RSpec
1179
- describe 'Routing' do
1180
- it { should route(:get, '/posts').to(controller: 'posts', action: 'index') }
1181
- it { should route(:get, '/posts/1').to('posts#show', id: 1) }
1182
- end
1183
-
1184
- # Test::Unit
1185
- class RoutesTest < ActionController::IntegrationTest
1186
- should route(:get, '/posts').to(controller: 'posts', action: 'index')
1187
- should route(:get, '/posts/1').to('posts#show', id: 1)
1188
- end
1189
- ```
1190
-
1191
- #### set_session
1192
-
1193
- The `set_session` matcher asserts that a key in the `session` hash has been set
1194
- to a certain value.
1195
-
1196
- ```ruby
1197
- class PostsController < ApplicationController
1198
- def show
1199
- session[:foo] = 'bar'
1200
- end
1201
- end
1202
-
1203
- # RSpec
1204
- describe PostsController do
1205
- describe 'GET #show' do
1206
- before { get :show }
1207
-
1208
- it { should set_session(:foo).to('bar') }
1209
- it { should_not set_session(:baz) }
1210
- end
1211
- end
1212
-
1213
- # Test::Unit
1214
- class PostsControllerTest < ActionController::TestCase
1215
- context 'GET #show' do
1216
- setup { get :show }
1217
-
1218
- should set_session(:foo).to('bar')
1219
- should_not set_session(:baz)
1220
- end
1221
- end
1222
- ```
1223
-
1224
- #### set_the_flash
1225
-
1226
- The `set_the_flash` matcher asserts that a key in the `flash` hash is set to a
1227
- certain value.
1228
-
1229
- ```ruby
1230
- class PostsController < ApplicationController
1231
- def index
1232
- flash[:foo] = 'A candy bar'
1233
- end
1234
-
1235
- def show
1236
- flash.now[:foo] = 'bar'
1237
- end
1238
-
1239
- def destroy
1240
- end
1241
- end
1242
-
1243
- # RSpec
1244
- describe PostsController do
1245
- describe 'GET #index' do
1246
- before { get :index }
1247
-
1248
- it { should set_the_flash.to('bar') }
1249
- it { should set_the_flash.to(/bar/) }
1250
- it { should set_the_flash[:foo].to('bar') }
1251
- it { should_not set_the_flash[:baz] }
1252
- end
1253
-
1254
- describe 'GET #show' do
1255
- before { get :show }
1256
-
1257
- it { should set_the_flash.now }
1258
- it { should set_the_flash[:foo].now }
1259
- it { should set_the_flash[:foo].to('bar').now }
1260
- end
1261
-
1262
- describe 'DELETE #destroy' do
1263
- before { delete :destroy }
1264
-
1265
- it { should_not set_the_flash }
1266
- end
1267
- end
1268
-
1269
- # Test::Unit
1270
- class PostsControllerTest < ActionController::TestCase
1271
- context 'GET #index' do
1272
- setup { get :index }
1273
-
1274
- should set_the_flash.to('bar')
1275
- should set_the_flash.to(/bar/)
1276
- should set_the_flash[:foo].to('bar')
1277
- should_not set_the_flash[:baz]
1278
- end
1279
-
1280
- context 'GET #show' do
1281
- setup { get :show }
1282
-
1283
- should set_the_flash.now
1284
- should set_the_flash[:foo].now
1285
- should set_the_flash[:foo].to('bar').now
1286
- end
1287
-
1288
- context 'DELETE #destroy' do
1289
- setup { delete :destroy }
1290
-
1291
- should_not set_the_flash
1292
- end
1293
- end
1294
- ```
1295
-
1296
- #### use_after_filter / use_after_action
139
+ ## Generating documentation
1297
140
 
1298
- The `use_after_filter` ensures a given `after_filter` is used. This is also
1299
- available as `use_after_action` to provide Rails 4 support.
141
+ YARD is used to generate documentation, which can be viewed [online][rubydocs].
142
+ You can preview changes you make to the documentation locally by running
1300
143
 
1301
- ```ruby
1302
- class UserController < ActionController::Base
1303
- after_filter :log_activity
1304
- end
144
+ yard doc
1305
145
 
1306
- # RSpec
1307
- describe UserController do
1308
- it { should use_after_filter(:log_activity) }
1309
- end
1310
-
1311
- # Test::Unit
1312
- class UserControllerTest < ActionController::TestCase
1313
- should use_after_filter(:log_activity)
1314
- end
1315
- ```
146
+ from this directory. Then, open `doc/index.html` in your browser.
1316
147
 
1317
- #### use_around_filter / use_around_action
148
+ If you want to see a live preview as you work without having to run `yard` over
149
+ and over again, keep this command running in a separate terminal session:
1318
150
 
1319
- The `use_around_filter` ensures a given `around_filter` is used. This is also
1320
- available as `use_around_action` to provide Rails 4 support.
1321
-
1322
- ```ruby
1323
- class UserController < ActionController::Base
1324
- around_filter :log_activity
1325
- end
1326
-
1327
- # RSpec
1328
- describe UserController do
1329
- it { should use_around_filter(:log_activity) }
1330
- end
1331
-
1332
- # Test::Unit
1333
- class UserControllerTest < ActionController::TestCase
1334
- should use_around_filter(:log_activity)
1335
- end
1336
- ```
1337
-
1338
- #### use_before_filter / use_before_action
1339
-
1340
- The `use_before_filter` ensures a given `before_filter` is used. This is also
1341
- available as `use_before_action` for Rails 4 support.
1342
-
1343
- ```ruby
1344
- class UserController < ActionController::Base
1345
- before_filter :authenticate_user!
1346
- end
1347
-
1348
- # RSpec
1349
- describe UserController do
1350
- it { should use_before_filter(:authenticate_user!) }
1351
- end
1352
-
1353
- # Test::Unit
1354
- class UserControllerTest < ActionController::TestCase
1355
- should use_before_filter(:authenticate_user!)
1356
- end
1357
- ```
1358
-
1359
- ## Independent Matchers
1360
-
1361
- Matchers to test non-Rails-dependent code:
1362
-
1363
- #### delegate_method
1364
-
1365
- ```ruby
1366
- class Human < ActiveRecord::Base
1367
- has_one :robot
1368
- delegate :work, to: :robot
1369
-
1370
- # alternatively, if you are not using Rails
1371
- def work
1372
- robot.work
1373
- end
1374
-
1375
- def protect
1376
- robot.protect('Sarah Connor')
1377
- end
1378
-
1379
- def speak
1380
- robot.beep_boop
1381
- end
1382
- end
1383
-
1384
- # RSpec
1385
- describe Human do
1386
- it { should delegate_method(:work).to(:robot) }
1387
- it { should delegate_method(:protect).to(:robot).with_arguments('Sarah Connor') }
1388
- it { should delegate_method(:beep_boop).to(:robot).as(:speak) }
1389
- end
1390
-
1391
- # Test::Unit
1392
- class HumanTest < ActiveSupport::TestCase
1393
- should delegate_method(:work).to(:robot)
1394
- should delegate_method(:protect).to(:robot).with_arguments('Sarah Connor')
1395
- should delegate_method(:beep_boop).to(:robot).as(:speak)
1396
- end
1397
- ```
151
+ watchr docs.watchr
1398
152
 
1399
153
  ## Versioning
1400
154