instructure-active_model-better_errors 1.6.3.rails2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. data/.document +5 -0
  2. data/.gitmodules +3 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +3 -0
  5. data/Gemfile +18 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.md +183 -0
  8. data/Rakefile +57 -0
  9. data/VERSION +1 -0
  10. data/active_model-better_errors.gemspec +110 -0
  11. data/lib/active_model/better_errors.rb +17 -0
  12. data/lib/active_model/error_collecting/array_reporter.rb +9 -0
  13. data/lib/active_model/error_collecting/core_ext.rb +6 -0
  14. data/lib/active_model/error_collecting/emulation.rb +65 -0
  15. data/lib/active_model/error_collecting/error_collection.rb +86 -0
  16. data/lib/active_model/error_collecting/error_message.rb +88 -0
  17. data/lib/active_model/error_collecting/error_message_set.rb +33 -0
  18. data/lib/active_model/error_collecting/errors.rb +52 -0
  19. data/lib/active_model/error_collecting/hash_reporter.rb +9 -0
  20. data/lib/active_model/error_collecting/human_array_reporter.rb +9 -0
  21. data/lib/active_model/error_collecting/human_hash_reporter.rb +15 -0
  22. data/lib/active_model/error_collecting/human_message_formatter.rb +72 -0
  23. data/lib/active_model/error_collecting/human_message_reporter.rb +32 -0
  24. data/lib/active_model/error_collecting/machine_array_reporter.rb +19 -0
  25. data/lib/active_model/error_collecting/machine_hash_reporter.rb +22 -0
  26. data/lib/active_model/error_collecting/message_reporter.rb +17 -0
  27. data/lib/active_model/error_collecting/reporter.rb +14 -0
  28. data/lib/active_model/error_collecting.rb +49 -0
  29. data/spec/lib/active_model/better_errors_spec.rb +7 -0
  30. data/spec/lib/active_model/error_collecting/emulation_spec.rb +45 -0
  31. data/spec/lib/active_model/error_collecting/error_collection_spec.rb +205 -0
  32. data/spec/lib/active_model/error_collecting/error_message_set_spec.rb +96 -0
  33. data/spec/lib/active_model/error_collecting/error_message_spec.rb +293 -0
  34. data/spec/lib/active_model/error_collecting/errors_spec.rb +95 -0
  35. data/spec/lib/active_model/error_collecting/human_array_reporter_spec.rb +33 -0
  36. data/spec/lib/active_model/error_collecting/human_hash_reporter_spec.rb +32 -0
  37. data/spec/lib/active_model/error_collecting/human_message_formatter_spec.rb +22 -0
  38. data/spec/lib/active_model/error_collecting/human_message_reporter_spec.rb +61 -0
  39. data/spec/lib/active_model/error_collecting/machine_array_reporter_spec.rb +40 -0
  40. data/spec/lib/active_model/error_collecting/machine_hash_reporter_spec.rb +40 -0
  41. data/spec/lib/active_model/error_collecting_spec.rb +22 -0
  42. data/spec/spec_helper.rb +30 -0
  43. data/spec/support/models.rb +7 -0
  44. data/test/integration.rb +10 -0
  45. metadata +308 -0
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::ErrorMessageSet do
4
+ subject(:set) { klass.new base, attribute, errors }
5
+ let(:klass) { ActiveModel::ErrorCollecting::ErrorMessageSet }
6
+ let(:attribute) { :first_name }
7
+ let(:errors) { [] }
8
+ let(:base) { User.new }
9
+
10
+ describe "#initialize" do
11
+ context "with no errors" do
12
+ its(:length) { should == 0 }
13
+ end
14
+
15
+ context "with one error" do
16
+ let(:errors) { [:invalid] }
17
+ its(:length) { should == 1 }
18
+ end
19
+ end
20
+
21
+ describe "#push" do
22
+ before { set.push error, options }
23
+ let(:error) { :invalid }
24
+ let(:options) { nil }
25
+ subject { set.first }
26
+
27
+ describe "without options" do
28
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
29
+ its(:message) { should == nil }
30
+ its(:type) { should == error }
31
+ end
32
+
33
+ describe "with options" do
34
+ let(:options) { { message: 'Invalid' } }
35
+
36
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
37
+ its(:message) { should == options[:message] }
38
+ its(:type) { should == error }
39
+ end
40
+ end
41
+
42
+ describe "#<<" do
43
+ before { set << error }
44
+ subject { set.first }
45
+
46
+ describe "when accepting error as a symbol" do
47
+ let(:error) { :invalid }
48
+
49
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
50
+ its(:message) { should == nil }
51
+ its(:type) { should == error }
52
+ end
53
+
54
+ describe "when accepting error as a tuple" do
55
+ let(:error) { [ :invalid, { message: "OMG!!" } ]}
56
+
57
+ it { should be_a ActiveModel::ErrorCollecting::ErrorMessage }
58
+ its(:message) { should == "OMG!!" }
59
+ its(:type) { should == :invalid }
60
+ end
61
+ end
62
+
63
+ describe "#to_a" do
64
+ let(:errors) { [:invalid, :too_long] }
65
+ subject { set.to_a }
66
+
67
+ it { should be_a Array }
68
+ its(:length) { should == 2 }
69
+ end
70
+
71
+ describe "#empty?" do
72
+ subject { set.empty? }
73
+
74
+ describe "when no error messages" do
75
+ it { should be_true }
76
+ end
77
+
78
+ describe "when contains error messages" do
79
+ let(:errors) { [:invalid, :too_long] }
80
+ it { should be_false }
81
+ end
82
+ end
83
+
84
+ describe "#==" do
85
+ subject { errors == set }
86
+ let(:errors) { [:invalid] }
87
+ let(:expected) { ["is invalid"] }
88
+ specify do
89
+ set.should == expected
90
+ end
91
+
92
+ specify do
93
+ expected.should == set
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,293 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::ErrorMessage do
4
+ let(:klass) { ActiveModel::ErrorCollecting::ErrorMessage }
5
+ let(:attribute) { :name }
6
+ let(:base) { User.new }
7
+ subject(:error_message) { klass.build(base, attribute, message, options) }
8
+
9
+ describe ".normalize" do
10
+ subject { klass.normalize message }
11
+ context "when message is a symbol" do
12
+ let(:message) { :invalid }
13
+ it { should == message }
14
+ end
15
+
16
+ context "when message is nil" do
17
+ let(:message) { nil }
18
+ it { should be nil }
19
+ end
20
+
21
+ context "when message is a string" do
22
+ let(:message) { 'bad' }
23
+ it { should == message }
24
+ end
25
+
26
+ context "when message is a proc" do
27
+ let(:message) { proc { 'bad' } }
28
+ it { should == 'bad' }
29
+ end
30
+ end
31
+
32
+ describe ".identify" do
33
+ subject { klass.identify message, override }
34
+ context "when message is a symbol and" do
35
+ let(:message) { :invalid }
36
+
37
+ context "when override is a symbol" do
38
+ let(:override) { :not_good }
39
+ it { should == [:not_good, nil] }
40
+ end
41
+
42
+ context "when override is nil" do
43
+ let(:override) { nil }
44
+ it { should == [:invalid, nil] }
45
+ end
46
+
47
+ context "when override is a string" do
48
+ let(:override) { "invalid" }
49
+ it { should == [:invalid, "invalid"] }
50
+ end
51
+
52
+ context "when override is a proc" do
53
+ let(:override) { proc { "Not good" } }
54
+ it { should == [:invalid, "Not good"] }
55
+ end
56
+ end
57
+
58
+ context "when message is a string and" do
59
+ let(:message) { "Invalid" }
60
+
61
+ context "when override is a symbol" do
62
+ let(:override) { :not_good }
63
+ it { should == [:not_good, "Invalid"] }
64
+ end
65
+
66
+ context "when override is nil" do
67
+ let(:override) { nil }
68
+ it { should == [nil, "Invalid"] }
69
+ end
70
+
71
+ context "when override is a string" do
72
+ let(:override) { "not good" }
73
+ it { should == [nil, "not good"] }
74
+ end
75
+
76
+ context "when override is a proc" do
77
+ let(:override) { proc { "Not Good" } }
78
+ it { should == [nil, "Not Good"] }
79
+ end
80
+ end
81
+
82
+ context "when message is nil and" do
83
+ let(:message) { nil }
84
+
85
+ context "when override is a symbol" do
86
+ let(:override) { :not_good }
87
+ it { should == [:not_good, nil] }
88
+ end
89
+
90
+ context "when override is nil" do
91
+ let(:override) { nil }
92
+ it { should == [nil, nil] }
93
+ end
94
+
95
+ context "when override is a string" do
96
+ let(:override) { "not good" }
97
+ it { should == [nil, "not good"] }
98
+ end
99
+
100
+ context "when override is a proc" do
101
+ let(:override) { proc { "Not Good" } }
102
+ it { should == [nil, "Not Good"] }
103
+ end
104
+ end
105
+
106
+ context "when message is a proc and" do
107
+ let(:message) { proc {"invalid"} }
108
+
109
+ context "when override is a symbol" do
110
+ let(:override) { :not_good }
111
+ it { should == [:not_good, "invalid"] }
112
+ end
113
+
114
+ context "when override is nil" do
115
+ let(:override) { nil }
116
+ it { should == [nil, "invalid"] }
117
+ end
118
+
119
+ context "when override is a string" do
120
+ let(:override) { "not good" }
121
+ it { should == [nil, "not good"] }
122
+ end
123
+
124
+ context "when override is a proc" do
125
+ let(:override) { proc { "Not Good" } }
126
+ it { should == [nil, "Not Good"] }
127
+ end
128
+ end
129
+ end
130
+
131
+
132
+ describe ".build" do
133
+ context "when message is a symbol and" do
134
+ let(:message) { :invalid }
135
+
136
+ context "when options[:message] is a string" do
137
+ let(:options) { { message: "Not Really Valid!" } }
138
+ its(:type) { should == message }
139
+ its(:message) { should == options[:message] }
140
+ end
141
+
142
+ context "when options[:message] is a symbol" do
143
+ let(:options) { { message: :not_really_valid } }
144
+ its(:type) { should == options[:message] }
145
+ its(:message) { should == nil }
146
+ end
147
+
148
+ context "when options[:message] is nil" do
149
+ let(:options) { { message: nil } }
150
+ its(:type) { should == message }
151
+ its(:message) { should == nil }
152
+ end
153
+
154
+ context "when options[:message] is proc" do
155
+ let(:options) { { message: proc { "Not Really Valid!" } } }
156
+ its(:type) { should == message }
157
+ its(:message) { should == options[:message].call }
158
+ end
159
+ end
160
+
161
+ context "when message is a string and" do
162
+ let(:message) { 'Invalid!' }
163
+
164
+ context "when options[:message] is a string" do
165
+ let(:options) { { message: "Not Really Valid!" } }
166
+ its(:type) { should == nil }
167
+ its(:message) { should == options[:message] }
168
+ end
169
+
170
+ context "when options[:message] is a symbol" do
171
+ let(:options) { { message: :not_really_valid } }
172
+ its(:type) { should == options[:message] }
173
+ its(:message) { should == message }
174
+ end
175
+
176
+ context "when options[:message] is nil" do
177
+ let(:options) { { } }
178
+ its(:type) { should == nil }
179
+ its(:message) { should == message }
180
+ end
181
+
182
+ context "when options[:message] is proc" do
183
+ let(:options) { { message: proc { "Not Really Valid!" } } }
184
+ its(:type) { should == nil }
185
+ its(:message) { should == options[:message].call }
186
+ end
187
+ end
188
+
189
+ context "when message is a proc and" do
190
+ let(:message) { proc{ 'Invalid!' } }
191
+
192
+ context "when options[:message] is a string" do
193
+ let(:options) { { message: "Not Really Valid!" } }
194
+ its(:type) { should == nil }
195
+ its(:message) { should == options[:message] }
196
+ end
197
+
198
+ context "when options[:message] is a symbol" do
199
+ let(:options) { { message: :not_really_valid } }
200
+ its(:type) { should == options[:message] }
201
+ its(:message) { should == message.call }
202
+ end
203
+
204
+ context "when options[:message] is nil" do
205
+ let(:options) { { } }
206
+ its(:type) { should == nil }
207
+ its(:message) { should == message.call }
208
+ end
209
+
210
+ context "when options[:message] is proc" do
211
+ let(:options) { { message: proc { "Not Really Valid!" } } }
212
+ its(:type) { should == nil }
213
+ its(:message) { should == options[:message].call }
214
+ end
215
+ end
216
+
217
+
218
+ context "when message is nil and" do
219
+ let(:message) { nil }
220
+
221
+ context "when options[:message] is a string" do
222
+ let(:options) { { message: "Not Really Valid!" } }
223
+ its(:type) { should == nil }
224
+ its(:message) { should == options[:message] }
225
+ end
226
+
227
+ context "when options[:message] is a symbol" do
228
+ let(:options) { { message: :not_really_valid } }
229
+ its(:type) { should == options[:message] }
230
+ its(:message) { should == nil }
231
+ end
232
+
233
+ context "when options[:message] is nil" do
234
+ let(:options) { { } }
235
+ its(:type) { should == nil }
236
+ its(:message) { should == nil }
237
+ end
238
+
239
+ context "when options[:message] is proc" do
240
+ let(:options) { { message: proc { "Not Really Valid!" } } }
241
+ its(:type) { should == nil }
242
+ its(:message) { should == options[:message].call }
243
+ end
244
+ end
245
+
246
+ [
247
+ :if, :unless, :on, :allow_nil, :allow_blank, :strict, :message
248
+ ].each do |field|
249
+ context "when options includes :#{field}" do
250
+ let(:message) { :invalid }
251
+ let(:options) { {} }
252
+ before { options[field] = proc{} }
253
+ its(:options) { should == {} }
254
+ end
255
+ end
256
+ end
257
+
258
+ describe '#initialize' do
259
+ let(:message) { :invalid }
260
+ let(:options) { { message: "Invalid!", count: 12 } }
261
+
262
+ its(:options) { should == { count: 12 } }
263
+ its(:attribute) { should == attribute }
264
+ end
265
+
266
+ describe '#<=>' do
267
+ subject { e1 <=> e2 }
268
+
269
+ context "when attribute is different" do
270
+ let(:e1) { klass.build base, :name, :invalid }
271
+ let(:e2) { klass.build base, :name1, :invalid }
272
+ it {should == nil }
273
+ end
274
+
275
+ context "when type is different" do
276
+ let(:e1) { klass.build base, :name, :invalid }
277
+ let(:e2) { klass.build base, :name, :invalid1 }
278
+ it {should == nil }
279
+ end
280
+
281
+ context "when message is different" do
282
+ let(:e1) { klass.build base, :name, :invalid, :message => "a" }
283
+ let(:e2) { klass.build base, :name, :invalid, :message => "b" }
284
+ it {should == nil }
285
+ end
286
+
287
+ context "when it is the same" do
288
+ let(:e1) { klass.build base, :name, :invalid }
289
+ let(:e2) { klass.build base, :name, :invalid }
290
+ it { should == 0 }
291
+ end
292
+ end
293
+ end
@@ -0,0 +1,95 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::Errors do
4
+ subject(:instance) { klass.new base }
5
+ let(:klass) { ActiveModel::ErrorCollecting::Errors }
6
+ let(:base) { User.new }
7
+ let(:reporter_name) { :mock }
8
+ let(:mock_reporter) {
9
+ Class.new do
10
+ def initialize(collection)
11
+ end
12
+ end
13
+ }
14
+
15
+ describe "#initialize" do
16
+ its(:base) { should be base }
17
+ end
18
+
19
+ describe "#error_collection" do
20
+ subject { instance.error_collection }
21
+ it { should be_a ActiveModel::ErrorCollecting::ErrorCollection }
22
+ its(:base) { should be base }
23
+ end
24
+
25
+ describe "#message_reporter" do
26
+ subject { instance.message_reporter }
27
+ let(:mock_reporter) { mock() }
28
+ before {
29
+ instance.
30
+ should_receive(:get_reporter).
31
+ with(:message).
32
+ and_return(mock_reporter)
33
+ }
34
+
35
+ it { should be mock_reporter }
36
+ end
37
+
38
+ describe "#hash_reporter" do
39
+ subject { instance.hash_reporter }
40
+ let(:mock_reporter) { mock() }
41
+ before {
42
+ instance.
43
+ should_receive(:get_reporter).
44
+ with(:hash).
45
+ and_return(mock_reporter)
46
+ }
47
+
48
+ it { should be mock_reporter }
49
+ end
50
+
51
+ describe "#array_reporter" do
52
+ subject { instance.array_reporter }
53
+ let(:mock_reporter) { mock() }
54
+ before {
55
+ instance.
56
+ should_receive(:get_reporter).
57
+ with(:array).
58
+ and_return(mock_reporter)
59
+ }
60
+
61
+ it { should be mock_reporter }
62
+ end
63
+
64
+ describe "#set_reporter" do
65
+ it "should set the reporter class" do
66
+ instance.set_reporter reporter_name, mock_reporter
67
+ reporter_classes = instance.instance_variable_get(:@reporter_classes)
68
+ reporter_classes[reporter_name.to_s].should == mock_reporter
69
+ end
70
+
71
+ it "should delete old reporter instance" do
72
+ reporters = instance.instance_variable_get(:@reporters)
73
+ reporters[reporter_name] = mock()
74
+ instance.set_reporter reporter_name, mock_reporter
75
+ reporters.has_key?(reporter_name.to_s).should be false
76
+ end
77
+ end
78
+
79
+ describe "#get_reporter_class" do
80
+ subject { instance.get_reporter_class(reporter_name) }
81
+ before { instance.set_reporter reporter_name, mock_reporter }
82
+ it { should == mock_reporter }
83
+ end
84
+
85
+ describe "#get_reporter" do
86
+ subject { instance.get_reporter(reporter_name) }
87
+ before { instance.set_reporter reporter_name, mock_reporter }
88
+ it { should be_a mock_reporter }
89
+ end
90
+
91
+ describe "#reporter_classes" do
92
+ subject { instance.reporter_classes }
93
+ it { should == ::ActiveModel::ErrorCollecting.reporters }
94
+ end
95
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanArrayReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanArrayReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+ describe "#initialize" do
10
+ its(:collection) { should be collection }
11
+ end
12
+
13
+ describe "#base" do
14
+ its(:base) { should be base }
15
+ end
16
+
17
+ describe "#to_a" do
18
+ subject { reporter.to_a }
19
+ let(:expected) { ['foo', 'bar'] }
20
+ before do
21
+ message_reporter = mock()
22
+ ActiveModel::ErrorCollecting::HumanMessageReporter.
23
+ should_receive(:new).
24
+ and_return(message_reporter)
25
+
26
+ message_reporter.
27
+ should_receive(:full_messages).
28
+ and_return(expected)
29
+ end
30
+
31
+ it { should == expected }
32
+ end
33
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanHashReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanHashReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+ describe "#initialize" do
10
+ its(:collection) { should be collection }
11
+ end
12
+
13
+ describe "#base" do
14
+ its(:base) { should be base }
15
+ end
16
+
17
+ describe "#to_hash" do
18
+ subject { reporter.to_hash }
19
+ let(:expected) {{
20
+ first_name: ["is invalid", "can't be empty"],
21
+ last_name: ["is invalid"]
22
+ }}
23
+
24
+ before do
25
+ collection[:first_name] << :invalid
26
+ collection[:first_name] << :empty
27
+ collection[:last_name] << :invalid
28
+ end
29
+
30
+ it { should == expected }
31
+ end
32
+ end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanMessageFormatter do
4
+ subject(:formatter) { klass.new base, error_message }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanMessageFormatter }
6
+ let(:base) { User.new }
7
+ let(:error_message) { ActiveModel::ErrorCollecting::ErrorMessage.build base, :first_name, :invalid }
8
+
9
+ describe "#initialize" do
10
+ its(:base) { should be base }
11
+ its(:error_message) { should be error_message }
12
+ its(:attribute) { should be error_message.attribute }
13
+ its(:type) { should be error_message.type }
14
+ its(:message) { should be error_message.message }
15
+ its(:options) { should be error_message.options }
16
+ end
17
+
18
+ describe "#format_message" do
19
+ subject { formatter.format_message }
20
+ it { should == "is invalid" }
21
+ end
22
+ end
@@ -0,0 +1,61 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::HumanMessageReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::HumanMessageReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+
10
+ describe "#initialize" do
11
+ its(:collection) { should be collection }
12
+ end
13
+
14
+ describe "#base" do
15
+ its(:base) { should be base }
16
+ end
17
+
18
+ describe "#full_message" do
19
+ subject { reporter.full_message attribute, message }
20
+ let(:attribute) { :first_name }
21
+ let(:message) { "is invalid" }
22
+
23
+ it { should == "First name is invalid" }
24
+ end
25
+
26
+ describe "#full_messages" do
27
+ subject { reporter.full_messages }
28
+ let(:expected) {[
29
+ "First name is invalid",
30
+ "First name can't be empty",
31
+ "Last name is invalid"
32
+ ]}
33
+
34
+ before do
35
+ collection[:first_name] << :invalid
36
+ collection[:first_name] << :empty
37
+ collection[:last_name] << :invalid
38
+ end
39
+
40
+ it { should == expected }
41
+ end
42
+
43
+ describe "#generate_message" do
44
+ subject { reporter.generate_message attribute, type, options }
45
+ let(:attribute) { :first_name }
46
+
47
+ context "when passing symbols as message" do
48
+ let(:type) { :too_short }
49
+ let(:options) { {count: 3} }
50
+ let(:expected) { "is too short (minimum is 3 characters)" }
51
+ it { should == expected }
52
+ end
53
+
54
+ context "when passing strings as message" do
55
+ let(:type) { "foo" }
56
+ let(:options) { nil }
57
+ let(:expected) { type }
58
+ it { should == expected }
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActiveModel::ErrorCollecting::MachineArrayReporter do
4
+ subject(:reporter) { klass.new collection }
5
+ let(:klass) { ActiveModel::ErrorCollecting::MachineArrayReporter }
6
+ let(:collection) { ActiveModel::ErrorCollecting::ErrorCollection.new base}
7
+ let(:base) { User.new }
8
+
9
+ describe "#initialize" do
10
+ its(:collection) { should be collection }
11
+ end
12
+
13
+ describe "#base" do
14
+ its(:base) { should be base }
15
+ end
16
+
17
+ describe "#to_a" do
18
+ subject { reporter.to_a }
19
+
20
+ before do
21
+ collection[:first_name] << :invalid
22
+ collection[:first_name] << [ :too_short, { count: 3 } ]
23
+ collection[:last_name] << :invalid
24
+ end
25
+
26
+ let(:expected) {[{
27
+ attribute: 'first_name',
28
+ type: :invalid
29
+ }, {
30
+ attribute: 'first_name',
31
+ type: :too_short,
32
+ options: { count: 3 }
33
+ },{
34
+ attribute: 'last_name',
35
+ type: :invalid
36
+ }]}
37
+
38
+ it { should == expected }
39
+ end
40
+ end