son_jay 0.4.1 → 0.5.0
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.
- checksums.yaml +8 -8
- data/CHANGELOG.md +13 -1
- data/lib/son_jay/acts_as_model.rb +6 -1
- data/lib/son_jay/model_array.rb +43 -2
- data/lib/son_jay/object_model/{properties → content}/abstract.rb +44 -8
- data/lib/son_jay/object_model/content/content_with_extra.rb +63 -0
- data/lib/son_jay/object_model/{properties/properties_without_extra.rb → content/content_without_extra.rb} +12 -2
- data/lib/son_jay/object_model/content.rb +20 -0
- data/lib/son_jay/object_model/content_data.rb +74 -0
- data/lib/son_jay/object_model/property_definitions.rb +12 -0
- data/lib/son_jay/object_model.rb +33 -13
- data/lib/son_jay/value_array.rb +1 -1
- data/lib/son_jay/version.rb +1 -1
- data/spec/acts_as_model_spec.rb +4 -4
- data/spec/model_array_spec.rb +86 -25
- data/spec/object_model/content/content_with_extra_spec.rb +201 -0
- data/spec/object_model/content/content_without_extra_spec.rb +180 -0
- data/spec/object_model/content_data_spec.rb +81 -0
- data/spec/object_model_spec.rb +106 -92
- data/spec/son_jay_spec.rb +1 -1
- data/spec/value_array_spec.rb +2 -2
- metadata +13 -9
- data/lib/son_jay/object_model/extra_data.rb +0 -36
- data/lib/son_jay/object_model/properties/properties_with_extra.rb +0 -27
- data/lib/son_jay/object_model/properties.rb +0 -20
- data/spec/object_model/extra_data_spec.rb +0 -37
data/spec/model_array_spec.rb
CHANGED
@@ -25,7 +25,7 @@ describe SonJay::ModelArray do
|
|
25
25
|
end
|
26
26
|
|
27
27
|
attr_accessor :loaded_data
|
28
|
-
def
|
28
|
+
def model_content ; Content.new(self) ; end
|
29
29
|
end }
|
30
30
|
|
31
31
|
describe '::array_class' do
|
@@ -36,40 +36,101 @@ describe SonJay::ModelArray do
|
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
39
|
+
describe "an instance" do
|
40
|
+
subject { subclass.new }
|
41
|
+
|
42
|
+
it "is initially empty" do
|
43
|
+
expect( subject ).to be_empty
|
44
|
+
expect( subject.length ).to eq( 0 )
|
45
|
+
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
47
|
+
describe "#additional" do
|
48
|
+
it "adds a new entry of the modeled type, and returns the entry" do
|
49
|
+
entry_0 = subject.additional
|
50
|
+
entry_1 = subject.additional
|
48
51
|
|
49
|
-
|
50
|
-
entry_1 = instance.additional
|
52
|
+
expect( entry_0 ).to be_kind_of( entry_class )
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
+
expect( subject.entries ).to eq( [
|
55
|
+
entry_0,
|
56
|
+
entry_1
|
57
|
+
] )
|
58
|
+
end
|
54
59
|
end
|
55
|
-
end
|
56
60
|
|
57
|
-
|
58
|
-
|
59
|
-
|
61
|
+
describe '#load_data' do
|
62
|
+
it "loads entries in the given enumerable into its own model instance entries" do
|
63
|
+
subject.load_data( ['entry 0 data', 'entry 1 data'] )
|
60
64
|
|
61
|
-
|
65
|
+
expect( subject.length ).to eq( 2 )
|
66
|
+
expect( subject[0].loaded_data ).to eq( 'entry 0 data' )
|
67
|
+
expect( subject[1].loaded_data ).to eq( 'entry 1 data' )
|
68
|
+
end
|
69
|
+
end
|
62
70
|
|
63
|
-
|
64
|
-
|
65
|
-
|
71
|
+
describe "#to_a" do
|
72
|
+
it "returns an isolated array of the entries" do
|
73
|
+
entry_0 = subject.additional
|
74
|
+
entry_1 = subject.additional
|
75
|
+
|
76
|
+
actual_array = subject.to_a
|
77
|
+
|
78
|
+
entry_2 = subject.additional
|
79
|
+
|
80
|
+
expect( actual_array ).to eq( [
|
81
|
+
entry_0,
|
82
|
+
entry_1
|
83
|
+
] )
|
84
|
+
end
|
66
85
|
end
|
67
|
-
end
|
68
86
|
|
69
|
-
|
70
|
-
|
71
|
-
|
87
|
+
describe '#model_content' do
|
88
|
+
it "returns the model array" do
|
89
|
+
expect( subject.model_content ).to equal( subject )
|
90
|
+
end
|
72
91
|
end
|
92
|
+
|
93
|
+
describe '#freeze' do
|
94
|
+
it "causes the instance to behave as frozen" do
|
95
|
+
subject.freeze
|
96
|
+
expect{ subject.additional }.to raise_exception( RuntimeError )
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#dup' do
|
101
|
+
it "makes a shallow copy" do
|
102
|
+
subject.additional
|
103
|
+
actual_dup = subject.dup
|
104
|
+
expect( actual_dup[0] ).to eq( subject[0] )
|
105
|
+
actual_dup.additional
|
106
|
+
expect( subject.length ).to eq( 1 )
|
107
|
+
end
|
108
|
+
|
109
|
+
it "returns a thawed copy of a frozen instance" do
|
110
|
+
subject.freeze
|
111
|
+
actual_dup = subject.dup
|
112
|
+
expect( actual_dup ).not_to be_frozen
|
113
|
+
expect{ actual_dup.additional }.not_to raise_exception
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe '#clone' do
|
118
|
+
it "makes a shallow copy" do
|
119
|
+
subject.additional
|
120
|
+
actual_clone = subject.clone
|
121
|
+
expect( actual_clone[0] ).to eq( subject[0] )
|
122
|
+
actual_clone.additional
|
123
|
+
expect( subject.length ).to eq( 1 )
|
124
|
+
end
|
125
|
+
|
126
|
+
it "returns a frozen copy of a frozen instance" do
|
127
|
+
subject.freeze
|
128
|
+
actual_clone = subject.clone
|
129
|
+
expect( actual_clone ).to be_frozen
|
130
|
+
expect{ actual_clone.additional }.to raise_exception( RuntimeError )
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
73
134
|
end
|
74
135
|
end
|
75
136
|
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SonJay
|
4
|
+
|
5
|
+
describe ObjectModel::Content::ContentWithExtra do
|
6
|
+
let( :detail_xy_class ) { models_module::DetailXY }
|
7
|
+
let( :detail_z_class ) { models_module::DetailZ }
|
8
|
+
|
9
|
+
let( :models_module ) {
|
10
|
+
mod = Module.new
|
11
|
+
mod::M = mod
|
12
|
+
|
13
|
+
module mod::M
|
14
|
+
class DetailXY < SonJay::ObjectModel
|
15
|
+
properties do
|
16
|
+
property :xxx
|
17
|
+
property :yyy
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class DetailZ < SonJay::ObjectModel
|
22
|
+
properties do
|
23
|
+
property :zzz
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
mod
|
29
|
+
}
|
30
|
+
|
31
|
+
let( :value_property_initializations ) {
|
32
|
+
->(*) {
|
33
|
+
property :aaa
|
34
|
+
property :bbb
|
35
|
+
}
|
36
|
+
}
|
37
|
+
let( :object_model_property_initializations ) {
|
38
|
+
_xy_class = detail_xy_class
|
39
|
+
_z_class = detail_z_class
|
40
|
+
->(*) {
|
41
|
+
property :detail_xy , model: _xy_class
|
42
|
+
property :detail_z , model: [_z_class]
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
context "with various properties defined" do
|
47
|
+
subject {
|
48
|
+
described_class.new( property_defs )
|
49
|
+
}
|
50
|
+
let( :property_defs ) {
|
51
|
+
ObjectModel::PropertyDefinitions.from_initializations( [
|
52
|
+
value_property_initializations,
|
53
|
+
object_model_property_initializations
|
54
|
+
] )
|
55
|
+
}
|
56
|
+
|
57
|
+
it "provides access to an extra-properties object" do
|
58
|
+
expect( subject.extra.to_h ).to eq( {} )
|
59
|
+
end
|
60
|
+
|
61
|
+
it "rejects assignment of an undefined property" do
|
62
|
+
expect{
|
63
|
+
subject['qq'] = 0
|
64
|
+
}.to raise_exception(
|
65
|
+
SonJay::PropertyNameError
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "implements enumerable behaviors" do
|
70
|
+
expect( subject ).to respond_to( :entries )
|
71
|
+
end
|
72
|
+
|
73
|
+
it "enumerates entries for all defined properties and extra assigned property values" do
|
74
|
+
subject['bbb'] = 'B'
|
75
|
+
subject['detail_xy'].xxx = 'X'
|
76
|
+
subject.extra['qqq'] = 'Q'
|
77
|
+
subject.extra['rrr'] = nil
|
78
|
+
actual_pairs = []
|
79
|
+
subject.each do |*pair|
|
80
|
+
actual_pairs << pair
|
81
|
+
end
|
82
|
+
expect( actual_pairs ).to match_array( [
|
83
|
+
[ 'aaa', nil ],
|
84
|
+
[ 'bbb', 'B' ],
|
85
|
+
[ 'qqq', 'Q' ],
|
86
|
+
[ 'rrr', nil ],
|
87
|
+
[ 'detail_xy', subject['detail_xy'] ],
|
88
|
+
[ 'detail_z', subject['detail_z' ] ],
|
89
|
+
] )
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '#freeze' do
|
93
|
+
it "causes the instance to behave as frozen" do
|
94
|
+
subject.freeze
|
95
|
+
expect{ subject['aaa'] = 1 }.to raise_exception( RuntimeError )
|
96
|
+
expect{ subject.extra['qq'] = 2 }.to raise_exception( RuntimeError )
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe '#dup' do
|
101
|
+
it "makes a shallow copy" do
|
102
|
+
subject[ 'aaa' ] = 'A'
|
103
|
+
subject[ 'bbb' ] = 'B'
|
104
|
+
subject.extra['qq'] = 'Q'
|
105
|
+
actual_dup = subject.dup
|
106
|
+
expect( actual_dup[ 'aaa' ] ).to eq( 'A' )
|
107
|
+
expect( actual_dup[ 'bbb' ] ).to eq( 'B' )
|
108
|
+
expect( actual_dup[ 'detail_xy' ] ).to equal( subject[ 'detail_xy' ] )
|
109
|
+
expect( actual_dup[ 'detail_z' ] ).to equal( subject[ 'detail_z' ] )
|
110
|
+
actual_dup[ 'bbb' ] = 'BB'
|
111
|
+
actual_dup.extra['qq'] = 'QQ'
|
112
|
+
expect( subject['bbb'] ).to eq( 'B' )
|
113
|
+
expect( subject.extra['qq'] ).to eq( 'Q' )
|
114
|
+
end
|
115
|
+
|
116
|
+
it "returns a thawed copy of a frozen instance" do
|
117
|
+
subject.extra['qq'] = 11
|
118
|
+
subject.freeze
|
119
|
+
actual_dup = subject.dup
|
120
|
+
expect( actual_dup ).not_to be_frozen
|
121
|
+
actual_dup['aaa'] = 98
|
122
|
+
actual_dup.extra['qq'] = 99
|
123
|
+
expect( actual_dup['aaa'] ).to eq( 98 )
|
124
|
+
expect( actual_dup.extra['qq'] ).to eq( 99 )
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#clone' do
|
129
|
+
it "makes a shallow copy" do
|
130
|
+
subject[ 'aaa' ] = 'A'
|
131
|
+
subject[ 'bbb' ] = 'B'
|
132
|
+
subject.extra['qq'] = 'Q'
|
133
|
+
actual_clone = subject.clone
|
134
|
+
expect( actual_clone[ 'aaa' ] ).to eq( 'A' )
|
135
|
+
expect( actual_clone[ 'bbb' ] ).to eq( 'B' )
|
136
|
+
expect( actual_clone[ 'detail_xy' ] ).to equal( subject[ 'detail_xy' ] )
|
137
|
+
expect( actual_clone[ 'detail_z' ] ).to equal( subject[ 'detail_z' ] )
|
138
|
+
expect( actual_clone.extra['qq'] ).to eq('Q')
|
139
|
+
actual_clone['bbb'] = 'BB'
|
140
|
+
actual_clone.extra['qq'] = 'QQ'
|
141
|
+
expect( subject['bbb'] ).to eq( 'B' )
|
142
|
+
expect( subject.extra['qq'] ).to eq( 'Q' )
|
143
|
+
end
|
144
|
+
|
145
|
+
it "returns a frozen copy of a frozen instance" do
|
146
|
+
subject.extra['qq'] = 1
|
147
|
+
subject.freeze
|
148
|
+
actual_clone = subject.clone
|
149
|
+
expect( actual_clone ).to be_frozen
|
150
|
+
expect{ subject['aaa'] = 9 }.to raise_exception( RuntimeError )
|
151
|
+
expect{ subject.extra['qq'] = 9 }.to raise_exception( RuntimeError )
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
context "with value properties defined" do
|
157
|
+
subject {
|
158
|
+
described_class.new( property_defs )
|
159
|
+
}
|
160
|
+
let( :property_defs ) {
|
161
|
+
ObjectModel::PropertyDefinitions.from_initializations( [
|
162
|
+
value_property_initializations
|
163
|
+
] )
|
164
|
+
}
|
165
|
+
|
166
|
+
it "has an initial number of entries equal to its number of defined properties" do
|
167
|
+
expect( subject.length ).to eq( 2 )
|
168
|
+
end
|
169
|
+
|
170
|
+
it "has name-indexed settable/gettable value properties by string or symbol" do
|
171
|
+
subject[ :aaa ] = 1
|
172
|
+
subject[ 'bbb' ] = 'XYZ'
|
173
|
+
|
174
|
+
expect( subject[ 'aaa' ] ).to eq( 1 )
|
175
|
+
expect( subject[ :bbb ] ).to eq( 'XYZ' )
|
176
|
+
end
|
177
|
+
|
178
|
+
it "has all property values nil by default" do
|
179
|
+
expect( subject[ 'aaa' ] ).to be_nil
|
180
|
+
expect( subject[ :bbb ] ).to be_nil
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
context "with model properties defined" do
|
185
|
+
subject {
|
186
|
+
described_class.new( property_defs )
|
187
|
+
}
|
188
|
+
let( :property_defs ) {
|
189
|
+
ObjectModel::PropertyDefinitions.from_initializations( [
|
190
|
+
object_model_property_initializations
|
191
|
+
] )
|
192
|
+
}
|
193
|
+
|
194
|
+
it "has name-indexed gettable values for defined properties by string or symbol" do
|
195
|
+
expect( subject[ 'detail_xy' ] ).to be_kind_of( detail_xy_class )
|
196
|
+
expect( subject[ :detail_z ] ).to be_kind_of( detail_z_class::Array )
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module SonJay
|
4
|
+
|
5
|
+
describe ObjectModel::Content::ContentWithoutExtra do
|
6
|
+
let( :detail_xy_class ) { models_module::DetailXY }
|
7
|
+
let( :detail_z_class ) { models_module::DetailZ }
|
8
|
+
|
9
|
+
let( :models_module ) {
|
10
|
+
mod = Module.new
|
11
|
+
mod::M = mod
|
12
|
+
|
13
|
+
module mod::M
|
14
|
+
class DetailXY < SonJay::ObjectModel
|
15
|
+
properties do
|
16
|
+
property :xxx
|
17
|
+
property :yyy
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class DetailZ < SonJay::ObjectModel
|
22
|
+
properties do
|
23
|
+
property :zzz
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
mod
|
29
|
+
}
|
30
|
+
|
31
|
+
let( :value_property_initializations ) {
|
32
|
+
->(*) {
|
33
|
+
property :aaa
|
34
|
+
property :bbb
|
35
|
+
}
|
36
|
+
}
|
37
|
+
let( :object_model_property_initializations ) {
|
38
|
+
_xy_class = detail_xy_class
|
39
|
+
_z_class = detail_z_class
|
40
|
+
->(*) {
|
41
|
+
property :detail_xy , model: _xy_class
|
42
|
+
property :detail_z , model: [_z_class]
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
context "with various properties defined" do
|
47
|
+
subject {
|
48
|
+
described_class.new( property_defs )
|
49
|
+
}
|
50
|
+
let( :property_defs ) {
|
51
|
+
ObjectModel::PropertyDefinitions.from_initializations( [
|
52
|
+
value_property_initializations,
|
53
|
+
object_model_property_initializations
|
54
|
+
] )
|
55
|
+
}
|
56
|
+
|
57
|
+
it "rejects assignment of an undefined property" do
|
58
|
+
expect{
|
59
|
+
subject['qq'] = 0
|
60
|
+
}.to raise_exception(
|
61
|
+
SonJay::PropertyNameError
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "implements enumerable behaviors" do
|
66
|
+
expect( subject ).to respond_to( :entries )
|
67
|
+
end
|
68
|
+
|
69
|
+
it "enumerates entries for all defined properties" do
|
70
|
+
subject['bbb'] = 'B'
|
71
|
+
subject['detail_xy'].xxx = 'X'
|
72
|
+
actual_pairs = []
|
73
|
+
subject.each do |*pair|
|
74
|
+
actual_pairs << pair
|
75
|
+
end
|
76
|
+
expect( actual_pairs ).to match_array( [
|
77
|
+
[ 'aaa', nil ],
|
78
|
+
[ 'bbb', 'B' ],
|
79
|
+
[ 'detail_xy', subject['detail_xy'] ],
|
80
|
+
[ 'detail_z', subject['detail_z' ] ],
|
81
|
+
] )
|
82
|
+
end
|
83
|
+
|
84
|
+
describe '#freeze' do
|
85
|
+
it "causes the instance to behave as frozen" do
|
86
|
+
subject.freeze
|
87
|
+
expect{ subject['aaa'] = 1 }.to raise_exception( RuntimeError )
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe '#dup' do
|
92
|
+
it "makes a shallow copy" do
|
93
|
+
subject[ 'aaa' ] = 'A'
|
94
|
+
subject[ 'bbb' ] = 'B'
|
95
|
+
actual_dup = subject.dup
|
96
|
+
expect( actual_dup[ 'aaa' ] ).to eq( 'A' )
|
97
|
+
expect( actual_dup[ 'bbb' ] ).to eq( 'B' )
|
98
|
+
expect( actual_dup[ 'detail_xy' ] ).to equal( subject[ 'detail_xy' ] )
|
99
|
+
expect( actual_dup[ 'detail_z' ] ).to equal( subject[ 'detail_z' ] )
|
100
|
+
actual_dup[ 'bbb' ] = 'BB'
|
101
|
+
expect( subject['bbb'] ).to eq( 'B' )
|
102
|
+
end
|
103
|
+
|
104
|
+
it "returns a thawed copy of a frozen instance" do
|
105
|
+
subject.freeze
|
106
|
+
actual_dup = subject.dup
|
107
|
+
expect( actual_dup ).not_to be_frozen
|
108
|
+
actual_dup['aaa'] = 99
|
109
|
+
expect( actual_dup['aaa'] ).to eq( 99 )
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe '#clone' do
|
114
|
+
it "makes a shallow copy" do
|
115
|
+
subject[ 'aaa' ] = 'A'
|
116
|
+
subject[ 'bbb' ] = 'B'
|
117
|
+
actual_clone = subject.clone
|
118
|
+
expect( actual_clone[ 'aaa' ] ).to eq( 'A' )
|
119
|
+
expect( actual_clone[ 'bbb' ] ).to eq( 'B' )
|
120
|
+
expect( actual_clone[ 'detail_xy' ] ).to equal( subject[ 'detail_xy' ] )
|
121
|
+
expect( actual_clone[ 'detail_z' ] ).to equal( subject[ 'detail_z' ] )
|
122
|
+
actual_clone[ 'bbb' ] = 'BB'
|
123
|
+
expect( subject['bbb'] ).to eq( 'B' )
|
124
|
+
end
|
125
|
+
|
126
|
+
it "returns a frozen copy of a frozen instance" do
|
127
|
+
subject.freeze
|
128
|
+
actual_clone = subject.clone
|
129
|
+
expect( actual_clone ).to be_frozen
|
130
|
+
expect{ subject['aaa'] = 1 }.to raise_exception( RuntimeError )
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context "with value properties defined" do
|
136
|
+
subject {
|
137
|
+
described_class.new( property_defs )
|
138
|
+
}
|
139
|
+
let( :property_defs ) {
|
140
|
+
ObjectModel::PropertyDefinitions.from_initializations( [
|
141
|
+
value_property_initializations
|
142
|
+
] )
|
143
|
+
}
|
144
|
+
|
145
|
+
it "has an initial number of entries equal to its number of defined properties" do
|
146
|
+
expect( subject.length ).to eq( 2 )
|
147
|
+
end
|
148
|
+
|
149
|
+
it "has name-indexed settable/gettable value properties by string or symbol" do
|
150
|
+
subject[ :aaa ] = 1
|
151
|
+
subject[ 'bbb' ] = 'XYZ'
|
152
|
+
|
153
|
+
expect( subject[ 'aaa' ] ).to eq( 1 )
|
154
|
+
expect( subject[ :bbb ] ).to eq( 'XYZ' )
|
155
|
+
end
|
156
|
+
|
157
|
+
it "has all property values nil by default" do
|
158
|
+
expect( subject[ 'aaa' ] ).to be_nil
|
159
|
+
expect( subject[ :bbb ] ).to be_nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "with model properties defined" do
|
164
|
+
subject {
|
165
|
+
described_class.new( property_defs )
|
166
|
+
}
|
167
|
+
let( :property_defs ) {
|
168
|
+
ObjectModel::PropertyDefinitions.from_initializations( [
|
169
|
+
object_model_property_initializations
|
170
|
+
] )
|
171
|
+
}
|
172
|
+
|
173
|
+
it "has name-indexed gettable values for defined properties by string or symbol" do
|
174
|
+
expect( subject[ 'detail_xy' ] ).to be_kind_of( detail_xy_class )
|
175
|
+
expect( subject[ :detail_z ] ).to be_kind_of( detail_z_class::Array )
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SonJay::ObjectModel::ContentData do
|
4
|
+
|
5
|
+
it "provides value access by name symbol or string" do
|
6
|
+
subject[ :aaa ] = 1
|
7
|
+
subject[ 'bbb' ] = 2
|
8
|
+
expect( subject[ 'aaa' ] ).to eq( 1 )
|
9
|
+
expect( subject[ :bbb ] ).to eq( 2 )
|
10
|
+
end
|
11
|
+
|
12
|
+
it "merges with a hash, returning a hash" do
|
13
|
+
subject[ :aa ] = 1
|
14
|
+
subject[ :bb ] = 2
|
15
|
+
|
16
|
+
actual = subject.hash_merge(
|
17
|
+
"bb" => 22,
|
18
|
+
"cc" => 33
|
19
|
+
)
|
20
|
+
|
21
|
+
expect( actual ).to eq(
|
22
|
+
'aa' => 1,
|
23
|
+
'bb' => 22,
|
24
|
+
'cc' => 33
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "indicates when it is empty" do
|
29
|
+
expect( subject ).to be_empty
|
30
|
+
end
|
31
|
+
|
32
|
+
it "indicates when it is not empty" do
|
33
|
+
subject[:a] = 'a'
|
34
|
+
expect( subject ).not_to be_empty
|
35
|
+
end
|
36
|
+
|
37
|
+
describe '#freeze' do
|
38
|
+
it "causes the instance to behave as frozen" do
|
39
|
+
subject.freeze
|
40
|
+
expect{ subject['a'] = 1 }.to raise_exception( RuntimeError )
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe '#dup' do
|
45
|
+
it "makes a shallow copy" do
|
46
|
+
subject[ 'aa' ] = 'A'
|
47
|
+
subject[ 'bb' ] = 'B'
|
48
|
+
actual_dup = subject.dup
|
49
|
+
expect( actual_dup.keys ).to match_array( ['aa', 'bb'] )
|
50
|
+
expect( actual_dup['aa'] ).to equal( subject['aa'] )
|
51
|
+
actual_dup['bb'] = 'BBB'
|
52
|
+
expect( subject['bb'] ).to eq( 'B' )
|
53
|
+
end
|
54
|
+
|
55
|
+
it "returns a thawed copy of a frozen instance" do
|
56
|
+
subject.freeze
|
57
|
+
actual_dup = subject.dup
|
58
|
+
expect( actual_dup ).not_to be_frozen
|
59
|
+
actual_dup['aa'] = 1
|
60
|
+
expect( actual_dup['aa'] ).to eq( 1 )
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe '#clone' do
|
65
|
+
it "makes a shallow copy" do
|
66
|
+
subject[ 'aa' ] = 'A'
|
67
|
+
subject[ 'bb' ] = 'B'
|
68
|
+
actual_clone = subject.clone
|
69
|
+
expect( actual_clone.keys ).to match_array( ['aa', 'bb'] )
|
70
|
+
expect( actual_clone['aa'] ).to equal( subject['aa'] )
|
71
|
+
actual_clone['bb'] = 'BBB'
|
72
|
+
expect( subject['bb'] ).to eq( 'B' )
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns a frozen copy of a frozen instance" do
|
76
|
+
subject.freeze
|
77
|
+
expect( subject.clone ).to be_frozen
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|