shoulda-matchers 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +11 -0
- data/.travis.yml +13 -0
- data/Appraisals +4 -6
- data/CONTRIBUTING.md +38 -0
- data/Gemfile +8 -5
- data/Gemfile.lock +77 -41
- data/NEWS.md +32 -0
- data/README.md +84 -0
- data/Rakefile +5 -36
- data/features/rails_integration.feature +88 -0
- data/features/step_definitions/rails_steps.rb +111 -0
- data/features/support/env.rb +5 -0
- data/gemfiles/3.0.gemfile +14 -0
- data/gemfiles/3.0.gemfile.lock +142 -0
- data/gemfiles/3.1.gemfile +16 -0
- data/gemfiles/3.1.gemfile.lock +164 -0
- data/lib/shoulda/matchers/action_controller/assign_to_matcher.rb +6 -9
- data/lib/shoulda/matchers/action_controller/filter_param_matcher.rb +1 -3
- data/lib/shoulda/matchers/action_controller/redirect_to_matcher.rb +10 -6
- data/lib/shoulda/matchers/action_controller/render_template_matcher.rb +1 -4
- data/lib/shoulda/matchers/action_controller/render_with_layout_matcher.rb +6 -6
- data/lib/shoulda/matchers/action_controller/respond_with_content_type_matcher.rb +11 -10
- data/lib/shoulda/matchers/action_controller/respond_with_matcher.rb +0 -2
- data/lib/shoulda/matchers/action_controller/route_matcher.rb +17 -14
- data/lib/shoulda/matchers/action_controller/set_session_matcher.rb +24 -16
- data/lib/shoulda/matchers/action_controller/set_the_flash_matcher.rb +52 -15
- data/lib/shoulda/matchers/action_mailer.rb +1 -1
- data/lib/shoulda/matchers/action_mailer/{have_sent_email.rb → have_sent_email_matcher.rb} +37 -21
- data/lib/shoulda/matchers/active_model.rb +1 -0
- data/lib/shoulda/matchers/active_model/allow_mass_assignment_of_matcher.rb +9 -10
- data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +60 -33
- data/lib/shoulda/matchers/active_model/ensure_length_of_matcher.rb +0 -1
- data/lib/shoulda/matchers/active_model/helpers.rb +13 -9
- data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +63 -0
- data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +38 -8
- data/lib/shoulda/matchers/active_model/validation_matcher.rb +1 -5
- data/lib/shoulda/matchers/active_record.rb +3 -1
- data/lib/shoulda/matchers/active_record/accept_nested_attributes_for_matcher.rb +127 -0
- data/lib/shoulda/matchers/active_record/association_matcher.rb +19 -7
- data/lib/shoulda/matchers/active_record/have_db_column_matcher.rb +20 -5
- data/lib/shoulda/matchers/active_record/have_db_index_matcher.rb +4 -10
- data/lib/shoulda/matchers/active_record/have_readonly_attribute_matcher.rb +3 -7
- data/lib/shoulda/matchers/active_record/query_the_database_matcher.rb +107 -0
- data/lib/shoulda/matchers/active_record/serialize_matcher.rb +111 -0
- data/lib/shoulda/matchers/integrations/rspec.rb +0 -1
- data/lib/shoulda/matchers/version.rb +1 -1
- data/shoulda-matchers.gemspec +30 -0
- data/spec/fixtures/addresses.yml +3 -0
- data/spec/fixtures/friendships.yml +0 -0
- data/spec/fixtures/posts.yml +5 -0
- data/spec/fixtures/products.yml +0 -0
- data/spec/fixtures/taggings.yml +0 -0
- data/spec/fixtures/tags.yml +9 -0
- data/spec/fixtures/users.yml +6 -0
- data/spec/shoulda/action_controller/assign_to_matcher_spec.rb +61 -0
- data/spec/shoulda/action_controller/filter_param_matcher_spec.rb +20 -0
- data/spec/shoulda/action_controller/redirect_to_matcher_spec.rb +40 -0
- data/spec/shoulda/action_controller/render_template_matcher_spec.rb +69 -0
- data/spec/shoulda/action_controller/render_with_layout_matcher_spec.rb +47 -0
- data/spec/shoulda/action_controller/respond_with_content_type_matcher_spec.rb +28 -0
- data/spec/shoulda/action_controller/respond_with_matcher_spec.rb +83 -0
- data/spec/shoulda/action_controller/route_matcher_spec.rb +65 -0
- data/spec/shoulda/action_controller/set_session_matcher_spec.rb +46 -0
- data/spec/shoulda/action_controller/set_the_flash_matcher_spec.rb +124 -0
- data/spec/shoulda/action_mailer/have_sent_email_spec.rb +293 -0
- data/spec/shoulda/active_model/allow_mass_assignment_of_matcher_spec.rb +95 -0
- data/spec/shoulda/active_model/allow_value_matcher_spec.rb +91 -0
- data/spec/shoulda/active_model/ensure_exclusion_of_matcher_spec.rb +57 -0
- data/spec/shoulda/active_model/ensure_inclusion_of_matcher_spec.rb +71 -0
- data/spec/shoulda/active_model/ensure_length_of_matcher_spec.rb +125 -0
- data/spec/shoulda/active_model/helpers_spec.rb +100 -0
- data/spec/shoulda/active_model/validate_acceptance_of_matcher_spec.rb +43 -0
- data/spec/shoulda/active_model/validate_confirmation_of_matcher_spec.rb +48 -0
- data/spec/shoulda/active_model/validate_format_of_matcher_spec.rb +38 -0
- data/spec/shoulda/active_model/validate_numericality_of_matcher_spec.rb +62 -0
- data/spec/shoulda/active_model/validate_presence_of_matcher_spec.rb +121 -0
- data/spec/shoulda/active_model/validate_uniqueness_of_matcher_spec.rb +143 -0
- data/spec/shoulda/active_record/accept_nested_attributes_for_matcher_spec.rb +84 -0
- data/spec/shoulda/active_record/association_matcher_spec.rb +449 -0
- data/spec/shoulda/active_record/have_db_column_matcher_spec.rb +185 -0
- data/spec/shoulda/active_record/have_db_index_matcher_spec.rb +88 -0
- data/spec/shoulda/active_record/have_readonly_attributes_matcher_spec.rb +46 -0
- data/spec/shoulda/active_record/query_the_database_matcher_spec.rb +45 -0
- data/spec/shoulda/active_record/serialize_matcher_spec.rb +81 -0
- data/spec/spec_helper.rb +31 -0
- data/spec/support/model_builder.rb +149 -0
- metadata +211 -60
- data/CONTRIBUTION_GUIDELINES.rdoc +0 -10
- data/README.rdoc +0 -80
@@ -1,16 +1,17 @@
|
|
1
1
|
module Shoulda # :nodoc:
|
2
2
|
module Matchers
|
3
3
|
module ActiveModel # :nodoc:
|
4
|
-
|
5
4
|
# Ensure that the attribute is numeric
|
6
5
|
#
|
7
6
|
# Options:
|
8
7
|
# * <tt>with_message</tt> - value the test expects to find in
|
9
8
|
# <tt>errors.on(:attribute)</tt>. Regexp or string. Defaults to the
|
10
9
|
# translation for <tt>:not_a_number</tt>.
|
10
|
+
# * <tt>only_integer</tt> - allows only integer values
|
11
11
|
#
|
12
|
-
#
|
13
|
-
# it { should validate_numericality_of(:
|
12
|
+
# Examples:
|
13
|
+
# it { should validate_numericality_of(:price) }
|
14
|
+
# it { should validate_numericality_of(:age).only_integer }
|
14
15
|
#
|
15
16
|
def validate_numericality_of(attr)
|
16
17
|
ValidateNumericalityOfMatcher.new(attr)
|
@@ -18,22 +19,51 @@ module Shoulda # :nodoc:
|
|
18
19
|
|
19
20
|
class ValidateNumericalityOfMatcher < ValidationMatcher # :nodoc:
|
20
21
|
|
22
|
+
def only_integer
|
23
|
+
@only_integer = true
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
21
27
|
def with_message(message)
|
22
|
-
|
28
|
+
if message
|
29
|
+
@expected_message = message
|
30
|
+
end
|
23
31
|
self
|
24
32
|
end
|
25
33
|
|
26
34
|
def matches?(subject)
|
27
35
|
super(subject)
|
28
|
-
|
29
|
-
disallows_value_of('abcd', @expected_message)
|
36
|
+
disallows_non_integers? && disallows_text?
|
30
37
|
end
|
31
38
|
|
32
39
|
def description
|
33
|
-
"only allow
|
40
|
+
"only allow #{allowed_type} values for #{@attribute}"
|
34
41
|
end
|
35
|
-
end
|
36
42
|
|
43
|
+
private
|
44
|
+
|
45
|
+
def allowed_type
|
46
|
+
if @only_integer
|
47
|
+
"integer"
|
48
|
+
else
|
49
|
+
"numeric"
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def disallows_non_integers?
|
54
|
+
if @only_integer
|
55
|
+
message = @expected_message || :not_an_integer
|
56
|
+
disallows_value_of(0.1, message) && disallows_value_of('0.1', message)
|
57
|
+
else
|
58
|
+
true
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def disallows_text?
|
63
|
+
message = @expected_message || :not_a_number
|
64
|
+
disallows_value_of('abcd', message)
|
65
|
+
end
|
66
|
+
end
|
37
67
|
end
|
38
68
|
end
|
39
69
|
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
module Shoulda # :nodoc:
|
2
2
|
module Matchers
|
3
3
|
module ActiveModel # :nodoc:
|
4
|
-
|
5
4
|
class ValidationMatcher # :nodoc:
|
6
|
-
|
7
5
|
attr_reader :failure_message
|
8
6
|
|
9
7
|
def initialize(attribute)
|
@@ -49,8 +47,6 @@ module Shoulda # :nodoc:
|
|
49
47
|
end
|
50
48
|
end
|
51
49
|
end
|
52
|
-
|
53
50
|
end
|
54
51
|
end
|
55
|
-
|
56
|
-
end
|
52
|
+
end
|
@@ -2,7 +2,9 @@ require 'shoulda/matchers/active_record/association_matcher'
|
|
2
2
|
require 'shoulda/matchers/active_record/have_db_column_matcher'
|
3
3
|
require 'shoulda/matchers/active_record/have_db_index_matcher'
|
4
4
|
require 'shoulda/matchers/active_record/have_readonly_attribute_matcher'
|
5
|
-
|
5
|
+
require 'shoulda/matchers/active_record/serialize_matcher'
|
6
|
+
require 'shoulda/matchers/active_record/query_the_database_matcher'
|
7
|
+
require 'shoulda/matchers/active_record/accept_nested_attributes_for_matcher'
|
6
8
|
|
7
9
|
module Shoulda
|
8
10
|
module Matchers
|
@@ -0,0 +1,127 @@
|
|
1
|
+
module Shoulda
|
2
|
+
module Matchers
|
3
|
+
module ActiveRecord
|
4
|
+
# Ensures that the model can accept nested attributes for the specified
|
5
|
+
# association.
|
6
|
+
#
|
7
|
+
# Options:
|
8
|
+
# * <tt>allow_destroy</tt> - Whether or not to allow destroy
|
9
|
+
# * <tt>limit</tt> - Max number of nested attributes
|
10
|
+
# * <tt>update_only</tt> - Only allow updates
|
11
|
+
#
|
12
|
+
# Example:
|
13
|
+
# it { should accept_nested_attributes_for(:friends) }
|
14
|
+
# it { should accept_nested_attributes_for(:friends).
|
15
|
+
# allow_destroy(true).
|
16
|
+
# limit(4) }
|
17
|
+
# it { should accept_nested_attributes_for(:friends).
|
18
|
+
# update_only(true) }
|
19
|
+
#
|
20
|
+
def accept_nested_attributes_for(name)
|
21
|
+
AcceptNestedAttributesForMatcher.new(name)
|
22
|
+
end
|
23
|
+
|
24
|
+
class AcceptNestedAttributesForMatcher
|
25
|
+
def initialize(name)
|
26
|
+
@name = name
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def allow_destroy(allow_destroy)
|
31
|
+
@allow_destroy = allow_destroy
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def limit(limit)
|
36
|
+
@limit = limit
|
37
|
+
self
|
38
|
+
end
|
39
|
+
|
40
|
+
def update_only(update_only)
|
41
|
+
@update_only = update_only
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
def matches?(subject)
|
46
|
+
@subject = subject
|
47
|
+
exists? &&
|
48
|
+
allow_destroy_correct? &&
|
49
|
+
limit_correct? &&
|
50
|
+
update_only_correct?
|
51
|
+
end
|
52
|
+
|
53
|
+
def failure_message
|
54
|
+
"Expected #{expectation} (#{@problem})"
|
55
|
+
end
|
56
|
+
|
57
|
+
def negative_failure_message
|
58
|
+
"Did not expect #{expectation}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def description
|
62
|
+
description = "accepts_nested_attributes_for :#{@name}"
|
63
|
+
description += " allow_destroy => #{@allow_destroy}" if @allow_destroy
|
64
|
+
description += " limit => #{@limit}" if @limit
|
65
|
+
description += " update_only => #{@update_only}" if @update_only
|
66
|
+
description
|
67
|
+
end
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def exists?
|
72
|
+
if config
|
73
|
+
true
|
74
|
+
else
|
75
|
+
@problem = "is not declared"
|
76
|
+
false
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def allow_destroy_correct?
|
81
|
+
if @allow_destroy.nil? || @allow_destroy == config[:allow_destroy]
|
82
|
+
true
|
83
|
+
else
|
84
|
+
@problem = (@allow_destroy ? "should" : "should not") +
|
85
|
+
" allow destroy"
|
86
|
+
false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def limit_correct?
|
91
|
+
if @limit.nil? || @limit == config[:limit]
|
92
|
+
true
|
93
|
+
else
|
94
|
+
@problem = "limit should be #@limit, got #{config[:limit]}"
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def update_only_correct?
|
100
|
+
if @update_only.nil? || @update_only == config[:update_only]
|
101
|
+
true
|
102
|
+
else
|
103
|
+
@problem = (@update_only ? "should" : "should not") +
|
104
|
+
" be update only"
|
105
|
+
false
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def config
|
110
|
+
model_config[@name]
|
111
|
+
end
|
112
|
+
|
113
|
+
def model_config
|
114
|
+
model_class.nested_attributes_options
|
115
|
+
end
|
116
|
+
|
117
|
+
def model_class
|
118
|
+
@subject.class
|
119
|
+
end
|
120
|
+
|
121
|
+
def expectation
|
122
|
+
"#{model_class.name} to accept nested attributes for #{@name}"
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
module Shoulda # :nodoc:
|
2
2
|
module Matchers
|
3
3
|
module ActiveRecord # :nodoc:
|
4
|
-
|
5
4
|
# Ensure that the belongs_to relationship exists.
|
6
5
|
#
|
7
6
|
# it { should belong_to(:parent) }
|
@@ -166,7 +165,7 @@ module Shoulda # :nodoc:
|
|
166
165
|
if @through == reflection.options[:through]
|
167
166
|
true
|
168
167
|
else
|
169
|
-
@missing = "Expected #{model_class.name} to have #{@name} through #{@through}, "
|
168
|
+
@missing = "Expected #{model_class.name} to have #{@name} through #{@through}, " +
|
170
169
|
"but got it through #{reflection.options[:through]}"
|
171
170
|
false
|
172
171
|
end
|
@@ -210,7 +209,7 @@ module Shoulda # :nodoc:
|
|
210
209
|
|
211
210
|
def join_table_exists?
|
212
211
|
if @macro != :has_and_belongs_to_many ||
|
213
|
-
::ActiveRecord::Base.connection.tables.include?(join_table
|
212
|
+
::ActiveRecord::Base.connection.tables.include?(join_table)
|
214
213
|
true
|
215
214
|
else
|
216
215
|
@missing = "join table #{join_table} doesn't exist"
|
@@ -219,7 +218,7 @@ module Shoulda # :nodoc:
|
|
219
218
|
end
|
220
219
|
|
221
220
|
def class_has_foreign_key?(klass)
|
222
|
-
if klass.column_names.include?(foreign_key
|
221
|
+
if klass.column_names.include?(foreign_key)
|
223
222
|
true
|
224
223
|
else
|
225
224
|
@missing = "#{klass} does not have a #{foreign_key} foreign key."
|
@@ -232,7 +231,7 @@ module Shoulda # :nodoc:
|
|
232
231
|
end
|
233
232
|
|
234
233
|
def join_table
|
235
|
-
reflection.options[:join_table]
|
234
|
+
reflection.options[:join_table].to_s
|
236
235
|
end
|
237
236
|
|
238
237
|
def associated_class
|
@@ -240,7 +239,13 @@ module Shoulda # :nodoc:
|
|
240
239
|
end
|
241
240
|
|
242
241
|
def foreign_key
|
243
|
-
|
242
|
+
if foreign_key_reflection
|
243
|
+
if foreign_key_reflection.respond_to?(:foreign_key)
|
244
|
+
foreign_key_reflection.foreign_key.to_s
|
245
|
+
else
|
246
|
+
foreign_key_reflection.primary_key_name.to_s
|
247
|
+
end
|
248
|
+
end
|
244
249
|
end
|
245
250
|
|
246
251
|
def through?
|
@@ -251,6 +256,14 @@ module Shoulda # :nodoc:
|
|
251
256
|
@reflection ||= model_class.reflect_on_association(@name)
|
252
257
|
end
|
253
258
|
|
259
|
+
def foreign_key_reflection
|
260
|
+
if [:has_one, :has_many].include?(@macro) && reflection.options.include?(:inverse_of)
|
261
|
+
associated_class.reflect_on_association(reflection.options[:inverse_of])
|
262
|
+
else
|
263
|
+
reflection
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
254
267
|
def through_reflection
|
255
268
|
@through_reflection ||= model_class.reflect_on_association(@through)
|
256
269
|
end
|
@@ -269,7 +282,6 @@ module Shoulda # :nodoc:
|
|
269
282
|
end
|
270
283
|
end
|
271
284
|
end
|
272
|
-
|
273
285
|
end
|
274
286
|
end
|
275
287
|
end
|
@@ -16,12 +16,11 @@ module Shoulda # :nodoc:
|
|
16
16
|
# with_options(:precision => 10, :scale => 2) }
|
17
17
|
#
|
18
18
|
def have_db_column(column)
|
19
|
-
HaveDbColumnMatcher.new(
|
19
|
+
HaveDbColumnMatcher.new(column)
|
20
20
|
end
|
21
21
|
|
22
22
|
class HaveDbColumnMatcher # :nodoc:
|
23
|
-
def initialize(
|
24
|
-
@macro = macro
|
23
|
+
def initialize(column)
|
25
24
|
@column = column
|
26
25
|
end
|
27
26
|
|
@@ -36,6 +35,7 @@ module Shoulda # :nodoc:
|
|
36
35
|
@default = opts[:default]
|
37
36
|
@null = opts[:null]
|
38
37
|
@scale = opts[:scale]
|
38
|
+
@primary = opts[:primary]
|
39
39
|
self
|
40
40
|
end
|
41
41
|
|
@@ -47,7 +47,8 @@ module Shoulda # :nodoc:
|
|
47
47
|
correct_limit? &&
|
48
48
|
correct_default? &&
|
49
49
|
correct_null? &&
|
50
|
-
correct_scale?
|
50
|
+
correct_scale? &&
|
51
|
+
correct_primary?
|
51
52
|
end
|
52
53
|
|
53
54
|
def failure_message
|
@@ -151,6 +152,21 @@ module Shoulda # :nodoc:
|
|
151
152
|
end
|
152
153
|
end
|
153
154
|
|
155
|
+
def correct_primary?
|
156
|
+
return true if @primary.nil?
|
157
|
+
if matched_column.primary == @primary
|
158
|
+
true
|
159
|
+
else
|
160
|
+
@missing = "#{model_class} has a db column named #{@column} "
|
161
|
+
if @primary
|
162
|
+
@missing << "that is not primary, but should be"
|
163
|
+
else
|
164
|
+
@missing << "that is primary, but should not be"
|
165
|
+
end
|
166
|
+
false
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
154
170
|
def matched_column
|
155
171
|
model_class.columns.detect { |each| each.name == @column.to_s }
|
156
172
|
end
|
@@ -163,7 +179,6 @@ module Shoulda # :nodoc:
|
|
163
179
|
expected = "#{model_class.name} to #{description}"
|
164
180
|
end
|
165
181
|
end
|
166
|
-
|
167
182
|
end
|
168
183
|
end
|
169
184
|
end
|
@@ -19,12 +19,11 @@ module Shoulda # :nodoc:
|
|
19
19
|
# it { should have_db_index(:ssn).unique(true) }
|
20
20
|
#
|
21
21
|
def have_db_index(columns)
|
22
|
-
HaveDbIndexMatcher.new(
|
22
|
+
HaveDbIndexMatcher.new(columns)
|
23
23
|
end
|
24
24
|
|
25
25
|
class HaveDbIndexMatcher # :nodoc:
|
26
|
-
def initialize(
|
27
|
-
@macro = macro
|
26
|
+
def initialize(columns)
|
28
27
|
@columns = normalize_columns_to_array(columns)
|
29
28
|
end
|
30
29
|
|
@@ -84,7 +83,7 @@ module Shoulda # :nodoc:
|
|
84
83
|
end
|
85
84
|
|
86
85
|
def expectation
|
87
|
-
|
86
|
+
"#{model_class.name} to #{description}"
|
88
87
|
end
|
89
88
|
|
90
89
|
def index_type
|
@@ -99,14 +98,9 @@ module Shoulda # :nodoc:
|
|
99
98
|
end
|
100
99
|
|
101
100
|
def normalize_columns_to_array(columns)
|
102
|
-
|
103
|
-
columns.collect { |each| each.to_s }
|
104
|
-
else
|
105
|
-
[columns.to_s]
|
106
|
-
end
|
101
|
+
Array.wrap(columns).map(&:to_s)
|
107
102
|
end
|
108
103
|
end
|
109
|
-
|
110
104
|
end
|
111
105
|
end
|
112
106
|
end
|
@@ -12,16 +12,16 @@ module Shoulda # :nodoc:
|
|
12
12
|
end
|
13
13
|
|
14
14
|
class HaveReadonlyAttributeMatcher # :nodoc:
|
15
|
-
|
16
15
|
def initialize(attribute)
|
17
16
|
@attribute = attribute.to_s
|
18
17
|
end
|
19
18
|
|
19
|
+
attr_reader :failure_message, :negative_failure_message
|
20
|
+
|
20
21
|
def matches?(subject)
|
21
22
|
@subject = subject
|
22
23
|
if readonly_attributes.include?(@attribute)
|
23
|
-
@negative_failure_message =
|
24
|
-
"Did not expect #{@attribute} to be read-only"
|
24
|
+
@negative_failure_message = "Did not expect #{@attribute} to be read-only"
|
25
25
|
true
|
26
26
|
else
|
27
27
|
if readonly_attributes.empty?
|
@@ -36,8 +36,6 @@ module Shoulda # :nodoc:
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
attr_reader :failure_message, :negative_failure_message
|
40
|
-
|
41
39
|
def description
|
42
40
|
"make #{@attribute} read-only"
|
43
41
|
end
|
@@ -51,9 +49,7 @@ module Shoulda # :nodoc:
|
|
51
49
|
def class_name
|
52
50
|
@subject.class.name
|
53
51
|
end
|
54
|
-
|
55
52
|
end
|
56
|
-
|
57
53
|
end
|
58
54
|
end
|
59
55
|
end
|