hamsterdam 1.0.0 → 1.0.1
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/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
|