instructure-active_model-better_errors 1.6.3.rails2
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.
- data/.document +5 -0
- data/.gitmodules +3 -0
- data/.rspec +2 -0
- data/.travis.yml +3 -0
- data/Gemfile +18 -0
- data/LICENSE.txt +20 -0
- data/README.md +183 -0
- data/Rakefile +57 -0
- data/VERSION +1 -0
- data/active_model-better_errors.gemspec +110 -0
- data/lib/active_model/better_errors.rb +17 -0
- data/lib/active_model/error_collecting/array_reporter.rb +9 -0
- data/lib/active_model/error_collecting/core_ext.rb +6 -0
- data/lib/active_model/error_collecting/emulation.rb +65 -0
- data/lib/active_model/error_collecting/error_collection.rb +86 -0
- data/lib/active_model/error_collecting/error_message.rb +88 -0
- data/lib/active_model/error_collecting/error_message_set.rb +33 -0
- data/lib/active_model/error_collecting/errors.rb +52 -0
- data/lib/active_model/error_collecting/hash_reporter.rb +9 -0
- data/lib/active_model/error_collecting/human_array_reporter.rb +9 -0
- data/lib/active_model/error_collecting/human_hash_reporter.rb +15 -0
- data/lib/active_model/error_collecting/human_message_formatter.rb +72 -0
- data/lib/active_model/error_collecting/human_message_reporter.rb +32 -0
- data/lib/active_model/error_collecting/machine_array_reporter.rb +19 -0
- data/lib/active_model/error_collecting/machine_hash_reporter.rb +22 -0
- data/lib/active_model/error_collecting/message_reporter.rb +17 -0
- data/lib/active_model/error_collecting/reporter.rb +14 -0
- data/lib/active_model/error_collecting.rb +49 -0
- data/spec/lib/active_model/better_errors_spec.rb +7 -0
- data/spec/lib/active_model/error_collecting/emulation_spec.rb +45 -0
- data/spec/lib/active_model/error_collecting/error_collection_spec.rb +205 -0
- data/spec/lib/active_model/error_collecting/error_message_set_spec.rb +96 -0
- data/spec/lib/active_model/error_collecting/error_message_spec.rb +293 -0
- data/spec/lib/active_model/error_collecting/errors_spec.rb +95 -0
- data/spec/lib/active_model/error_collecting/human_array_reporter_spec.rb +33 -0
- data/spec/lib/active_model/error_collecting/human_hash_reporter_spec.rb +32 -0
- data/spec/lib/active_model/error_collecting/human_message_formatter_spec.rb +22 -0
- data/spec/lib/active_model/error_collecting/human_message_reporter_spec.rb +61 -0
- data/spec/lib/active_model/error_collecting/machine_array_reporter_spec.rb +40 -0
- data/spec/lib/active_model/error_collecting/machine_hash_reporter_spec.rb +40 -0
- data/spec/lib/active_model/error_collecting_spec.rb +22 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/support/models.rb +7 -0
- data/test/integration.rb +10 -0
- metadata +308 -0
@@ -0,0 +1,33 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class ErrorMessageSet < Array
|
4
|
+
def initialize(base, attribute, errors=[])
|
5
|
+
@base = base
|
6
|
+
@attribute = attribute
|
7
|
+
errors.each do |error|
|
8
|
+
push(*error)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def <<(error)
|
13
|
+
super ErrorMessage.build(@base, @attribute, *error)
|
14
|
+
end
|
15
|
+
|
16
|
+
def push(message, options = {})
|
17
|
+
super ErrorMessage.build(@base, @attribute, message, options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def []=(index, error)
|
21
|
+
super index, ErrorMessage.build(@base, @attribute, *error)
|
22
|
+
end
|
23
|
+
|
24
|
+
def insert(index, error)
|
25
|
+
super index, ErrorMessage.build(@base, @attribute, *error)
|
26
|
+
end
|
27
|
+
|
28
|
+
def to_a
|
29
|
+
dup
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class Errors
|
4
|
+
include Emulation
|
5
|
+
|
6
|
+
attr_reader :base
|
7
|
+
def initialize(base)
|
8
|
+
@base = base
|
9
|
+
@reporters = {}
|
10
|
+
@reporter_classes = reporter_classes
|
11
|
+
end
|
12
|
+
|
13
|
+
def error_collection
|
14
|
+
@error_collection ||= ErrorCollection.new(@base)
|
15
|
+
end
|
16
|
+
|
17
|
+
def message_reporter
|
18
|
+
get_reporter(:message)
|
19
|
+
end
|
20
|
+
|
21
|
+
def hash_reporter
|
22
|
+
get_reporter(:hash)
|
23
|
+
end
|
24
|
+
|
25
|
+
def array_reporter
|
26
|
+
get_reporter(:array)
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_reporter(type, reporter)
|
30
|
+
type = type.to_s
|
31
|
+
klass = ::ActiveModel::ErrorCollecting.get_reporter_class(type, reporter)
|
32
|
+
@reporter_classes[type] = klass
|
33
|
+
@reporters.delete type
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_reporter(type)
|
37
|
+
type = type.to_s
|
38
|
+
klass = get_reporter_class(type)
|
39
|
+
@reporters[type] = klass.new(error_collection)
|
40
|
+
end
|
41
|
+
|
42
|
+
def reporter_classes
|
43
|
+
::ActiveModel::ErrorCollecting.reporters
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_reporter_class(type)
|
47
|
+
type = type.to_s
|
48
|
+
@reporter_classes[type]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class HumanHashReporter < HashReporter
|
4
|
+
def to_hash
|
5
|
+
collection.to_hash.inject({}) do |hash, kv|
|
6
|
+
attribute, error_message_set = kv
|
7
|
+
hash[attribute] = error_message_set.map do |error_message|
|
8
|
+
HumanMessageFormatter.new(base, error_message).format_message
|
9
|
+
end
|
10
|
+
hash
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class HumanMessageFormatter
|
4
|
+
extend Forwardable
|
5
|
+
|
6
|
+
def_delegators :@error_message, :attribute, :message, :options
|
7
|
+
|
8
|
+
attr_reader :base, :error_message
|
9
|
+
|
10
|
+
def initialize(base, error_message)
|
11
|
+
@base, @error_message = base, error_message
|
12
|
+
end
|
13
|
+
|
14
|
+
def type
|
15
|
+
@error_message.type || :invalid
|
16
|
+
end
|
17
|
+
|
18
|
+
def format_message
|
19
|
+
return message if message && error_message.type.nil?
|
20
|
+
|
21
|
+
keys = i18n_keys
|
22
|
+
key = keys.shift
|
23
|
+
|
24
|
+
options = {
|
25
|
+
:default => keys,
|
26
|
+
:model => base.class.human_name,
|
27
|
+
:attribute => base.class.human_attribute_name(attribute),
|
28
|
+
:value => value
|
29
|
+
}.merge(self.options)
|
30
|
+
|
31
|
+
I18n.translate key, options
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def value
|
37
|
+
return if attribute == :base
|
38
|
+
base.send :read_attribute, attribute
|
39
|
+
end
|
40
|
+
|
41
|
+
def ancestor_keys
|
42
|
+
return [] unless base.class.respond_to?(:i18n_scope)
|
43
|
+
scope = base.class.i18n_scope
|
44
|
+
base.class.lookup_ancestors.map do |klass|
|
45
|
+
model_key = klass.model_name.i18n_key
|
46
|
+
[
|
47
|
+
:"#{scope}.errors.models.#{model_key}.attributes.#{attribute}.#{type}",
|
48
|
+
:"#{scope}.errors.models.#{model_key}.#{type}"
|
49
|
+
]
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def i18n_keys
|
54
|
+
keys = ancestor_keys
|
55
|
+
keys << message
|
56
|
+
|
57
|
+
if base.class.respond_to?(:i18n_scope)
|
58
|
+
keys << :"#{base.class.i18n_scope}.errors.messages.#{type}"
|
59
|
+
end
|
60
|
+
|
61
|
+
keys << :"errors.attributes.#{attribute}.#{type}"
|
62
|
+
keys << :"activerecord.errors.attributes.#{attribute}.#{type}"
|
63
|
+
keys << :"errors.messages.#{type}"
|
64
|
+
keys << :"activerecord.errors.messages.#{type}"
|
65
|
+
|
66
|
+
keys.compact!
|
67
|
+
keys.flatten!
|
68
|
+
keys
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class HumanMessageReporter < MessageReporter
|
4
|
+
def full_messages
|
5
|
+
@collection.map do |attribute, error_message|
|
6
|
+
formatter = HumanMessageFormatter.new(base, error_message)
|
7
|
+
message = formatter.format_message
|
8
|
+
full_message attribute, message
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def full_message(attribute, message)
|
13
|
+
return message if attribute == :base
|
14
|
+
attr_name = attribute.to_s.gsub('.', '_').humanize
|
15
|
+
attr_name = base.class.human_attribute_name(attribute, :default => attr_name)
|
16
|
+
I18n.t(:"errors.format", {
|
17
|
+
:default => "%{attribute} %{message}",
|
18
|
+
:attribute => attr_name,
|
19
|
+
:message => message
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
# This method is not used internally.
|
24
|
+
# This is for API Compatibility with ActiveModel::Errors only
|
25
|
+
def generate_message(attribute, type = :invalid, options = {})
|
26
|
+
error_message = ErrorMessage.build(base, attribute, type, options)
|
27
|
+
formatter = HumanMessageFormatter.new(base, error_message)
|
28
|
+
formatter.format_message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class MachineArrayReporter < ArrayReporter
|
4
|
+
def to_a
|
5
|
+
collection.to_a.map do |error_message|
|
6
|
+
format_error_message error_message
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def format_error_message(error_message)
|
11
|
+
result = {}
|
12
|
+
result[:attribute] = error_message.attribute.to_s
|
13
|
+
result[:type] = error_message.type || :invalid
|
14
|
+
result[:options] = error_message.options unless error_message.options.blank?
|
15
|
+
result
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class MachineHashReporter < HashReporter
|
4
|
+
def to_hash
|
5
|
+
collection.to_hash.inject({}) do |hash, kv|
|
6
|
+
attribute, error_message_set = kv
|
7
|
+
hash[attribute] = error_message_set.map do |error_message|
|
8
|
+
format_error_message(error_message)
|
9
|
+
end
|
10
|
+
hash
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_error_message(error_message)
|
15
|
+
result = {}
|
16
|
+
result[:type] = error_message.type || :invalid
|
17
|
+
result[:options] = error_message.options unless error_message.options.blank?
|
18
|
+
result
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module ActiveModel
|
2
|
+
module ErrorCollecting
|
3
|
+
class MessageReporter < Reporter
|
4
|
+
def full_messages
|
5
|
+
raise "abstract method"
|
6
|
+
end
|
7
|
+
|
8
|
+
def full_message(attribute, message)
|
9
|
+
raise "abstract method"
|
10
|
+
end
|
11
|
+
|
12
|
+
def generate_message(attribute, type = :invalid, options = {})
|
13
|
+
raise "abstract method"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'active_model/error_collecting/error_message'
|
2
|
+
require 'active_model/error_collecting/error_message_set'
|
3
|
+
require 'active_model/error_collecting/error_collection'
|
4
|
+
|
5
|
+
require 'active_model/error_collecting/reporter'
|
6
|
+
require 'active_model/error_collecting/message_reporter'
|
7
|
+
require 'active_model/error_collecting/hash_reporter'
|
8
|
+
require 'active_model/error_collecting/array_reporter'
|
9
|
+
|
10
|
+
require 'active_model/error_collecting/human_message_formatter'
|
11
|
+
require 'active_model/error_collecting/human_message_reporter'
|
12
|
+
require 'active_model/error_collecting/human_hash_reporter'
|
13
|
+
require 'active_model/error_collecting/human_array_reporter'
|
14
|
+
|
15
|
+
require 'active_model/error_collecting/machine_hash_reporter'
|
16
|
+
require 'active_model/error_collecting/machine_array_reporter'
|
17
|
+
|
18
|
+
require 'active_model/error_collecting/emulation'
|
19
|
+
require 'active_model/error_collecting/errors'
|
20
|
+
|
21
|
+
require 'active_model/error_collecting/core_ext'
|
22
|
+
|
23
|
+
module ActiveModel
|
24
|
+
module ErrorCollecting
|
25
|
+
class << self
|
26
|
+
def set_reporter(name, reporter)
|
27
|
+
name = name.to_s
|
28
|
+
@reporter_maps ||= {}
|
29
|
+
return @reporter_maps.delete(name) unless reporter
|
30
|
+
@reporter_maps[name] = get_reporter_class(name, reporter)
|
31
|
+
end
|
32
|
+
|
33
|
+
def reporters
|
34
|
+
@reporter_maps ||= {}
|
35
|
+
@reporter_maps.clone
|
36
|
+
end
|
37
|
+
|
38
|
+
def get_reporter_class(name, reporter)
|
39
|
+
return reporter if reporter.is_a? Class
|
40
|
+
class_name = "active_model/error_collecting/#{reporter}_#{name}_reporter"
|
41
|
+
class_name.classify.constantize
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
set_reporter :message, :human
|
46
|
+
set_reporter :array, :human
|
47
|
+
set_reporter :hash, :human
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
shared_examples_for "a delegated method" do
|
4
|
+
let(:target_instance) { mock() }
|
5
|
+
before do
|
6
|
+
target_instance.should_receive method
|
7
|
+
instance.stub(target).and_return(target_instance)
|
8
|
+
end
|
9
|
+
|
10
|
+
specify { instance.send method }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe ActiveModel::ErrorCollecting::Emulation do
|
14
|
+
subject(:instance) { klass.new }
|
15
|
+
let(:klass) { Class.new { include ActiveModel::ErrorCollecting::Emulation } }
|
16
|
+
|
17
|
+
delegation_map = {
|
18
|
+
error_collection: [
|
19
|
+
:clear, :include?, :get, :set, :delete, :[], :[]=, :each, :size,
|
20
|
+
:values, :keys, :count, :empty?, :added?, :any?, :entries
|
21
|
+
],
|
22
|
+
|
23
|
+
message_reporter: [
|
24
|
+
:full_messages, :full_message, :generate_message
|
25
|
+
],
|
26
|
+
|
27
|
+
hash_reporter: [
|
28
|
+
:to_hash
|
29
|
+
],
|
30
|
+
|
31
|
+
hash_reporter: [
|
32
|
+
:to_hash
|
33
|
+
]
|
34
|
+
}
|
35
|
+
|
36
|
+
delegation_map.each do |target, methods|
|
37
|
+
methods.each do |method|
|
38
|
+
describe "delegating ##{method} to ##{target}" do
|
39
|
+
let(:target) { target }
|
40
|
+
let(:method) { method }
|
41
|
+
it_should_behave_like "a delegated method"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,205 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveModel::ErrorCollecting::ErrorCollection do
|
4
|
+
subject(:collection) { klass.new(base) }
|
5
|
+
let(:klass) { ActiveModel::ErrorCollecting::ErrorCollection }
|
6
|
+
let(:base) { User.new }
|
7
|
+
let(:errors){{
|
8
|
+
:first_name => [ [ :too_long, { count: 3 } ] ],
|
9
|
+
'last_name' => [ [ :invalid, { message: "Invalid" } ] ],
|
10
|
+
:email => [ :invalid ],
|
11
|
+
}}
|
12
|
+
|
13
|
+
before do
|
14
|
+
errors.each do |attribute, error_list|
|
15
|
+
error_list.each do |error|
|
16
|
+
collection[attribute] = error
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#clear" do
|
22
|
+
before { collection.clear }
|
23
|
+
it { should be_empty }
|
24
|
+
end
|
25
|
+
|
26
|
+
describe "#include?" do
|
27
|
+
it { should be_include :first_name }
|
28
|
+
it { should be_include :last_name }
|
29
|
+
it { should be_include :email }
|
30
|
+
it { should_not be_include 'first_name' }
|
31
|
+
it { should_not be_include 'last_name' }
|
32
|
+
it { should_not be_include 'email' }
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#get" do
|
36
|
+
subject { collection.get(:first_name) }
|
37
|
+
it { should be_a ActiveModel::ErrorCollecting::ErrorMessageSet }
|
38
|
+
its(:length) { should be 1 }
|
39
|
+
|
40
|
+
describe "when value is nil" do
|
41
|
+
before { collection.delete :first_name }
|
42
|
+
it { should be nil }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#set" do
|
47
|
+
subject { collection.get :first_name }
|
48
|
+
|
49
|
+
describe "when value is array" do
|
50
|
+
before { collection.set(:first_name, []) }
|
51
|
+
it { should be_a ActiveModel::ErrorCollecting::ErrorMessageSet }
|
52
|
+
its(:length) { should be 0 }
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "when value is nil" do
|
56
|
+
before { collection.set(:first_name, nil) }
|
57
|
+
it { should be_nil }
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#delete" do
|
62
|
+
subject { collection.get(:first_name) }
|
63
|
+
before { collection.delete(:first_name) }
|
64
|
+
it { should be_nil }
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#[]" do
|
68
|
+
subject { collection[:first_name] }
|
69
|
+
|
70
|
+
describe "when no error messages" do
|
71
|
+
before { collection.clear }
|
72
|
+
it { should be_blank }
|
73
|
+
it { should_not be_nil }
|
74
|
+
it { should be_a ActiveModel::ErrorCollecting::ErrorMessageSet }
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "when there are error messages" do
|
78
|
+
it { should_not be_blank }
|
79
|
+
it { should_not be_nil }
|
80
|
+
it { should be_a ActiveModel::ErrorCollecting::ErrorMessageSet }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "#[]=" do
|
85
|
+
subject(:error_message_set) { collection.get field }
|
86
|
+
|
87
|
+
describe "when assigning existing attribute" do
|
88
|
+
let(:field) { :first_name }
|
89
|
+
it "should append to existing set" do
|
90
|
+
expect {
|
91
|
+
collection[field] = "I'm invalid."
|
92
|
+
}.to change { error_message_set.length }.by(1)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "when assigning to new attribute" do
|
97
|
+
let(:field) { :a_new_attribute }
|
98
|
+
before { collection[field] = "I'm invalid" }
|
99
|
+
it { should_not be_nil }
|
100
|
+
it { should be_a ActiveModel::ErrorCollecting::ErrorMessageSet }
|
101
|
+
its(:length) { should be 1 }
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#each" do
|
106
|
+
it "should loop through each error" do
|
107
|
+
count = 0
|
108
|
+
collection.each do |attribute, error|
|
109
|
+
attribute.should be_a Symbol
|
110
|
+
error.should be_a ActiveModel::ErrorCollecting::ErrorMessage
|
111
|
+
count += 1
|
112
|
+
end
|
113
|
+
|
114
|
+
expect(count).to be collection.size
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "#size" do
|
119
|
+
subject { collection.size }
|
120
|
+
it { should be 3 }
|
121
|
+
|
122
|
+
describe "when adding one more error" do
|
123
|
+
before { collection[:name] = "Not Valid" }
|
124
|
+
it { should be 4 }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe "#values" do
|
129
|
+
subject { collection.values }
|
130
|
+
|
131
|
+
it { should be_a Array }
|
132
|
+
its(:length) { should be 3 }
|
133
|
+
|
134
|
+
it "should contain ErrorMessageSet as elements" do
|
135
|
+
collection.values.each do |el|
|
136
|
+
el.should be_a ActiveModel::ErrorCollecting::ErrorMessageSet
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe "#keys" do
|
142
|
+
subject { collection.keys }
|
143
|
+
it { should == [:first_name, :last_name, :email] }
|
144
|
+
end
|
145
|
+
|
146
|
+
describe "#to_a" do
|
147
|
+
subject { collection.to_a }
|
148
|
+
its(:size) { should == 3 }
|
149
|
+
|
150
|
+
describe "when adding one more error" do
|
151
|
+
before { collection[:name] = "Not Valid" }
|
152
|
+
its(:size) { should == 4 }
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should contain ErrorMessage as elements" do
|
156
|
+
collection.to_a.each do |error|
|
157
|
+
error.should be_a ActiveModel::ErrorCollecting::ErrorMessage
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
describe "#to_hash" do
|
163
|
+
subject { collection.to_hash }
|
164
|
+
|
165
|
+
it { should be_a Hash }
|
166
|
+
it { should == collection.instance_variable_get(:@collection) }
|
167
|
+
it { should_not be collection.instance_variable_get(:@collection) }
|
168
|
+
end
|
169
|
+
|
170
|
+
describe "#empty?" do
|
171
|
+
subject { collection.empty? }
|
172
|
+
it{ should be false }
|
173
|
+
|
174
|
+
describe "after clearing the collection" do
|
175
|
+
before { collection.clear }
|
176
|
+
|
177
|
+
it { should be true }
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
describe "#add" do
|
182
|
+
it "should add error to collection" do
|
183
|
+
expect {
|
184
|
+
collection.add :name, "Invalid"
|
185
|
+
}.to change { collection[:name].length }.by(1)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
describe "#added?" do
|
190
|
+
describe "when an error message is not added" do
|
191
|
+
subject { collection.added? :name, :not_there }
|
192
|
+
it { should be false }
|
193
|
+
end
|
194
|
+
|
195
|
+
describe "when an error message with the same option is added" do
|
196
|
+
subject { collection.added? :first_name, :too_long, { :count => 3 } }
|
197
|
+
it { should be true }
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "when an error message with the different option is added" do
|
201
|
+
subject { collection.added? :first_name, :too_long, { :count => 4 } }
|
202
|
+
it { should be false }
|
203
|
+
end
|
204
|
+
end
|
205
|
+
end
|