1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
require_relative '../../spec_helper'
require_relative 'fixtures/classes'
describe "Data#deconstruct_keys" do
it "returns a hash of attributes" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
end
it "requires one argument" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
-> {
d.deconstruct_keys
}.should raise_error(ArgumentError, /wrong number of arguments \(given 0, expected 1\)/)
end
it "returns only specified keys" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([:x, :y]).should == {x: 1, y: 2}
d.deconstruct_keys([:x] ).should == {x: 1}
d.deconstruct_keys([] ).should == {}
end
it "accepts string attribute names" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys(['x', 'y']).should == {'x' => 1, 'y' => 2}
end
it "accepts argument position number as well but returns them as keys" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([0, 1]).should == {0 => 1, 1 => 2}
d.deconstruct_keys([0] ).should == {0 => 1}
d.deconstruct_keys([-1] ).should == {-1 => 2}
end
it "ignores incorrect position numbers" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([0, 3]).should == {0 => 1}
end
it "support mixing attribute names and argument position numbers" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([0, :x]).should == {0 => 1, :x => 1}
end
it "returns an empty hash when there are more keys than attributes" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([:x, :y, :x]).should == {}
end
it "returns at first not existing attribute name" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([:a, :x]).should == {}
d.deconstruct_keys([:x, :a]).should == {x: 1}
end
it "returns at first not existing argument position number" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys([3, 0]).should == {}
d.deconstruct_keys([0, 3]).should == {0 => 1}
end
it "accepts nil argument and return all the attributes" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
d.deconstruct_keys(nil).should == {x: 1, y: 2}
end
it "tries to convert a key with #to_int if index is not a String nor a Symbol, but responds to #to_int" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
key = mock("to_int")
key.should_receive(:to_int).and_return(1)
d.deconstruct_keys([key]).should == { key => 2 }
end
it "raises a TypeError if the conversion with #to_int does not return an Integer" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
key = mock("to_int")
key.should_receive(:to_int).and_return("not an Integer")
-> {
d.deconstruct_keys([key])
}.should raise_error(TypeError, /can't convert MockObject to Integer/)
end
it "raises TypeError if index is not a String, a Symbol and not convertible to Integer " do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
-> {
d.deconstruct_keys([0, []])
}.should raise_error(TypeError, "no implicit conversion of Array into Integer")
end
it "raise TypeError if passed anything except nil or array" do
klass = Data.define(:x, :y)
d = klass.new(1, 2)
-> { d.deconstruct_keys('x') }.should raise_error(TypeError, /expected Array or nil/)
-> { d.deconstruct_keys(1) }.should raise_error(TypeError, /expected Array or nil/)
-> { d.deconstruct_keys(:x) }.should raise_error(TypeError, /expected Array or nil/)
-> { d.deconstruct_keys({}) }.should raise_error(TypeError, /expected Array or nil/)
end
end
|