dirt-core 2.2.3
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/Gemfile +8 -0
- data/Gemfile.lock +46 -0
- data/MIT-LICENSE +23 -0
- data/README +14 -0
- data/doc/BlockValidator.html +272 -0
- data/doc/ClosureValidator.html +276 -0
- data/doc/Dirt.html +158 -0
- data/doc/Dirt/FooBar.html +167 -0
- data/doc/Dirt/HerpZerp.html +161 -0
- data/doc/Dirt/HerpZerp/DerpGerp.html +161 -0
- data/doc/Dirt/HerpZerp/DerpGerp/FooBar.html +167 -0
- data/doc/Dirt/MemoryPersister.html +453 -0
- data/doc/Dirt/MemoryRecord.html +157 -0
- data/doc/Dirt/MissingRecordError.html +157 -0
- data/doc/Dirt/Model.html +320 -0
- data/doc/Dirt/NoPersisterError.html +157 -0
- data/doc/Dirt/Relation.html +338 -0
- data/doc/Dirt/Role.html +345 -0
- data/doc/Dirt/TooManyRecordsError.html +157 -0
- data/doc/Dirt/TransactionError.html +157 -0
- data/doc/ExistenceValidator.html +316 -0
- data/doc/FooBar.html +153 -0
- data/doc/Gemfile.html +131 -0
- data/doc/HerpZerp.html +147 -0
- data/doc/HerpZerp/DerpGerp.html +147 -0
- data/doc/HerpZerp/DerpGerp/FooBar.html +153 -0
- data/doc/Persister.html +311 -0
- data/doc/Persisting.html +413 -0
- data/doc/PresenceValidator.html +281 -0
- data/doc/README.html +132 -0
- data/doc/Role.html +309 -0
- data/doc/Scheduler.html +147 -0
- data/doc/SelfExistenceValidator.html +278 -0
- data/doc/TestPersister.html +411 -0
- data/doc/Validating.html +293 -0
- data/doc/created.rid +18 -0
- data/doc/images/add.png +0 -0
- data/doc/images/brick.png +0 -0
- data/doc/images/brick_link.png +0 -0
- data/doc/images/bug.png +0 -0
- data/doc/images/bullet_black.png +0 -0
- data/doc/images/bullet_toggle_minus.png +0 -0
- data/doc/images/bullet_toggle_plus.png +0 -0
- data/doc/images/date.png +0 -0
- data/doc/images/delete.png +0 -0
- data/doc/images/find.png +0 -0
- data/doc/images/loadingAnimation.gif +0 -0
- data/doc/images/macFFBgHack.png +0 -0
- data/doc/images/package.png +0 -0
- data/doc/images/page_green.png +0 -0
- data/doc/images/page_white_text.png +0 -0
- data/doc/images/page_white_width.png +0 -0
- data/doc/images/plugin.png +0 -0
- data/doc/images/ruby.png +0 -0
- data/doc/images/tag_blue.png +0 -0
- data/doc/images/tag_green.png +0 -0
- data/doc/images/transparent.png +0 -0
- data/doc/images/wrench.png +0 -0
- data/doc/images/wrench_orange.png +0 -0
- data/doc/images/zoom.png +0 -0
- data/doc/index.html +110 -0
- data/doc/js/darkfish.js +155 -0
- data/doc/js/jquery.js +18 -0
- data/doc/js/navigation.js +142 -0
- data/doc/js/search.js +94 -0
- data/doc/js/search_index.js +1 -0
- data/doc/js/searcher.js +228 -0
- data/doc/rdoc.css +543 -0
- data/doc/table_of_contents.html +203 -0
- data/lib/dirt/bdd/matchers.rb +10 -0
- data/lib/dirt/bdd/persister_spec_helper.rb +213 -0
- data/lib/dirt/bdd/shared_examples.rb +29 -0
- data/lib/dirt/contexts/context.rb +15 -0
- data/lib/dirt/core.rb +36 -0
- data/lib/dirt/errors/missing_record_error.rb +4 -0
- data/lib/dirt/errors/no_persister_error.rb +4 -0
- data/lib/dirt/errors/too_many_records_error.rb +4 -0
- data/lib/dirt/errors/transaction_error.rb +4 -0
- data/lib/dirt/models/model_behaviour.rb +47 -0
- data/lib/dirt/persisters/memory_persister.rb +86 -0
- data/lib/dirt/persisters/persister.rb +54 -0
- data/lib/dirt/persisters/relation.rb +38 -0
- data/lib/dirt/roles/persisting.rb +73 -0
- data/lib/dirt/roles/role.rb +32 -0
- data/lib/dirt/roles/validating.rb +27 -0
- data/lib/dirt/roles/validation/closure_validator.rb +15 -0
- data/lib/dirt/roles/validation/existence_validator.rb +53 -0
- data/lib/dirt/roles/validation/presence_validator.rb +21 -0
- data/lib/dirt/roles/validation/self_existence_validator.rb +18 -0
- data/spec/isolations/closure_validator_spec.rb +57 -0
- data/spec/isolations/context_spec.rb +54 -0
- data/spec/isolations/existence_validator_spec.rb +151 -0
- data/spec/isolations/memory_persister_spec.rb +175 -0
- data/spec/isolations/model_spec.rb +91 -0
- data/spec/isolations/persister_spec.rb +113 -0
- data/spec/isolations/persisting_spec.rb +266 -0
- data/spec/isolations/presence_validator_spec.rb +63 -0
- data/spec/isolations/role_spec.rb +116 -0
- data/spec/isolations/self_existence_validator_spec.rb +64 -0
- data/spec/isolations/spec_helper.rb +26 -0
- data/spec/isolations/validating_spec.rb +88 -0
- metadata +161 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'active_support/all'
|
2
|
+
|
3
|
+
# Tests for whether the property referenced by an id is saved in the appropriate persister.
|
4
|
+
# This validator is stateful. #error_message returns the errors from the most recent run of #valid?.
|
5
|
+
#
|
6
|
+
# For more about validation, see Validating
|
7
|
+
class ExistenceValidator
|
8
|
+
# Takes the symbol name of the property to validate, and an options hash.
|
9
|
+
#
|
10
|
+
# Options include:
|
11
|
+
# * +as+:: The class of the type to search under
|
12
|
+
# * +list+:: If set, will treat +property+ as an id list, checking existence of all.
|
13
|
+
#
|
14
|
+
def initialize(property, opts)
|
15
|
+
@property = property
|
16
|
+
@type = opts[:as] || raise(ArgumentError.new('ExistenceValidator requires as: be provided with a type.'))
|
17
|
+
@list = opts[:list] || false
|
18
|
+
@bad_ids = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def valid?(validated)
|
22
|
+
return false unless validated
|
23
|
+
|
24
|
+
if @list
|
25
|
+
ids = validated.send(@property) || []
|
26
|
+
else
|
27
|
+
ids = [validated.send(property_id)]
|
28
|
+
end
|
29
|
+
|
30
|
+
persister = Persister.for(@type)
|
31
|
+
|
32
|
+
@bad_ids = ids.select do |id|
|
33
|
+
not persister.exists?(id)
|
34
|
+
end
|
35
|
+
|
36
|
+
@bad_ids.empty?
|
37
|
+
end
|
38
|
+
|
39
|
+
def error_message(validated)
|
40
|
+
unless @bad_ids.empty?
|
41
|
+
if @list
|
42
|
+
"Those #{@type.to_s.demodulize.pluralize} (ids: #{@bad_ids.join(", ")}) do not exist."
|
43
|
+
else
|
44
|
+
"That #{@type.to_s.demodulize} (id: #{@bad_ids.first || "nil"}) does not exist."
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
def property_id
|
51
|
+
"#{@property}_id".to_sym
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# Tests whether the given property is set (ie non-nil)
|
2
|
+
#
|
3
|
+
# For more about validation, see Validating
|
4
|
+
class PresenceValidator
|
5
|
+
# Takes the property name as symbol
|
6
|
+
def initialize(property)
|
7
|
+
@property = property
|
8
|
+
end
|
9
|
+
|
10
|
+
def valid?(validated)
|
11
|
+
return false unless validated
|
12
|
+
|
13
|
+
value = validated.send(@property)
|
14
|
+
|
15
|
+
value.present? && !(value =~ /\A\s*\Z/)
|
16
|
+
end
|
17
|
+
|
18
|
+
def error_message(validated)
|
19
|
+
"#{validated.class.to_s.demodulize} #{@property.to_s.gsub('_', ' ').downcase} must be provided."
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# Tests for the existence of the given id in the persister.
|
2
|
+
#
|
3
|
+
# For more about validation, see Validating
|
4
|
+
class SelfExistenceValidator
|
5
|
+
def initialize(type, id)
|
6
|
+
@type = type
|
7
|
+
@id = id
|
8
|
+
end
|
9
|
+
|
10
|
+
# +true+ if the validated object exists in the persister.
|
11
|
+
def valid?(validated)
|
12
|
+
Persister.for(@type).exists?(@id)
|
13
|
+
end
|
14
|
+
|
15
|
+
def error_message(validated)
|
16
|
+
"That #{@type.to_s.demodulize.downcase} (id: #{ @id || "nil" }) does not exist."
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2014 Tenjin Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require './spec/isolations/spec_helper'
|
25
|
+
|
26
|
+
describe ClosureValidator do
|
27
|
+
let(:expected_validity) { double('validity') }
|
28
|
+
let(:expected_error) { double('error') }
|
29
|
+
|
30
|
+
describe 'closure use' do
|
31
|
+
subject do
|
32
|
+
ClosureValidator.new(lambda { |val| expected_validity }, lambda { |err| expected_error })
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should use the block to determines validity' do
|
36
|
+
subject.valid?(expected_validity).should be expected_validity
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should use the second block to determine the error' do
|
40
|
+
subject.error_message(expected_error).should be expected_error
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe 'parameters' do
|
45
|
+
subject do
|
46
|
+
ClosureValidator.new(lambda { |val| val }, lambda { |err| err })
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should pass the validated object into the valid? closure' do
|
50
|
+
subject.valid?(expected_validity).should be expected_validity
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should pass the validated object into the error closure' do
|
54
|
+
subject.error_message(expected_error).should be expected_error
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2014 Tenjin Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require './spec/isolations/spec_helper'
|
25
|
+
|
26
|
+
describe Dirt::Context do
|
27
|
+
describe '#run' do
|
28
|
+
it 'should create an instance and call #call on it' do
|
29
|
+
Dirt::Context.any_instance.should_receive(:call)
|
30
|
+
|
31
|
+
Dirt::Context.run(double('params'))
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should pass forward params to #new' do
|
35
|
+
args = double('params')
|
36
|
+
|
37
|
+
Dirt::Context.should_receive(:new).with(args).and_call_original
|
38
|
+
|
39
|
+
Dirt::Context.run(args)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#initialize' do
|
44
|
+
it 'should accept no param' do
|
45
|
+
Dirt::Context.new()
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should accept params' do
|
49
|
+
args = double('params')
|
50
|
+
|
51
|
+
Dirt::Context.new(args)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,151 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2014 Tenjin Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require './spec/isolations/spec_helper'
|
25
|
+
|
26
|
+
describe ExistenceValidator do
|
27
|
+
let(:persister) { double('persister') }
|
28
|
+
let(:decorated) { double('decorated') }
|
29
|
+
let(:is_list) { false }
|
30
|
+
|
31
|
+
subject { ExistenceValidator.new(:some_reference, {as: :some_class, list: is_list}) }
|
32
|
+
|
33
|
+
before(:each) do
|
34
|
+
Persister.for(:some_class, persister)
|
35
|
+
end
|
36
|
+
|
37
|
+
after(:each) do
|
38
|
+
Persister.clear
|
39
|
+
end
|
40
|
+
|
41
|
+
describe '#initialize' do
|
42
|
+
it 'should explode when as: is not supplied' do
|
43
|
+
expect { ExistenceValidator.new(decorated, {}) }.to raise_error(ArgumentError)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe '#valid?' do
|
48
|
+
it 'should return false if given nil' do
|
49
|
+
subject.valid?(nil).should be false
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'single' do
|
53
|
+
before(:each) do
|
54
|
+
decorated.stub(:some_reference_id).and_return(double('id'))
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should return true when persister has something by the id' do
|
58
|
+
persister.stub(:exists?).and_return(true)
|
59
|
+
|
60
|
+
subject.valid?(decorated).should be true
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'should return false when persister has nothing by the id' do
|
64
|
+
persister.stub(:exists?).and_return(false)
|
65
|
+
|
66
|
+
subject.valid?(decorated).should be false
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context 'list' do
|
71
|
+
subject { ExistenceValidator.new(:some_reference_ids, {as: :some_class, list: true}) }
|
72
|
+
|
73
|
+
before(:each) do
|
74
|
+
decorated.stub(:some_reference_ids).and_return([double('id1'), double('id2'), double('id3')])
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'should return true when persister has something for every id' do
|
78
|
+
persister.stub(:exists?).and_return(true, true, true)
|
79
|
+
|
80
|
+
subject.valid?(decorated).should be true
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should return false when persister has nothing for an id' do
|
84
|
+
persister.stub(:exists?).and_return(true, false, true)
|
85
|
+
|
86
|
+
subject.valid?(decorated).should be false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#errors' do
|
92
|
+
context 'valid? not called previously' do
|
93
|
+
it 'should return nil' do
|
94
|
+
subject.error_message(decorated).should be nil
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'single' do
|
99
|
+
let(:id) { double('id') }
|
100
|
+
before(:each) do
|
101
|
+
decorated.stub(:some_reference_id).and_return(id)
|
102
|
+
end
|
103
|
+
|
104
|
+
it 'should return nil when persister has something for the id' do
|
105
|
+
persister.stub(:exists?).and_return(true)
|
106
|
+
subject.valid?(decorated)
|
107
|
+
|
108
|
+
subject.error_message(decorated).should be nil
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should return an error when persister has nothing for the id' do
|
112
|
+
persister.stub(:exists?).and_return(false)
|
113
|
+
subject.valid?(decorated)
|
114
|
+
|
115
|
+
subject.error_message(decorated).should == "That some_class (id: #{id}) does not exist."
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
context 'list' do
|
120
|
+
subject { ExistenceValidator.new(:some_reference_ids, {as: :some_class, list: true}) }
|
121
|
+
let(:id1) { double('id1') }
|
122
|
+
let(:id2) { double('id2') }
|
123
|
+
let(:id3) { double('id3') }
|
124
|
+
|
125
|
+
before(:each) do
|
126
|
+
decorated.stub(:some_reference_ids).and_return([id1, id2, id3])
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'should return nil when persister has something for every id' do
|
130
|
+
persister.stub(:exists?).and_return(true, true, true)
|
131
|
+
subject.valid?(decorated)
|
132
|
+
|
133
|
+
subject.error_message(decorated).should be nil
|
134
|
+
end
|
135
|
+
|
136
|
+
it 'should return an error when persister has nothing for an id' do
|
137
|
+
persister.stub(:exists?).and_return(false, false, false)
|
138
|
+
subject.valid?(decorated)
|
139
|
+
|
140
|
+
subject.error_message(decorated).should == "Those some_classes (ids: #{[id1, id2, id3].join(", ")}) do not exist."
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'should return include only the failed when persister has nothing for an id' do
|
144
|
+
persister.stub(:exists?).and_return(true, false, false)
|
145
|
+
subject.valid?(decorated)
|
146
|
+
|
147
|
+
subject.error_message(decorated).should == "Those some_classes (ids: #{[id2, id3].join(", ")}) do not exist."
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright (c) 2014 Tenjin Inc.
|
3
|
+
#
|
4
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
# a copy of this software and associated documentation files (the
|
6
|
+
# "Software"), to deal in the Software without restriction, including
|
7
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
# the following conditions:
|
11
|
+
#
|
12
|
+
# The above copyright notice and this permission notice shall be
|
13
|
+
# included in all copies or substantial portions of the Software.
|
14
|
+
#
|
15
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
18
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
#++
|
23
|
+
|
24
|
+
require 'dirt/bdd/persister_spec_helper'
|
25
|
+
require './spec/isolations/spec_helper'
|
26
|
+
|
27
|
+
module Dirt
|
28
|
+
describe MemoryPersister do
|
29
|
+
let(:type) { :test }
|
30
|
+
subject do
|
31
|
+
MemoryPersister.new(:Mock) do |*args|
|
32
|
+
double('Persisting', *args)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
it_behaves_like(:persister) do
|
37
|
+
let(:persisted) { double('persisted object', attr1: 5, to_hash: {attr1: 5}) }
|
38
|
+
let(:persisted2) { double('persisted object 2', attr1: 5, to_hash: {attr1: 5}) }
|
39
|
+
let(:different_persisted) { double('different persisted object', attr1: 28, to_hash: {attr1: 28}) }
|
40
|
+
|
41
|
+
let(:where_params) { {attr1: 5} }
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#new' do
|
45
|
+
it 'should explode when not given a block' do
|
46
|
+
expect { MemoryPersister.new(:some_type).new }.to raise_error(RuntimeError, 'Cannot create a new instance without a block given to init.')
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'should return an object' do
|
50
|
+
subject.new.should_not be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'called with args' do
|
54
|
+
it 'should populate the new object with args data' do
|
55
|
+
subject.new(arg1: 'val1').arg1.should == 'val1'
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe '#save' do
|
61
|
+
let(:data) { double('data', to_hash: {some: 'data'}) }
|
62
|
+
|
63
|
+
it 'should return the id + data as struct on success' do
|
64
|
+
result = subject.save(data)
|
65
|
+
|
66
|
+
result.should == OpenStruct.new(data.to_hash.merge(id: result.id))
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'should remember the data by the given id' do
|
70
|
+
id = 3
|
71
|
+
|
72
|
+
fake1 = double('other data', to_hash: {})
|
73
|
+
fake2 = double('another data', to_hash: {})
|
74
|
+
|
75
|
+
subject.save(fake1)
|
76
|
+
subject.save(fake2)
|
77
|
+
subject.save(double('replaced', to_hash: {}))
|
78
|
+
subject.save(data, id)
|
79
|
+
|
80
|
+
subject.instance_variable_get(:@records).should == {1 => fake1, 2 => fake2, id => data}
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'should remember the data by a made up id when none given' do
|
84
|
+
subject.save(data, nil)
|
85
|
+
|
86
|
+
subject.instance_variable_get(:@records).should == {1 => data}
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe '#load' do
|
91
|
+
let(:data) { double('data', to_hash: {some: 'data'}) }
|
92
|
+
|
93
|
+
it 'should return only the appropriate id and data' do
|
94
|
+
id = double('id')
|
95
|
+
|
96
|
+
subject.instance_variable_set(:@records, {id => data, double('id2') => double('data2')})
|
97
|
+
|
98
|
+
subject.load(id).should == OpenStruct.new(data.to_hash.merge(id: id))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#exists?' do
|
103
|
+
it 'should return only the appropriate id and data' do
|
104
|
+
id = double('id')
|
105
|
+
data = double('data')
|
106
|
+
|
107
|
+
subject.instance_variable_set(:@records, {id => data})
|
108
|
+
|
109
|
+
subject.exists?(id).should be true
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'should raise exception when given an invalid id' do
|
113
|
+
id = double('id3')
|
114
|
+
|
115
|
+
subject.instance_variable_set(:@records, {double('id') => double('data'), double('id2') => double('data2')})
|
116
|
+
|
117
|
+
subject.exists?(id).should be false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#all' do
|
122
|
+
it 'should return all of the appropriate id and data' do
|
123
|
+
records = {double('id1') => double('data1', to_hash: {attr1: double}),
|
124
|
+
double('id2') => double('data2', to_hash: {attr1: double}),
|
125
|
+
double('id3') => double('data3', to_hash: {attr1: double})}
|
126
|
+
|
127
|
+
subject.instance_variable_set(:@records, records)
|
128
|
+
|
129
|
+
subject.all.should == records.collect { |id, r| OpenStruct.new(r.to_hash.merge(id: id)) }
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
describe '#delete' do
|
134
|
+
let(:data) { double('data', to_hash: {some: 'data'}) }
|
135
|
+
|
136
|
+
it 'should return the deleted id and data as a struct' do
|
137
|
+
id = double('id')
|
138
|
+
|
139
|
+
subject.instance_variable_set(:@records, {id => data})
|
140
|
+
|
141
|
+
subject.delete(id).should == OpenStruct.new(data.to_hash.merge(id: id))
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'should delete the given id and data' do
|
145
|
+
id = double('id')
|
146
|
+
|
147
|
+
subject.instance_variable_set(:@records, {id => data})
|
148
|
+
|
149
|
+
subject.delete(id)
|
150
|
+
|
151
|
+
subject.instance_variable_get(:@records).should == {}
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'should delete only the appropriate id and data' do
|
155
|
+
id1 = double('id1')
|
156
|
+
id2 = double('id2')
|
157
|
+
data2 = double('data2')
|
158
|
+
|
159
|
+
subject.instance_variable_set(:@records, {id1 => data, id2 => data2})
|
160
|
+
|
161
|
+
subject.delete(id1)
|
162
|
+
|
163
|
+
subject.instance_variable_get(:@records).should == {id2 => data2}
|
164
|
+
end
|
165
|
+
|
166
|
+
it 'should return nil when given an invalid id' do
|
167
|
+
id = double('id3')
|
168
|
+
|
169
|
+
subject.instance_variable_set(:@records, {double('id') => double('data'), double('id2') => double('data2')})
|
170
|
+
|
171
|
+
subject.delete(id).should == nil
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|