safestruct 1.2.0 → 1.2.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.
- checksums.yaml +4 -4
- data/Rakefile +1 -1
- data/lib/safestruct.rb +20 -3
- data/lib/safestruct/safe_array.rb +22 -11
- data/lib/safestruct/safe_hash.rb +26 -13
- data/lib/safestruct/safe_struct.rb +8 -4
- data/lib/safestruct/version.rb +10 -3
- data/test/test_hash.rb +19 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f085259a240f99941fe60eef6a271a6066e649d3
|
4
|
+
data.tar.gz: a289d416c0ade1aa76eae8e0c897fac7b63e6700
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a71c903f7ecddfe2a42c48465f7a76969db5566e7d0cdf18bf53878f5bad067c7b7e86029a1516e5515124547a6ce5a2c9badc36f84e1a1ca05cb6fcd049e65
|
7
|
+
data.tar.gz: aade5b05f5666e89204cd5b95a4561829d7f70bae9380a7d204013527bdd03e21757c9f30f379c74f5ced2b558e25b702ccf1cbcaa13cd2d4e9df71c833688fb
|
data/Rakefile
CHANGED
@@ -3,7 +3,7 @@ require './lib/safestruct/version.rb'
|
|
3
3
|
|
4
4
|
Hoe.spec 'safestruct' do
|
5
5
|
|
6
|
-
self.version =
|
6
|
+
self.version = SaferStruct::VERSION
|
7
7
|
|
8
8
|
self.summary = "safestruct - safe data structures (array, hash, struct) - say goodbye to null / nil (and maybe) - say hello to zero"
|
9
9
|
self.description = summary
|
data/lib/safestruct.rb
CHANGED
@@ -19,19 +19,31 @@ require 'safestruct/safe_struct'
|
|
19
19
|
####################################
|
20
20
|
## add zero/zero_new machinery for builin classes
|
21
21
|
|
22
|
-
|
22
|
+
#########################
|
23
|
+
#### with value semantics
|
23
24
|
class Integer
|
24
25
|
def self.zero() 0; end ## note: 0.frozen? == true by default
|
26
|
+
def zero?() self == self.class.zero; end
|
25
27
|
end
|
26
28
|
|
27
29
|
class Bool
|
28
30
|
def self.zero() false; end ## note: false.frozen? == true by default
|
29
31
|
end
|
30
32
|
|
31
|
-
|
33
|
+
class TrueClass # note: ruby has no builtin/default bool (base) class only TrueClass|FalseClass
|
34
|
+
def zero?() false; end
|
35
|
+
end
|
36
|
+
|
37
|
+
class FalseClass
|
38
|
+
def zero?() true; end
|
39
|
+
end
|
40
|
+
|
41
|
+
##################
|
42
|
+
#### with reference semantics (new copy ALWAYS needed)
|
32
43
|
class String
|
33
44
|
def self.new_zero() new; end
|
34
45
|
def self.zero() @zero ||= new_zero.freeze; end
|
46
|
+
def zero?() self == self.class.zero; end
|
35
47
|
end
|
36
48
|
|
37
49
|
|
@@ -90,9 +102,14 @@ module Safe
|
|
90
102
|
def struct( class_name, **attributes )
|
91
103
|
SafeStruct.new( class_name, attributes )
|
92
104
|
end
|
105
|
+
|
106
|
+
### note: do NOT add helpers for
|
107
|
+
## - hash( class_name, ...) and
|
108
|
+
## - array( class_name, ...) for now
|
109
|
+
## why? why not? needs more testing/considerations for overloading / breaking builtin defaults
|
93
110
|
end # module ClassMethods
|
94
111
|
end # module Safe
|
95
112
|
|
96
113
|
|
97
114
|
|
98
|
-
puts
|
115
|
+
puts SaferStruct.banner ## say hello
|
@@ -18,14 +18,23 @@ class SafeArray
|
|
18
18
|
if klass.nil?
|
19
19
|
|
20
20
|
klass = Class.new( SafeArray )
|
21
|
-
klass.
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
klass.define_singleton_method( :klass_value ) do
|
22
|
+
@klass_value ||= klass_value
|
23
|
+
end
|
24
|
+
klass.define_singleton_method( :klass_size ) do
|
25
|
+
@klass_size ||= size
|
26
|
+
end
|
27
|
+
|
28
|
+
##### was: not working for anymous class e.g. klass_value.to_s => #<Class:>
|
29
|
+
# klass.class_eval( <<RUBY )
|
30
|
+
# def self.klass_value
|
31
|
+
# @klass_value ||= #{klass_value}
|
32
|
+
# end
|
33
|
+
# def self.klass_size
|
34
|
+
# @klass_size ||= #{size}
|
35
|
+
# end
|
36
|
+
# RUBY
|
37
|
+
|
29
38
|
## add to cache for later (re)use
|
30
39
|
cache[ klass_value ][ size ] = klass
|
31
40
|
end
|
@@ -36,6 +45,8 @@ RUBY
|
|
36
45
|
def self.new_zero() new; end
|
37
46
|
def self.zero() @zero ||= new_zero.freeze; end
|
38
47
|
|
48
|
+
def zero?() self == self.class.zero; end
|
49
|
+
|
39
50
|
|
40
51
|
def initialize( size=self.class.klass_size )
|
41
52
|
@ary = []
|
@@ -71,11 +82,11 @@ RUBY
|
|
71
82
|
## note: use a new unfrozen copy of the zero object
|
72
83
|
## changes to the object MUST be possible (new "empty" modifable object expected)
|
73
84
|
diff.times { @ary << self.class.klass_value.new_zero }
|
74
|
-
|
85
|
+
else # assume value semantics e.g. Integer, Bool, etc. zero values gets replaced
|
75
86
|
## puts "use value semantics"
|
76
87
|
diff.times { @ary << self.class.klass_value.zero }
|
77
|
-
|
78
|
-
|
88
|
+
end
|
89
|
+
self # return reference to self
|
79
90
|
end
|
80
91
|
alias_method :'length=', :'size='
|
81
92
|
|
data/lib/safestruct/safe_hash.rb
CHANGED
@@ -26,6 +26,7 @@ class SafeHash
|
|
26
26
|
if debug?
|
27
27
|
puts "[debug] SafeHash - build_class klass_value:"
|
28
28
|
pp klass_value
|
29
|
+
pp klass_value.to_s ## note: for "anonymous" class something like #<Class:>
|
29
30
|
end
|
30
31
|
|
31
32
|
if klass.nil?
|
@@ -34,14 +35,24 @@ class SafeHash
|
|
34
35
|
end
|
35
36
|
|
36
37
|
klass = Class.new( SafeHash )
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
|
39
|
+
klass.define_singleton_method( :klass_key ) do
|
40
|
+
@klass_key ||= klass_key
|
41
|
+
end
|
42
|
+
klass.define_singleton_method( :klass_value ) do
|
43
|
+
@klass_value ||= klass_value
|
44
|
+
end
|
45
|
+
|
46
|
+
### was: - NOT working for "anonymous" classes e.g. klass_value.to_s starting with #<Class:>
|
47
|
+
# klass.class_eval( <<RUBY )
|
48
|
+
# def self.klass_key
|
49
|
+
# @klass_key ||= #{klass_key}
|
50
|
+
# end
|
51
|
+
# def self.klass_value
|
52
|
+
# @klass_value ||= #{klass_value}
|
53
|
+
# end
|
54
|
+
# RUBY
|
55
|
+
|
45
56
|
## add to cache for later (re)use
|
46
57
|
cache[ klass_value ] = klass
|
47
58
|
else
|
@@ -58,6 +69,8 @@ RUBY
|
|
58
69
|
def self.new_zero() new; end
|
59
70
|
def self.zero() @zero ||= new_zero.freeze; end
|
60
71
|
|
72
|
+
def zero?() self == self.class.zero; end
|
73
|
+
|
61
74
|
|
62
75
|
def initialize
|
63
76
|
## todo/check: if hash works if value is a (nested) hash
|
@@ -100,11 +113,11 @@ RUBY
|
|
100
113
|
if self.class.klass_value.respond_to?( :new_zero )
|
101
114
|
## note: use a dup(licated) unfrozen copy of the zero object
|
102
115
|
## changes to the object MUST be possible (new "empty" modifable object expected)
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
116
|
+
item = @h[ key ] = self.class.klass_value.new_zero
|
117
|
+
else # assume value semantics e.g. Integer, Bool, etc. zero values gets replaced
|
118
|
+
## puts "use value semantics"
|
119
|
+
item = @h[ key ] = self.class.klass_value.zero
|
120
|
+
end
|
108
121
|
end
|
109
122
|
item
|
110
123
|
end
|
@@ -21,7 +21,7 @@ def self.build_class( class_name, **attributes )
|
|
21
21
|
## check if valid class_name MUST start with uppercase letter etc.
|
22
22
|
## todo/fix: check if constant is undefined in Safe namespace!!!!
|
23
23
|
|
24
|
-
|
24
|
+
|
25
25
|
klass = Class.new( SafeStruct ) do
|
26
26
|
define_method( :initialize ) do |*args|
|
27
27
|
attributes.keys.zip( args ).each do |key, arg|
|
@@ -100,13 +100,13 @@ def self.build_class( class_name, **attributes )
|
|
100
100
|
end
|
101
101
|
|
102
102
|
|
103
|
-
## note: use
|
103
|
+
## note: use Kernel for "namespacing"
|
104
104
|
## make all enums convenience converters (always) global
|
105
105
|
## including uppercase methods (e.g. State(), Color(), etc.) does NOT work otherwise (with other module includes)
|
106
106
|
|
107
|
-
## add global convenience converter function
|
107
|
+
## add global "Kernel" convenience converter function
|
108
108
|
## e.g. Vote(0) is same as Vote.convert(0)
|
109
|
-
|
109
|
+
Kernel.class_eval( <<RUBY )
|
110
110
|
def #{class_name}( arg )
|
111
111
|
#{class_name}.convert( arg )
|
112
112
|
end
|
@@ -130,5 +130,9 @@ def self.zero
|
|
130
130
|
## freeze only works for now for "value" objects e.g. integer, bool, etc.
|
131
131
|
@zero ||= new_zero.freeze
|
132
132
|
end
|
133
|
+
|
134
|
+
def zero?() self == self.class.zero; end
|
135
|
+
|
136
|
+
|
133
137
|
end # class SafeStruct
|
134
138
|
end # module Safe
|
data/lib/safestruct/version.rb
CHANGED
@@ -1,11 +1,18 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
|
4
|
-
|
4
|
+
###
|
5
|
+
# note: do not "pollute" Safe namespace / module
|
6
|
+
# use its own module
|
7
|
+
#
|
8
|
+
# note: SafeStruct is already taken :-), thus, use SaferStruct
|
9
|
+
|
10
|
+
|
11
|
+
module SaferStruct
|
5
12
|
|
6
13
|
MAJOR = 1
|
7
14
|
MINOR = 2
|
8
|
-
PATCH =
|
15
|
+
PATCH = 1
|
9
16
|
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
10
17
|
|
11
18
|
def self.version
|
@@ -20,4 +27,4 @@ module Safe
|
|
20
27
|
"#{File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )}"
|
21
28
|
end
|
22
29
|
|
23
|
-
end # module
|
30
|
+
end # module SaferStruct
|
data/test/test_hash.rb
CHANGED
@@ -23,6 +23,20 @@ class TestHash < MiniTest::Test
|
|
23
23
|
## nested e.g. String => (String => Integer)
|
24
24
|
Hash_Hash_X_Integer = SafeHash.build_class( String, Hash_X_Integer )
|
25
25
|
|
26
|
+
SafeStruct.new( :Game123, host: '',
|
27
|
+
challenger: '',
|
28
|
+
turn: '')
|
29
|
+
|
30
|
+
def test_hash_of_hash
|
31
|
+
## note: use Game123 (with unique/unused name)
|
32
|
+
## for testing an "anonymous" hash class (e.g. without a class name)
|
33
|
+
h = Hash.of( String => Hash.of( String => Game123 ))
|
34
|
+
pp h
|
35
|
+
h2 = Hash.of( String => Hash.of( String => Game123 ))
|
36
|
+
pp h2
|
37
|
+
assert true
|
38
|
+
end
|
39
|
+
|
26
40
|
|
27
41
|
def test_integer
|
28
42
|
pp Hash_X_Integer
|
@@ -39,6 +53,11 @@ def test_integer
|
|
39
53
|
assert_equal true, Hash_X_Integer.zero == Hash_X_Integer.new
|
40
54
|
assert_equal true, Hash_X_Integer.zero == Hash_X_Integer.new_zero
|
41
55
|
|
56
|
+
assert_equal true, h.zero?
|
57
|
+
assert_equal true, Hash_X_Integer.zero.zero?
|
58
|
+
assert_equal true, Hash_X_Integer.new.zero?
|
59
|
+
assert_equal true, Hash_X_Integer.new_zero.zero?
|
60
|
+
|
42
61
|
pp Hash_X_Integer.zero
|
43
62
|
assert_equal true, Hash_X_Integer.zero.frozen?
|
44
63
|
assert_equal false, Hash_X_Integer.new.frozen?
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: safestruct
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.2.
|
4
|
+
version: 1.2.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-03-
|
11
|
+
date: 2019-03-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: enums
|