hash_initialized_struct 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hash_initialized_struct/version.rb +1 -1
- data/lib/hash_initialized_struct.rb +28 -10
- data/spec/hash_initialized_struct_spec.rb +28 -13
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0a019905cb0578ccd137f19e03bc4506c4394d70
|
4
|
+
data.tar.gz: d995895f24be535e41f72b7c55d8f074b05dbf66
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaa60f77a463b145fe836d23b06b1953ef64959a99b78e14c603280de7e655b482c5abcca48e2ceb921cd2ed8cae716fbadcc3417c4744426e80fd3b86d1bea8
|
7
|
+
data.tar.gz: 9c3990737ae43394e9ea0f2d3ea8c7fe186b3165c3718edc3568f894d3cae8a5517cdc000cf4a230610b34c97cf5bfeadf308d11232ed5c274cd4ba271271a4b
|
@@ -35,16 +35,10 @@ class HashInitializedStruct
|
|
35
35
|
|
36
36
|
def initialize(attrs)
|
37
37
|
provided = attrs.keys
|
38
|
-
needed =
|
39
|
-
(provided
|
40
|
-
|
41
|
-
|
42
|
-
(needed - provided).tap do |missing|
|
43
|
-
raise ArgumentError, "Missing keys: #{missing.map(&:inspect).join(', ')}" unless missing.empty?
|
44
|
-
end
|
45
|
-
attrs.each do |attr,value|
|
46
|
-
instance_variable_set("@#{attr}", value)
|
47
|
-
end
|
38
|
+
needed = needed_keys
|
39
|
+
self.raise_on_unrecognised_keys(provided, needed)
|
40
|
+
self.raise_on_missing_keys(provided, needed)
|
41
|
+
set_attributes(attrs)
|
48
42
|
end
|
49
43
|
|
50
44
|
def to_h
|
@@ -52,6 +46,30 @@ class HashInitializedStruct
|
|
52
46
|
Hash[ self.class::STRUCT_ATTRS.map {|key| [key, self.public_send(key)]} ]
|
53
47
|
end
|
54
48
|
alias :to_hash :to_h
|
49
|
+
|
50
|
+
protected
|
51
|
+
|
52
|
+
def needed_keys
|
53
|
+
self.class::STRUCT_ATTRS
|
54
|
+
end
|
55
|
+
|
56
|
+
def raise_on_unrecognised_keys(provided, needed)
|
57
|
+
(provided - needed).tap do |unknown|
|
58
|
+
raise ArgumentError, "Unrecognised keys: #{unknown.map(&:inspect).join(', ')}" unless unknown.empty?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def raise_on_missing_keys(provided, needed)
|
63
|
+
(needed - provided).tap do |missing|
|
64
|
+
raise ArgumentError, "Missing keys: #{missing.map(&:inspect).join(', ')}" unless missing.empty?
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def set_attributes(attrs)
|
69
|
+
attrs.each do |attr,value|
|
70
|
+
instance_variable_set("@#{attr}", value)
|
71
|
+
end
|
72
|
+
end
|
55
73
|
end
|
56
74
|
end
|
57
75
|
end
|
@@ -46,23 +46,38 @@ describe "HashInitializedStruct" do
|
|
46
46
|
expect(point.to_h).to eq Hash(point) # to_h == to_hash
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
49
|
+
describe "overriding the constructor" do
|
50
|
+
it "allows additional checks" do
|
51
|
+
# Could do this with an anonymous class and define_method, but we're trying to emulate
|
52
|
+
# how it might actually be used.
|
53
|
+
class My3DPoint < HashInitializedStruct.new(:x, :y, :z)
|
54
|
+
def initialize(attrs)
|
55
|
+
super
|
56
|
+
[x, y, z].each do |attr|
|
57
|
+
raise ArgumentError, "#{attr} must be a number" unless attr.kind_of?(Numeric)
|
58
|
+
end
|
57
59
|
end
|
58
60
|
end
|
61
|
+
|
62
|
+
good = My3DPoint.new(x: 1, y: 2, z: 9)
|
63
|
+
expect(good.x).to eq 1
|
64
|
+
|
65
|
+
expect {
|
66
|
+
My3DPoint.new(x: "1", y: nil, z: 9)
|
67
|
+
}.to raise_error(ArgumentError)
|
59
68
|
end
|
60
69
|
|
61
|
-
|
62
|
-
|
70
|
+
it "allows partial checks" do
|
71
|
+
class MyOptionally4DPoint < HashInitializedStruct.new(:x, :y, :z, :t)
|
72
|
+
def initialize(attrs)
|
73
|
+
provided = attrs.keys
|
74
|
+
raise_on_unrecognised_keys(provided, needed_keys)
|
75
|
+
set_attributes
|
76
|
+
end
|
77
|
+
end
|
63
78
|
|
64
|
-
|
65
|
-
|
66
|
-
|
79
|
+
good = My3DPoint.new(x: 1, y: 2, z: 9) # Missing :t
|
80
|
+
expect(good.x).to eq 1
|
81
|
+
end
|
67
82
|
end
|
68
83
|
end
|