thoughtbot-shoulda 2.10.1 → 2.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (83) hide show
  1. data/CONTRIBUTION_GUIDELINES.rdoc +4 -6
  2. data/README.rdoc +14 -12
  3. data/lib/shoulda.rb +1 -1
  4. data/lib/shoulda/action_controller.rb +0 -2
  5. data/lib/shoulda/action_controller/macros.rb +38 -75
  6. data/lib/shoulda/action_controller/matchers/respond_with_content_type_matcher.rb +4 -0
  7. data/lib/shoulda/action_controller/matchers/set_session_matcher.rb +1 -1
  8. data/lib/shoulda/action_view/macros.rb +6 -1
  9. data/lib/shoulda/active_record/assertions.rb +4 -4
  10. data/lib/shoulda/active_record/helpers.rb +0 -13
  11. data/lib/shoulda/active_record/macros.rb +50 -127
  12. data/lib/shoulda/active_record/matchers.rb +2 -1
  13. data/lib/shoulda/active_record/matchers/allow_mass_assignment_of_matcher.rb +1 -1
  14. data/lib/shoulda/active_record/matchers/allow_value_matcher.rb +5 -5
  15. data/lib/shoulda/active_record/matchers/association_matcher.rb +3 -3
  16. data/lib/shoulda/active_record/matchers/{have_index_matcher.rb → have_db_index_matcher.rb} +15 -8
  17. data/lib/shoulda/active_record/matchers/have_named_scope_matcher.rb +3 -0
  18. data/lib/shoulda/active_record/matchers/validate_format_of_matcher.rb +67 -0
  19. data/lib/shoulda/active_record/matchers/validation_matcher.rb +1 -0
  20. data/lib/shoulda/assertions.rb +18 -6
  21. data/lib/shoulda/context.rb +99 -1
  22. data/lib/shoulda/macros.rb +83 -23
  23. data/lib/shoulda/private_helpers.rb +1 -8
  24. data/lib/shoulda/test_unit.rb +3 -0
  25. data/test/fail_macros.rb +6 -1
  26. data/test/functional/posts_controller_test.rb +17 -21
  27. data/test/functional/users_controller_test.rb +1 -1
  28. data/test/matchers/active_record/allow_mass_assignment_of_matcher_test.rb +1 -1
  29. data/test/matchers/active_record/allow_value_matcher_test.rb +24 -1
  30. data/test/matchers/active_record/association_matcher_test.rb +8 -3
  31. data/test/matchers/active_record/ensure_inclusion_of_matcher_test.rb +1 -1
  32. data/test/matchers/active_record/ensure_length_of_matcher_test.rb +1 -1
  33. data/test/matchers/active_record/have_db_column_matcher_test.rb +1 -1
  34. data/test/matchers/active_record/{have_index_matcher_test.rb → have_db_index_matcher_test.rb} +24 -7
  35. data/test/matchers/active_record/have_named_scope_matcher_test.rb +1 -1
  36. data/test/matchers/active_record/have_readonly_attributes_matcher_test.rb +1 -1
  37. data/test/matchers/active_record/validate_acceptance_of_matcher_test.rb +1 -1
  38. data/test/matchers/active_record/validate_format_of_matcher_test.rb +39 -0
  39. data/test/matchers/active_record/validate_numericality_of_matcher_test.rb +1 -1
  40. data/test/matchers/active_record/validate_presence_of_matcher_test.rb +1 -1
  41. data/test/matchers/active_record/validate_uniqueness_of_matcher_test.rb +1 -1
  42. data/test/matchers/controller/assign_to_matcher_test.rb +1 -1
  43. data/test/matchers/controller/filter_param_matcher_test.rb +1 -1
  44. data/test/matchers/controller/render_with_layout_matcher_test.rb +1 -1
  45. data/test/matchers/controller/respond_with_content_type_matcher_test.rb +12 -7
  46. data/test/matchers/controller/respond_with_matcher_test.rb +1 -1
  47. data/test/matchers/controller/route_matcher_test.rb +1 -1
  48. data/test/matchers/controller/set_session_matcher_test.rb +9 -2
  49. data/test/matchers/controller/set_the_flash_matcher.rb +1 -1
  50. data/test/model_builder.rb +1 -1
  51. data/test/other/autoload_macro_test.rb +1 -1
  52. data/test/other/context_test.rb +45 -1
  53. data/test/other/convert_to_should_syntax_test.rb +3 -3
  54. data/test/other/helpers_test.rb +102 -3
  55. data/test/other/private_helpers_test.rb +6 -8
  56. data/test/other/should_test.rb +8 -3
  57. data/test/rails_root/app/controllers/{application.rb → application_controller.rb} +0 -0
  58. data/test/rails_root/app/controllers/posts_controller.rb +1 -0
  59. data/test/rails_root/app/models/pets/cat.rb +7 -0
  60. data/test/rails_root/app/models/profile.rb +2 -0
  61. data/test/rails_root/app/models/registration.rb +2 -0
  62. data/test/rails_root/app/models/user.rb +3 -0
  63. data/test/rails_root/config/boot.rb +6 -5
  64. data/test/rails_root/config/environment.rb +5 -1
  65. data/test/rails_root/db/migrate/20090506203502_create_profiles.rb +12 -0
  66. data/test/rails_root/db/migrate/20090506203536_create_registrations.rb +14 -0
  67. data/test/rails_root/db/migrate/20090513104502_create_cats.rb +12 -0
  68. data/test/rails_root/test/shoulda_macros/custom_macro.rb +1 -1
  69. data/test/rails_root/vendor/gems/gem_with_macro-0.0.1/shoulda_macros/gem_macro.rb +1 -1
  70. data/test/rails_root/vendor/plugins/plugin_with_macro/shoulda_macros/plugin_macro.rb +1 -1
  71. data/test/rspec_test.rb +1 -1
  72. data/test/test_helper.rb +3 -10
  73. data/test/unit/address_test.rb +2 -2
  74. data/test/unit/cat_test.rb +7 -0
  75. data/test/unit/dog_test.rb +2 -3
  76. data/test/unit/flea_test.rb +1 -1
  77. data/test/unit/post_test.rb +2 -2
  78. data/test/unit/product_test.rb +2 -6
  79. data/test/unit/tag_test.rb +2 -2
  80. data/test/unit/tagging_test.rb +1 -1
  81. data/test/unit/user_test.rb +18 -8
  82. metadata +16 -10
  83. data/lib/shoulda/action_controller/helpers.rb +0 -47
@@ -1,12 +1,10 @@
1
- We're using GitHub[http://github.com/thoughtbot/shoulda/tree/master] and Lighthouse[http://thoughtbot.lighthouseapp.com/projects/5807], and we've been getting any combination of github pull requests, Lighthouse tickets, patches, emails, etc. We need to normalize this workflow to make sure we don't miss any fixes.
1
+ We're using GitHub[http://github.com/thoughtbot/shoulda/tree/master], and we've been getting any combination of github pull requests, tickets, patches, emails, etc. We need to normalize this workflow to make sure we don't miss any fixes.
2
2
 
3
3
  * Make sure you're accessing the source from the {official repository}[http://github.com/thoughtbot/shoulda/tree/master].
4
- * We prefer git branches over patches, but we can take either.
4
+ * We prefer git branches over patches, but we can take either.
5
5
  * If you're using git, please make a branch for each separate contribution. We can cherry pick your commits, but pulling from a branch is easier.
6
6
  * If you're submitting patches, please cut each fix or feature into a separate patch.
7
- * There should be a Lighthouse[http://thoughtbot.lighthouseapp.com/projects/5807] ticket for any submission. If you've found a bug and want to fix it, open a new ticket at the same time.
8
- * We've got github/lighthouse integration going, so you can update tickets when you commit. {This blog post}[http://hoth.entp.com/2008/4/11/github-and-lighthouse-sitting-in-a-tree] explains the commit options pretty well.
9
- * Please <b>don't send pull requests</b> Just update the lighthouse ticket with the url for your fix (or attach the patch) when it's ready. The github pull requests pretty much get dropped on the floor until someone with commit rights notices them in the mailbox.
7
+ * There should be an issue[http://github.com/thoughtbot/shoulda/issues] for any submission. If you've found a bug and want to fix it, open a new ticket at the same time.
8
+ * Please <b>don't send pull requests</b> Just update the issue with the url for your fix (or attach the patch) when it's ready. The github pull requests pretty much get dropped on the floor until someone with commit rights notices them in the mailbox.
10
9
  * Contributions without tests won't be accepted. The file <tt>/test/README</tt> explains the testing system pretty thoroughly.
11
10
 
12
-
@@ -75,22 +75,24 @@ Makes TDD so much easier.
75
75
  === Controller Tests (Shoulda::Controller::Macros)
76
76
 
77
77
  Macros to test the most common controller patterns...
78
+
79
+ class PostsControllerTest < ActionController::TestCase
80
+ context "on GET to :show for first record" do
81
+ setup do
82
+ get :show, :id => 1
83
+ end
78
84
 
79
- context "on GET to :show for first record" do
80
- setup do
81
- get :show, :id => 1
82
- end
83
-
84
- should_assign_to :user
85
- should_respond_with :success
86
- should_render_template :show
87
- should_not_set_the_flash
85
+ should_assign_to :user
86
+ should_respond_with :success
87
+ should_render_template :show
88
+ should_not_set_the_flash
88
89
 
89
- should "do something else really cool" do
90
- assert_equal 1, assigns(:user).id
90
+ should "do something else really cool" do
91
+ assert_equal 1, assigns(:user).id
92
+ end
91
93
  end
92
94
  end
93
-
95
+
94
96
  === Helpful Assertions (Shoulda::Assertions)
95
97
 
96
98
  More to come here, but have fun with what's there.
@@ -1,5 +1,5 @@
1
1
  module Shoulda
2
- VERSION = "2.10.1"
2
+ VERSION = "2.10.2"
3
3
  end
4
4
 
5
5
  if defined? Spec
@@ -1,5 +1,4 @@
1
1
  require 'shoulda'
2
- require 'shoulda/action_controller/helpers'
3
2
  require 'shoulda/action_controller/matchers'
4
3
  require 'shoulda/action_controller/macros'
5
4
 
@@ -7,7 +6,6 @@ module Test # :nodoc: all
7
6
  module Unit
8
7
  class TestCase
9
8
  include Shoulda::ActionController::Matchers
10
- include Shoulda::ActionController::Helpers
11
9
  extend Shoulda::ActionController::Macros
12
10
  end
13
11
  end
@@ -24,31 +24,35 @@ module Shoulda # :nodoc:
24
24
  module Macros
25
25
  include Matchers
26
26
 
27
- # Macro that creates a test asserting that the flash contains the given value.
28
- # val can be a String, a Regex, or nil (indicating that the flash should not be set)
27
+ # Macro that creates a test asserting that the flash contains the given
28
+ # value. Expects a +String+ or +Regexp+.
29
+ #
30
+ # If the argument is +nil+, it will assert that the flash is not set.
31
+ # This behavior is deprecated.
29
32
  #
30
33
  # Example:
31
34
  #
32
35
  # should_set_the_flash_to "Thank you for placing this order."
33
36
  # should_set_the_flash_to /created/i
34
- # should_set_the_flash_to nil
35
37
  def should_set_the_flash_to(val)
36
- matcher = set_the_flash.to(val)
37
38
  if val
39
+ matcher = set_the_flash.to(val)
38
40
  should matcher.description do
39
41
  assert_accepts matcher, @controller
40
42
  end
41
43
  else
42
- should "not #{matcher.description}" do
43
- assert_rejects matcher, @controller
44
- end
44
+ warn "[DEPRECATION] should_set_the_flash_to nil is deprecated. " <<
45
+ "Use should_not_set_the_flash instead."
46
+ should_not_set_the_flash
45
47
  end
46
48
  end
47
49
 
48
- # Macro that creates a test asserting that the flash is empty. Same as
49
- # @should_set_the_flash_to nil@
50
+ # Macro that creates a test asserting that the flash is empty.
50
51
  def should_not_set_the_flash
51
- should_set_the_flash_to nil
52
+ matcher = set_the_flash
53
+ should "not #{matcher.description}" do
54
+ assert_rejects matcher, @controller
55
+ end
52
56
  end
53
57
 
54
58
  # Macro that creates a test asserting that filter_parameter_logging
@@ -71,8 +75,9 @@ module Shoulda # :nodoc:
71
75
  #
72
76
  # Options:
73
77
  # * <tt>:class</tt> - The expected class of the instance variable being checked.
74
- # * <tt>:equals</tt> - A string which is evaluated and compared for equality with
75
- # the instance variable being checked.
78
+ #
79
+ # If a block is passed, the assigned variable is expected to be equal to
80
+ # the return value of that block.
76
81
  #
77
82
  # Example:
78
83
  #
@@ -80,25 +85,11 @@ module Shoulda # :nodoc:
80
85
  # should_assign_to :user, :class => User
81
86
  # should_assign_to(:user) { @user }
82
87
  def should_assign_to(*names, &block)
83
- opts = names.extract_options!
84
- if opts[:equals]
85
- warn "[DEPRECATION] should_assign_to :var, :equals => 'val' " <<
86
- "is deprecated. Use should_assign_to(:var) { 'val' } instead."
87
- end
88
+ klass = get_options!(names, :class)
88
89
  names.each do |name|
89
- matcher = assign_to(name).with_kind_of(opts[:class])
90
- test_name = matcher.description
91
- test_name << " which is equal to #{opts[:equals]}" if opts[:equals]
92
- should test_name do
93
- if opts[:equals]
94
- instantiate_variables_from_assigns do
95
- expected_value = eval(opts[:equals],
96
- self.send(:binding),
97
- __FILE__,
98
- __LINE__)
99
- matcher = matcher.with(expected_value)
100
- end
101
- elsif block
90
+ matcher = assign_to(name).with_kind_of(klass)
91
+ should matcher.description do
92
+ if block
102
93
  expected_value = instance_eval(&block)
103
94
  matcher = matcher.with(expected_value)
104
95
  end
@@ -141,49 +132,29 @@ module Shoulda # :nodoc:
141
132
  # should_respond_with_content_type :rss
142
133
  # should_respond_with_content_type /rss/
143
134
  def should_respond_with_content_type(content_type)
144
- should "respond with content type of #{content_type}" do
145
- matcher = respond_with_content_type(content_type)
135
+ matcher = respond_with_content_type(content_type)
136
+ should matcher.description do
146
137
  assert_accepts matcher, @controller
147
138
  end
148
139
  end
149
140
 
150
- # Macro that creates a test asserting that a value returned from the session is correct.
151
- # The given string is evaled to produce the resulting redirect path. All of the instance variables
152
- # set by the controller are available to the evaled string.
141
+ # Macro that creates a test asserting that a value returned from the
142
+ # session is correct. Expects the session key as a parameter, and a block
143
+ # that returns the expected value.
144
+ #
153
145
  # Example:
154
146
  #
155
- # should_set_session(:user_id) { '@user.id' }
147
+ # should_set_session(:user_id) { @user.id }
156
148
  # should_set_session(:message) { "Free stuff" }
157
- def should_set_session(key, expected = nil, &block)
149
+ def should_set_session(key, &block)
158
150
  matcher = set_session(key)
159
- if expected
160
- warn "[DEPRECATION] should_set_session :key, 'val' is deprecated. " <<
161
- "Use should_set_session(:key) { 'val' } instead."
162
- end
163
151
  should matcher.description do
164
- if expected
165
- instantiate_variables_from_assigns do
166
- expected_value = eval(expected,
167
- self.send(:binding),
168
- __FILE__,
169
- __LINE__)
170
- matcher = matcher.to(expected_value)
171
- end
172
- else
173
- expected_value = instance_eval(&block)
174
- matcher = matcher.to(expected_value)
175
- end
152
+ expected_value = instance_eval(&block)
153
+ matcher = matcher.to(expected_value)
176
154
  assert_accepts matcher, @controller
177
155
  end
178
156
  end
179
157
 
180
- # Deprecated. See should_set_session
181
- def should_return_from_session(key, expected)
182
- warn "[DEPRECATION] should_require_attributes is deprecated. " <<
183
- "Use should_set_session instead."
184
- should_set_session(key, expected)
185
- end
186
-
187
158
  # Macro that creates a test asserting that the controller rendered the given template.
188
159
  # Example:
189
160
  #
@@ -217,26 +188,18 @@ module Shoulda # :nodoc:
217
188
  should_render_with_layout nil
218
189
  end
219
190
 
220
- # Macro that creates a test asserting that the controller returned a redirect to the given path.
221
- # The given string is evaled to produce the resulting redirect path. All of the instance variables
222
- # set by the controller are available to the evaled string.
191
+ # Macro that creates a test asserting that the controller returned a
192
+ # redirect to the given path. The passed description will be used when
193
+ # generating a test name. Expects a block that returns the expected path
194
+ # for the redirect.
195
+ #
223
196
  # Example:
224
197
  #
225
198
  # should_redirect_to("the user's profile") { user_url(@user) }
226
199
  def should_redirect_to(description, &block)
227
- unless block
228
- warn "[DEPRECATION] should_redirect_to without a block is " <<
229
- "deprecated. Use should_redirect_to('somewhere') { } instead."
230
- end
231
200
  should "redirect to #{description}" do
232
- if block
233
- url = instance_eval(&block)
234
- else
235
- instantiate_variables_from_assigns do
236
- url = eval(description, self.send(:binding), __FILE__, __LINE__)
237
- end
238
- end
239
- assert_redirected_to url
201
+ expected_url = instance_eval(&block)
202
+ assert_redirected_to expected_url
240
203
  end
241
204
  end
242
205
 
@@ -30,6 +30,10 @@ module Shoulda # :nodoc:
30
30
  content_type
31
31
  end
32
32
  end
33
+
34
+ def description
35
+ "respond with content type of #{@content_type}"
36
+ end
33
37
 
34
38
  def matches?(controller)
35
39
  @controller = controller
@@ -46,7 +46,7 @@ module Shoulda # :nodoc:
46
46
  private
47
47
 
48
48
  def assigned_value?
49
- !assigned_value.blank?
49
+ !assigned_value.nil?
50
50
  end
51
51
 
52
52
  def cleared_value?
@@ -11,7 +11,6 @@ module Shoulda # :nodoc:
11
11
  # get :new
12
12
  # end
13
13
  #
14
- # should_render_a_form
15
14
  # should_render_page_with_metadata :title => /index/
16
15
  #
17
16
  # should "do something else really cool" do
@@ -23,12 +22,17 @@ module Shoulda # :nodoc:
23
22
  module Macros
24
23
 
25
24
  # Macro that creates a test asserting that the rendered view contains a <form> element.
25
+ #
26
+ # Deprecated.
26
27
  def should_render_a_form
28
+ warn "[DEPRECATION] should_render_a_form is deprecated."
27
29
  should "display a form" do
28
30
  assert_select "form", true, "The template doesn't contain a <form> element"
29
31
  end
30
32
  end
31
33
 
34
+ # Deprecated.
35
+ #
32
36
  # Macro that creates a test asserting that the rendered view contains the selected metatags.
33
37
  # Values can be string or Regexps.
34
38
  # Example:
@@ -40,6 +44,7 @@ module Shoulda # :nodoc:
40
44
  # Example:
41
45
  # should_render_page_with_metadata :title => /index/
42
46
  def should_render_page_with_metadata(options)
47
+ warn "[DEPRECATION] should_render_page_with_metadata is deprecated."
43
48
  options.each do |key, value|
44
49
  should "have metatag #{key}" do
45
50
  if key.to_sym == :title
@@ -30,8 +30,8 @@ module Shoulda # :nodoc:
30
30
  #
31
31
  # assert_good_value(User, :email, "user@example.com")
32
32
  #
33
- # @product = Product.new(:tangible => false)
34
- # assert_good_value(Product, :price, "0")
33
+ # product = Product.new(:tangible => false)
34
+ # assert_good_value(product, :price, "0")
35
35
  def assert_good_value(object_or_klass, attribute, value, error_message_to_avoid = nil)
36
36
  object = get_instance_of(object_or_klass)
37
37
  matcher = allow_value(value).
@@ -54,8 +54,8 @@ module Shoulda # :nodoc:
54
54
  #
55
55
  # assert_bad_value(User, :email, "invalid")
56
56
  #
57
- # @product = Product.new(:tangible => true)
58
- # assert_bad_value(Product, :price, "0")
57
+ # product = Product.new(:tangible => true)
58
+ # assert_bad_value(product, :price, "0")
59
59
  def assert_bad_value(object_or_klass, attribute, value,
60
60
  error_message_to_expect = nil)
61
61
  object = get_instance_of(object_or_klass)
@@ -8,19 +8,6 @@ module Shoulda # :nodoc:
8
8
  end
9
9
  end
10
10
 
11
- def get_instance_of(object_or_klass)
12
- if object_or_klass.is_a?(Class)
13
- klass = object_or_klass
14
- instance_variable_get("@#{instance_variable_name_for(klass)}") || klass.new
15
- else
16
- object_or_klass
17
- end
18
- end
19
-
20
- def instance_variable_name_for(klass)
21
- klass.to_s.split('::').last.underscore
22
- end
23
-
24
11
  # Helper method that determines the default error message used by Active
25
12
  # Record. Works for both existing Rails 2.1 and Rails 2.2 with the newly
26
13
  # introduced I18n module used for localization.
@@ -25,10 +25,6 @@ module Shoulda # :nodoc:
25
25
 
26
26
  # Ensures that the model cannot be saved if one of the attributes listed is not present.
27
27
  #
28
- # If an instance variable has been created in the setup named after the
29
- # model being tested, then this method will use that. Otherwise, it will
30
- # create a new instance to test against.
31
- #
32
28
  # Options:
33
29
  # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
34
30
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.blank')</tt>
@@ -38,23 +34,15 @@ module Shoulda # :nodoc:
38
34
  #
39
35
  def should_validate_presence_of(*attributes)
40
36
  message = get_options!(attributes, :message)
41
- klass = model_class
42
37
 
43
38
  attributes.each do |attribute|
44
39
  matcher = validate_presence_of(attribute).with_message(message)
45
40
  should matcher.description do
46
- assert_accepts(matcher, get_instance_of(klass))
41
+ assert_accepts(matcher, subject)
47
42
  end
48
43
  end
49
44
  end
50
45
 
51
- # Deprecated. See should_validate_presence_of
52
- def should_require_attributes(*attributes)
53
- warn "[DEPRECATION] should_require_attributes is deprecated. " <<
54
- "Use should_validate_presence_of instead."
55
- should_validate_presence_of(*attributes)
56
- end
57
-
58
46
  # Ensures that the model cannot be saved if one of the attributes listed is not unique.
59
47
  # Requires an existing record
60
48
  #
@@ -78,37 +66,27 @@ module Shoulda # :nodoc:
78
66
  scope = [*scope].compact
79
67
  case_sensitive = true if case_sensitive.nil?
80
68
 
81
- klass = model_class
82
-
83
69
  attributes.each do |attribute|
84
70
  matcher = validate_uniqueness_of(attribute).
85
71
  with_message(message).scoped_to(scope)
86
72
  matcher = matcher.case_insensitive unless case_sensitive
87
73
  should matcher.description do
88
- assert_accepts(matcher, get_instance_of(klass))
74
+ assert_accepts(matcher, subject)
89
75
  end
90
76
  end
91
77
  end
92
78
 
93
- # Deprecated. See should_validate_uniqueness_of
94
- def should_require_unique_attributes(*attributes)
95
- warn "[DEPRECATION] should_require_unique_attributes is deprecated. " <<
96
- "Use should_validate_uniqueness_of instead."
97
- should_validate_uniqueness_of(*attributes)
98
- end
99
-
100
79
  # Ensures that the attribute can be set on mass update.
101
80
  #
102
81
  # should_allow_mass_assignment_of :first_name, :last_name
103
82
  #
104
83
  def should_allow_mass_assignment_of(*attributes)
105
84
  get_options!(attributes)
106
- klass = model_class
107
85
 
108
86
  attributes.each do |attribute|
109
87
  matcher = allow_mass_assignment_of(attribute)
110
88
  should matcher.description do
111
- assert_accepts matcher, klass.new
89
+ assert_accepts matcher, subject
112
90
  end
113
91
  end
114
92
  end
@@ -119,90 +97,67 @@ module Shoulda # :nodoc:
119
97
  #
120
98
  def should_not_allow_mass_assignment_of(*attributes)
121
99
  get_options!(attributes)
122
- klass = model_class
123
100
 
124
101
  attributes.each do |attribute|
125
102
  matcher = allow_mass_assignment_of(attribute)
126
103
  should "not #{matcher.description}" do
127
- assert_rejects matcher, klass.new
104
+ assert_rejects matcher, subject
128
105
  end
129
106
  end
130
107
  end
131
108
 
132
- # Deprecated. See should_not_allow_mass_assignment_of
133
- def should_protect_attributes(*attributes)
134
- warn "[DEPRECATION] should_protect_attributes is deprecated. " <<
135
- "Use should_not_allow_mass_assignment_of instead."
136
- should_not_allow_mass_assignment_of(*attributes)
137
- end
138
-
139
109
  # Ensures that the attribute cannot be changed once the record has been created.
140
110
  #
141
111
  # should_have_readonly_attributes :password, :admin_flag
142
112
  #
143
113
  def should_have_readonly_attributes(*attributes)
144
114
  get_options!(attributes)
145
- klass = model_class
146
115
 
147
116
  attributes.each do |attribute|
148
117
  matcher = have_readonly_attribute(attribute)
149
118
  should matcher.description do
150
- assert_accepts matcher, klass.new
119
+ assert_accepts matcher, subject
151
120
  end
152
121
  end
153
122
  end
154
123
 
155
124
  # Ensures that the attribute cannot be set to the given values
156
125
  #
157
- # If an instance variable has been created in the setup named after the
158
- # model being tested, then this method will use that. Otherwise, it will
159
- # create a new instance to test against.
160
- #
161
126
  # Options:
162
127
  # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
163
- # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.invalid')</tt>
128
+ # Regexp or string. If omitted, the test will pass if there is ANY error in
129
+ # <tt>errors.on(:attribute)</tt>.
164
130
  #
165
131
  # Example:
166
132
  # should_not_allow_values_for :isbn, "bad 1", "bad 2"
167
133
  #
168
134
  def should_not_allow_values_for(attribute, *bad_values)
169
135
  message = get_options!(bad_values, :message)
170
- klass = model_class
171
136
  bad_values.each do |value|
172
137
  matcher = allow_value(value).for(attribute).with_message(message)
173
138
  should "not #{matcher.description}" do
174
- assert_rejects matcher, get_instance_of(klass)
139
+ assert_rejects matcher, subject
175
140
  end
176
141
  end
177
142
  end
178
143
 
179
144
  # Ensures that the attribute can be set to the given values.
180
145
  #
181
- # If an instance variable has been created in the setup named after the
182
- # model being tested, then this method will use that. Otherwise, it will
183
- # create a new instance to test against.
184
- #
185
146
  # Example:
186
147
  # should_allow_values_for :isbn, "isbn 1 2345 6789 0", "ISBN 1-2345-6789-0"
187
148
  #
188
149
  def should_allow_values_for(attribute, *good_values)
189
150
  get_options!(good_values)
190
- klass = model_class
191
- klass = model_class
192
151
  good_values.each do |value|
193
152
  matcher = allow_value(value).for(attribute)
194
153
  should matcher.description do
195
- assert_accepts matcher, get_instance_of(klass)
154
+ assert_accepts matcher, subject
196
155
  end
197
156
  end
198
157
  end
199
158
 
200
159
  # Ensures that the length of the attribute is in the given range
201
160
  #
202
- # If an instance variable has been created in the setup named after the
203
- # model being tested, then this method will use that. Otherwise, it will
204
- # create a new instance to test against.
205
- #
206
161
  # Options:
207
162
  # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
208
163
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % range.first</tt>
@@ -216,8 +171,6 @@ module Shoulda # :nodoc:
216
171
  short_message, long_message = get_options!([opts],
217
172
  :short_message,
218
173
  :long_message)
219
- klass = model_class
220
-
221
174
  matcher = ensure_length_of(attribute).
222
175
  is_at_least(range.first).
223
176
  with_short_message(short_message).
@@ -225,16 +178,12 @@ module Shoulda # :nodoc:
225
178
  with_long_message(long_message)
226
179
 
227
180
  should matcher.description do
228
- assert_accepts matcher, get_instance_of(klass)
181
+ assert_accepts matcher, subject
229
182
  end
230
183
  end
231
184
 
232
185
  # Ensures that the length of the attribute is at least a certain length
233
186
  #
234
- # If an instance variable has been created in the setup named after the
235
- # model being tested, then this method will use that. Otherwise, it will
236
- # create a new instance to test against.
237
- #
238
187
  # Options:
239
188
  # * <tt>:short_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
240
189
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.too_short') % min_length</tt>
@@ -244,23 +193,18 @@ module Shoulda # :nodoc:
244
193
  #
245
194
  def should_ensure_length_at_least(attribute, min_length, opts = {})
246
195
  short_message = get_options!([opts], :short_message)
247
- klass = model_class
248
196
 
249
197
  matcher = ensure_length_of(attribute).
250
198
  is_at_least(min_length).
251
199
  with_short_message(short_message)
252
200
 
253
201
  should matcher.description do
254
- assert_accepts matcher, get_instance_of(klass)
202
+ assert_accepts matcher, subject
255
203
  end
256
204
  end
257
205
 
258
206
  # Ensures that the length of the attribute is exactly a certain length
259
207
  #
260
- # If an instance variable has been created in the setup named after the
261
- # model being tested, then this method will use that. Otherwise, it will
262
- # create a new instance to test against.
263
- #
264
208
  # Options:
265
209
  # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
266
210
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.wrong_length') % length</tt>
@@ -270,22 +214,17 @@ module Shoulda # :nodoc:
270
214
  #
271
215
  def should_ensure_length_is(attribute, length, opts = {})
272
216
  message = get_options!([opts], :message)
273
- klass = model_class
274
217
  matcher = ensure_length_of(attribute).
275
218
  is_equal_to(length).
276
219
  with_message(message)
277
220
 
278
221
  should matcher.description do
279
- assert_accepts matcher, get_instance_of(klass)
222
+ assert_accepts matcher, subject
280
223
  end
281
224
  end
282
225
 
283
226
  # Ensure that the attribute is in the range specified
284
227
  #
285
- # If an instance variable has been created in the setup named after the
286
- # model being tested, then this method will use that. Otherwise, it will
287
- # create a new instance to test against.
288
- #
289
228
  # Options:
290
229
  # * <tt>:low_message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
291
230
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.inclusion')</tt>
@@ -300,23 +239,18 @@ module Shoulda # :nodoc:
300
239
  :message,
301
240
  :low_message,
302
241
  :high_message)
303
- klass = model_class
304
242
  matcher = ensure_inclusion_of(attribute).
305
243
  in_range(range).
306
244
  with_message(message).
307
245
  with_low_message(low_message).
308
246
  with_high_message(high_message)
309
247
  should matcher.description do
310
- assert_accepts matcher, get_instance_of(klass)
248
+ assert_accepts matcher, subject
311
249
  end
312
250
  end
313
251
 
314
252
  # Ensure that the attribute is numeric
315
253
  #
316
- # If an instance variable has been created in the setup named after the
317
- # model being tested, then this method will use that. Otherwise, it will
318
- # create a new instance to test against.
319
- #
320
254
  # Options:
321
255
  # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
322
256
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.not_a_number')</tt>
@@ -326,23 +260,15 @@ module Shoulda # :nodoc:
326
260
  #
327
261
  def should_validate_numericality_of(*attributes)
328
262
  message = get_options!(attributes, :message)
329
- klass = model_class
330
263
  attributes.each do |attribute|
331
264
  matcher = validate_numericality_of(attribute).
332
265
  with_message(message)
333
266
  should matcher.description do
334
- assert_accepts matcher, get_instance_of(klass)
267
+ assert_accepts matcher, subject
335
268
  end
336
269
  end
337
270
  end
338
271
 
339
- # Deprecated. See should_validate_numericality_of
340
- def should_only_allow_numeric_values_for(*attributes)
341
- warn "[DEPRECATION] should_only_allow_numeric_values_for is " <<
342
- "deprecated. Use should_validate_numericality_of instead."
343
- should_validate_numericality_of(*attributes)
344
- end
345
-
346
272
  # Ensures that the has_many relationship exists. Will also test that the
347
273
  # associated table has the required columns. Works with polymorphic
348
274
  # associations.
@@ -358,11 +284,10 @@ module Shoulda # :nodoc:
358
284
  #
359
285
  def should_have_many(*associations)
360
286
  through, dependent = get_options!(associations, :through, :dependent)
361
- klass = model_class
362
287
  associations.each do |association|
363
288
  matcher = have_many(association).through(through).dependent(dependent)
364
289
  should matcher.description do
365
- assert_accepts(matcher, klass.new)
290
+ assert_accepts(matcher, subject)
366
291
  end
367
292
  end
368
293
  end
@@ -378,12 +303,11 @@ module Shoulda # :nodoc:
378
303
  # should_have_one :god # unless hindu
379
304
  #
380
305
  def should_have_one(*associations)
381
- dependent = get_options!(associations, :dependent)
382
- klass = model_class
306
+ dependent, through = get_options!(associations, :dependent, :through)
383
307
  associations.each do |association|
384
- matcher = have_one(association).dependent(dependent)
308
+ matcher = have_one(association).dependent(dependent).through(through)
385
309
  should matcher.description do
386
- assert_accepts(matcher, klass.new)
310
+ assert_accepts(matcher, subject)
387
311
  end
388
312
  end
389
313
  end
@@ -395,12 +319,11 @@ module Shoulda # :nodoc:
395
319
  #
396
320
  def should_have_and_belong_to_many(*associations)
397
321
  get_options!(associations)
398
- klass = model_class
399
322
 
400
323
  associations.each do |association|
401
324
  matcher = have_and_belong_to_many(association)
402
325
  should matcher.description do
403
- assert_accepts(matcher, klass.new)
326
+ assert_accepts(matcher, subject)
404
327
  end
405
328
  end
406
329
  end
@@ -411,11 +334,10 @@ module Shoulda # :nodoc:
411
334
  #
412
335
  def should_belong_to(*associations)
413
336
  dependent = get_options!(associations, :dependent)
414
- klass = model_class
415
337
  associations.each do |association|
416
338
  matcher = belong_to(association).dependent(dependent)
417
339
  should matcher.description do
418
- assert_accepts(matcher, klass.new)
340
+ assert_accepts(matcher, subject)
419
341
  end
420
342
  end
421
343
  end
@@ -426,7 +348,7 @@ module Shoulda # :nodoc:
426
348
  #
427
349
  def should_have_class_methods(*methods)
428
350
  get_options!(methods)
429
- klass = model_class
351
+ klass = described_type
430
352
  methods.each do |method|
431
353
  should "respond to class method ##{method}" do
432
354
  assert_respond_to klass, method, "#{klass.name} does not have class method #{method}"
@@ -440,7 +362,7 @@ module Shoulda # :nodoc:
440
362
  #
441
363
  def should_have_instance_methods(*methods)
442
364
  get_options!(methods)
443
- klass = model_class
365
+ klass = described_type
444
366
  methods.each do |method|
445
367
  should "respond to instance method ##{method}" do
446
368
  assert_respond_to klass.new, method, "#{klass.name} does not have instance method #{method}"
@@ -449,7 +371,7 @@ module Shoulda # :nodoc:
449
371
  end
450
372
 
451
373
  # Ensure that the given columns are defined on the models backing SQL table.
452
- # Also aliased to should_have_index for readability.
374
+ # Also aliased to should_have_db_column for readability.
453
375
  # Takes the same options available in migrations:
454
376
  # :type, :precision, :limit, :default, :null, and :scale
455
377
  #
@@ -465,7 +387,6 @@ module Shoulda # :nodoc:
465
387
  column_type, precision, limit, default, null, scale, sql_type =
466
388
  get_options!(columns, :type, :precision, :limit,
467
389
  :default, :null, :scale, :sql_type)
468
- klass = model_class
469
390
  columns.each do |name|
470
391
  matcher = have_db_column(name).
471
392
  of_type(column_type).
@@ -473,7 +394,7 @@ module Shoulda # :nodoc:
473
394
  :default => default, :null => null,
474
395
  :scale => scale, :sql_type => sql_type)
475
396
  should matcher.description do
476
- assert_accepts(matcher, klass.new)
397
+ assert_accepts(matcher, subject)
477
398
  end
478
399
  end
479
400
  end
@@ -481,7 +402,7 @@ module Shoulda # :nodoc:
481
402
  alias_method :should_have_db_column, :should_have_db_columns
482
403
 
483
404
  # Ensures that there are DB indices on the given columns or tuples of columns.
484
- # Also aliased to should_have_index for readability
405
+ # Also aliased to should_have_db_index for readability
485
406
  #
486
407
  # Options:
487
408
  # * <tt>:unique</tt> - whether or not the index has a unique
@@ -492,30 +413,39 @@ module Shoulda # :nodoc:
492
413
  #
493
414
  # Examples:
494
415
  #
495
- # should_have_indices :email, :name, [:commentable_type, :commentable_id]
496
- # should_have_index :age
497
- # should_have_index :ssn, :unique => true
416
+ # should_have_db_indices :email, :name, [:commentable_type, :commentable_id]
417
+ # should_have_db_index :age
418
+ # should_have_db_index :ssn, :unique => true
498
419
  #
499
- def should_have_indices(*columns)
420
+ def should_have_db_indices(*columns)
500
421
  unique = get_options!(columns, :unique)
501
- klass = model_class
502
422
 
503
423
  columns.each do |column|
504
- matcher = have_index(column).unique(unique)
424
+ matcher = have_db_index(column).unique(unique)
505
425
  should matcher.description do
506
- assert_accepts(matcher, klass.new)
426
+ assert_accepts(matcher, subject)
507
427
  end
508
428
  end
509
429
  end
510
430
 
511
- alias_method :should_have_index, :should_have_indices
431
+ alias_method :should_have_db_index, :should_have_db_indices
432
+
433
+ # Deprecated. See should_have_db_index
434
+ def should_have_index(*args)
435
+ warn "[DEPRECATION] should_have_index is deprecated. " <<
436
+ "Use should_have_db_index instead."
437
+ should_have_db_index(*args)
438
+ end
439
+
440
+ # Deprecated. See should_have_db_indices
441
+ def should_have_indices(*args)
442
+ warn "[DEPRECATION] should_have_indices is deprecated. " <<
443
+ "Use should_have_db_indices instead."
444
+ should_have_db_indices(*args)
445
+ end
512
446
 
513
447
  # Ensures that the model cannot be saved if one of the attributes listed is not accepted.
514
448
  #
515
- # If an instance variable has been created in the setup named after the
516
- # model being tested, then this method will use that. Otherwise, it will
517
- # create a new instance to test against.
518
- #
519
449
  # Options:
520
450
  # * <tt>:message</tt> - value the test expects to find in <tt>errors.on(:attribute)</tt>.
521
451
  # Regexp or string. Default = <tt>I18n.translate('activerecord.errors.messages.accepted')</tt>
@@ -525,23 +455,17 @@ module Shoulda # :nodoc:
525
455
  #
526
456
  def should_validate_acceptance_of(*attributes)
527
457
  message = get_options!(attributes, :message)
528
- klass = model_class
529
458
 
530
459
  attributes.each do |attribute|
531
460
  matcher = validate_acceptance_of(attribute).with_message(message)
532
461
  should matcher.description do
533
- assert_accepts matcher, get_instance_of(klass)
462
+ assert_accepts matcher, subject
534
463
  end
535
464
  end
536
465
  end
537
466
 
538
- # Deprecated. See should_validate_uniqueness_of
539
- def should_require_acceptance_of(*attributes)
540
- warn "[DEPRECATION] should_require_acceptance_of is deprecated. " <<
541
- "Use should_validate_acceptance_of instead."
542
- should_validate_acceptance_of(*attributes)
543
- end
544
-
467
+ # Deprecated.
468
+ #
545
469
  # Ensures that the model has a method named scope_name that returns a NamedScope object with the
546
470
  # proxy options set to the options you supply. scope_name can be either a symbol, or a method
547
471
  # call which will be evaled against the model. The eval'd method call has access to all the same
@@ -578,10 +502,9 @@ module Shoulda # :nodoc:
578
502
  # end
579
503
  #
580
504
  def should_have_named_scope(scope_call, find_options = nil)
581
- klass = model_class
582
505
  matcher = have_named_scope(scope_call).finding(find_options)
583
506
  should matcher.description do
584
- assert_accepts matcher.in_context(self), klass.new
507
+ assert_accepts matcher.in_context(self), subject
585
508
  end
586
509
  end
587
510
  end