hamsterdam 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -0
- data/lib/hamsterdam.rb +16 -1
- data/spec/hamsterdam_spec.rb +104 -71
- metadata +1 -1
data/CHANGELOG
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
Hamsterdam v1.0.1
|
2
|
+
* Added nice to_s and inspect
|
3
|
+
* Also storing .field_names_list as another way of getting field names of a struct, but retaining order of declaration (.field_names is a Hamster.set, .field_names_list is a Hamster.list)
|
4
|
+
|
1
5
|
Hamsterdam v1.0.0
|
2
6
|
* Can define immutable record types via Hamsterdam::Struct.define(*field_names)
|
3
7
|
* Provides getters for all fields, and set_* transformers that return the updated version of the record.
|
data/lib/hamsterdam.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'hamster'
|
2
2
|
|
3
3
|
module Hamsterdam
|
4
|
-
VERSION = "1.0.
|
4
|
+
VERSION = "1.0.1"
|
5
5
|
|
6
6
|
class Struct
|
7
7
|
def self.define(*field_names)
|
@@ -19,10 +19,14 @@ module Hamsterdam
|
|
19
19
|
end
|
20
20
|
|
21
21
|
struct_class.instance_variable_set(:@field_names, Hamster.set(*field_names))
|
22
|
+
struct_class.instance_variable_set(:@field_names_list, Hamster.list(*field_names))
|
22
23
|
class << struct_class
|
23
24
|
def field_names
|
24
25
|
@field_names
|
25
26
|
end
|
27
|
+
def field_names_list
|
28
|
+
@field_names_list
|
29
|
+
end
|
26
30
|
end
|
27
31
|
struct_class
|
28
32
|
end
|
@@ -52,6 +56,17 @@ module Hamsterdam
|
|
52
56
|
@data
|
53
57
|
end
|
54
58
|
|
59
|
+
def inspect
|
60
|
+
to_s
|
61
|
+
end
|
62
|
+
|
63
|
+
def to_s
|
64
|
+
name = self.class.name.split(/::/).last
|
65
|
+
data = to_hamster_hash
|
66
|
+
fields = self.class.field_names_list.map { |fname| "#{fname}: #{data[fname].inspect}" }
|
67
|
+
"<#{([name]+fields).join(" ")}>"
|
68
|
+
end
|
69
|
+
|
55
70
|
private
|
56
71
|
def validate_keys(data)
|
57
72
|
valid_keys = self.class.field_names
|
data/spec/hamsterdam_spec.rb
CHANGED
@@ -4,8 +4,10 @@ describe "Hamsterdam structures" do
|
|
4
4
|
def define_hamsterdam_struct(*field_names)
|
5
5
|
Hamsterdam::Struct.define(*field_names)
|
6
6
|
end
|
7
|
+
|
8
|
+
let(:struct_class) { define_hamsterdam_struct(:top, :bottom) }
|
9
|
+
|
7
10
|
describe "Struct.define" do
|
8
|
-
let(:struct_class) { define_hamsterdam_struct(:top, :bottom) }
|
9
11
|
|
10
12
|
it "creates a structure class based on the given fields" do
|
11
13
|
struct = struct_class.new(top: 200, bottom: "all the way down")
|
@@ -45,89 +47,120 @@ describe "Hamsterdam structures" do
|
|
45
47
|
it "raises helpful error when constructed with invalid objects" do
|
46
48
|
lambda do struct_class.new("LAWDY") end.should raise_error /Do not want.*LAWDY/
|
47
49
|
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "equality" do
|
53
|
+
it "considers two structs equal if they have the same field values" do
|
54
|
+
s1 = struct_class.new(top: 50, bottom: 75)
|
55
|
+
s2 = struct_class.new(top: 50, bottom: 75)
|
56
|
+
s1.eql?(s2).should == true
|
57
|
+
(s1 == s2).should == true
|
58
|
+
s1.should == s2
|
59
|
+
end
|
48
60
|
|
49
|
-
|
50
|
-
it "considers two structs equal if they have the same field values" do
|
51
|
-
s1 = struct_class.new(top: 50, bottom: 75)
|
52
|
-
s2 = struct_class.new(top: 50, bottom: 75)
|
53
|
-
s1.eql?(s2).should == true
|
54
|
-
(s1 == s2).should == true
|
55
|
-
s1.should == s2
|
56
|
-
end
|
57
|
-
|
58
|
-
it "considers two structs NOT equal if they have the different field values" do
|
59
|
-
s1 = struct_class.new(top: 50, bottom: 75)
|
60
|
-
s2 = struct_class.new(top: 50, bottom: 74)
|
61
|
-
s3 = struct_class.new(top: 51, bottom: 75)
|
62
|
-
|
63
|
-
s1.eql?(s2).should_not == true
|
64
|
-
(s1 == s2).should_not == true
|
65
|
-
s1.should_not == s2
|
66
|
-
|
67
|
-
s1.eql?(s3).should_not == true
|
68
|
-
(s1 == s3).should_not == true
|
69
|
-
s1.should_not == s3
|
70
|
-
end
|
71
|
-
|
72
|
-
it "doesn't consider to structs eql? unless they are same class" do
|
73
|
-
s1 = struct_class.new(top: 50, bottom: 75)
|
74
|
-
s2 = define_hamsterdam_struct(:top, :bottom).new(top:50, bottom:75)
|
75
|
-
s1.eql?(s2).should == false
|
76
|
-
(s1 == s2).should == true # should still be ==
|
77
|
-
end
|
78
|
-
|
79
|
-
it "considers equal two structs if one has missing keys, and the other has nil values for those keys" do
|
80
|
-
s1 = struct_class.new(top: 50, bottom: nil)
|
81
|
-
s2 = struct_class.new(top: 50)
|
82
|
-
#binding.pry
|
83
|
-
s1.eql?(s2).should == true
|
84
|
-
(s1 == s2).should == true
|
85
|
-
s1.should == s2
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
it "uses the same #hash as Hamster::Hash" do
|
61
|
+
it "considers two structs NOT equal if they have the different field values" do
|
90
62
|
s1 = struct_class.new(top: 50, bottom: 75)
|
91
|
-
|
63
|
+
s2 = struct_class.new(top: 50, bottom: 74)
|
64
|
+
s3 = struct_class.new(top: 51, bottom: 75)
|
65
|
+
|
66
|
+
s1.eql?(s2).should_not == true
|
67
|
+
(s1 == s2).should_not == true
|
68
|
+
s1.should_not == s2
|
69
|
+
|
70
|
+
s1.eql?(s3).should_not == true
|
71
|
+
(s1 == s3).should_not == true
|
72
|
+
s1.should_not == s3
|
73
|
+
end
|
74
|
+
|
75
|
+
it "doesn't consider to structs eql? unless they are same class" do
|
76
|
+
s1 = struct_class.new(top: 50, bottom: 75)
|
77
|
+
s2 = define_hamsterdam_struct(:top, :bottom).new(top:50, bottom:75)
|
78
|
+
s1.eql?(s2).should == false
|
79
|
+
(s1 == s2).should == true # should still be ==
|
80
|
+
end
|
81
|
+
|
82
|
+
it "considers equal two structs if one has missing keys, and the other has nil values for those keys" do
|
83
|
+
s1 = struct_class.new(top: 50, bottom: nil)
|
84
|
+
s2 = struct_class.new(top: 50)
|
85
|
+
#binding.pry
|
86
|
+
s1.eql?(s2).should == true
|
87
|
+
(s1 == s2).should == true
|
88
|
+
s1.should == s2
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "uses the same #hash as Hamster::Hash" do
|
93
|
+
s1 = struct_class.new(top: 50, bottom: 75)
|
94
|
+
s1.hash.should == Hamster.hash(top:50, bottom:75).hash
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "transformation" do
|
98
|
+
it "provides setters for individual fields that return an updated version of the struct" do
|
99
|
+
struct = struct_class.new(top: 10, bottom: 1)
|
100
|
+
struct2 = struct.set_top("woot")
|
101
|
+
struct2.top.should == "woot"
|
102
|
+
struct2.bottom.should == 1
|
103
|
+
|
104
|
+
struct.top.should == 10
|
105
|
+
struct.bottom.should == 1
|
92
106
|
end
|
93
107
|
|
94
|
-
|
95
|
-
|
96
|
-
struct = struct_class.new(top: 10, bottom: 1)
|
97
|
-
struct2 = struct.set_top("woot")
|
98
|
-
struct2.top.should == "woot"
|
99
|
-
struct2.bottom.should == 1
|
108
|
+
it "provides a merge function" do
|
109
|
+
struct = struct_class.new(top: 10, bottom: 1)
|
100
110
|
|
101
|
-
|
102
|
-
|
103
|
-
|
111
|
+
struct2 = struct.merge(bottom: "new")
|
112
|
+
struct2.top.should == 10
|
113
|
+
struct2.bottom.should == "new"
|
104
114
|
|
105
|
-
|
106
|
-
|
115
|
+
struct.top.should == 10
|
116
|
+
struct.bottom.should == 1
|
107
117
|
|
108
|
-
|
109
|
-
|
110
|
-
|
118
|
+
struct3 = struct2.merge(top: "newer", bottom: "very")
|
119
|
+
struct3.top.should == "newer"
|
120
|
+
struct3.bottom.should == "very"
|
121
|
+
end
|
111
122
|
|
112
|
-
|
113
|
-
|
123
|
+
it "can merge-in Hamster::Hash" do
|
124
|
+
struct = struct_class.new(top: 10, bottom: 1)
|
114
125
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
end
|
126
|
+
struct2 = struct.merge(Hamster.hash(bottom: "newer", top: "newest"))
|
127
|
+
struct2.top.should == "newest"
|
128
|
+
struct2.bottom.should == "newer"
|
119
129
|
|
120
|
-
|
121
|
-
|
130
|
+
struct.top.should == 10
|
131
|
+
struct.bottom.should == 1
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
describe "inspect and to_s" do
|
136
|
+
module Hamstest
|
137
|
+
Wheel = Hamsterdam::Struct.define(:x,:y,:radius,:label)
|
138
|
+
Vehicle = Hamsterdam::Struct.define(:wheels, :body_style)
|
139
|
+
Thinger = Hamsterdam::Struct.define(:a_hash, :a_set, :a_list)
|
140
|
+
end
|
122
141
|
|
123
|
-
struct2 = struct.merge(Hamster.hash(bottom: "newer", top: "newest"))
|
124
|
-
struct2.top.should == "newest"
|
125
|
-
struct2.bottom.should == "newer"
|
126
142
|
|
127
|
-
|
128
|
-
|
129
|
-
|
143
|
+
it "generates a nice clear string representation of the internal data" do
|
144
|
+
wheel = Hamstest::Wheel.new x: 50, y: 100, radius: 5.0, label: "front"
|
145
|
+
expected = "<Wheel x: 50 y: 100 radius: 5.0 label: \"front\">"
|
146
|
+
wheel.inspect.should == expected
|
147
|
+
wheel.to_s.should == expected
|
130
148
|
end
|
131
149
|
|
150
|
+
it "does a nice job with other Hamsterdam structs" do
|
151
|
+
wheel1 = Hamstest::Wheel.new x: 50, y: 100, radius: 5.0, label: "front"
|
152
|
+
wheel2 = Hamstest::Wheel.new x: 100, y: 100, radius: 5.0, label: "back"
|
153
|
+
car = Hamstest::Vehicle.new wheels: Hamster.list(wheel1, wheel2), body_style: "sedan"
|
154
|
+
expected = "<Vehicle wheels: [<Wheel x: 50 y: 100 radius: 5.0 label: \"front\">, <Wheel x: 100 y: 100 radius: 5.0 label: \"back\">] body_style: \"sedan\">"
|
155
|
+
car.inspect.should == expected
|
156
|
+
car.to_s.should == expected
|
157
|
+
end
|
158
|
+
|
159
|
+
it "does a nice job with Hamster Lists, Sets, and Hashes" do
|
160
|
+
thinger = Hamstest::Thinger.new a_hash: Hamster.hash(red: "fish"), a_set: Hamster.set(42,37), a_list: Hamster.list(:oh, :the, :things)
|
161
|
+
expected = "<Thinger a_hash: {:red => \"fish\"} a_set: {42, 37} a_list: [:oh, :the, :things]>"
|
162
|
+
thinger.inspect.should == expected
|
163
|
+
thinger.to_s.should == expected
|
164
|
+
end
|
132
165
|
end
|
133
166
|
end
|