lab42_data_class 0.7.1 → 0.7.2
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/lib/lab42/data_class/builtin_constraints.rb +14 -0
- data/lib/lab42/data_class/constraint.rb +30 -0
- data/lib/lab42/data_class/constraints/kernel.rb +86 -0
- data/lib/lab42/data_class/proxy/constraints/maker.rb +11 -4
- data/lib/lab42/data_class/proxy.rb +35 -7
- data/lib/lab42/data_class/version.rb +1 -1
- metadata +8 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 746ce73ef4464de258f683f0d8366f15799cb8e3ea34a062cc6f4deb34f0a60d
|
4
|
+
data.tar.gz: 96c679474b72b872f4885ab2c98f7ddfd5f914268b3a9da5ba59f7ae026e5eed
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 184dc66df2185e0869a5cbce9811c8bedf685123037fadf8d17c30bfd762884b9f0d0756bc0d43787dce2586c8094bb2a798aba9b54087198b59a1a0d95023c0
|
7
|
+
data.tar.gz: 859c555137b976c4885157c5b39d42393c528adf94abb3dd28b9cbd3e38625d3bccac9b5cf5e317cdf3dddb08494fa989dd11523902f79402ed915822d616a64
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "lab42/data_class"
|
4
|
+
module Lab42
|
5
|
+
module DataClass
|
6
|
+
class Constraint
|
7
|
+
attr_reader :name, :function
|
8
|
+
|
9
|
+
def call(value)
|
10
|
+
function.(value)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_s
|
14
|
+
"Constraint<#{name}>"
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
def initialize(name:, function:)
|
19
|
+
raise ArgumentError, "name not a String, but #{name}" unless String === name
|
20
|
+
unless function.respond_to?(:arity) && function.arity == 1
|
21
|
+
raise ArgumentError, "function not a callable with arity 1 #{function}"
|
22
|
+
end
|
23
|
+
|
24
|
+
@name = name
|
25
|
+
@function = function
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# SPDX-License-Identifier: Apache-2.0
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Kernel
|
4
|
+
Constraint = Lab42::DataClass::Constraint
|
5
|
+
Maker = Lab42::DataClass::Proxy::Constraints::Maker # TODO: Move Maker to Lab42::DataClass:ConstraintMaker
|
6
|
+
Anything = Constraint.new(name: "Anything", function: ->(_) { true })
|
7
|
+
Boolean = Constraint.new(name: "Boolean", function: -> { [false, true].member?(_1) })
|
8
|
+
|
9
|
+
def All?(constraint = nil, &blk)
|
10
|
+
constraint = Maker.make_constraint(constraint, &blk)
|
11
|
+
f = -> do
|
12
|
+
_1.all?(&constraint)
|
13
|
+
end
|
14
|
+
Constraint.new(name: "All?(#{constraint})", function: f)
|
15
|
+
end
|
16
|
+
|
17
|
+
def Any?(constraint = nil, &blk)
|
18
|
+
constraint = Maker.make_constraint(constraint, &blk)
|
19
|
+
f = -> do
|
20
|
+
_1.any?(&constraint)
|
21
|
+
end
|
22
|
+
Constraint.new(name: "Any?(#{constraint})", function: f)
|
23
|
+
end
|
24
|
+
|
25
|
+
def Choice(*constraints)
|
26
|
+
constraints = constraints.map{ Maker.make_constraint _1 }
|
27
|
+
f = ->(value) do
|
28
|
+
constraints.any?{ _1.(value) }
|
29
|
+
end
|
30
|
+
Constraint.new(name: "Choice(#{constraints.join(', ')})", function: f)
|
31
|
+
end
|
32
|
+
|
33
|
+
def Contains(str)
|
34
|
+
f = -> { _1.include?(str) rescue false }
|
35
|
+
Constraint.new(name: "Contains(#{str})", function: f)
|
36
|
+
end
|
37
|
+
|
38
|
+
def EndsWith(str)
|
39
|
+
f = -> { _1.end_with?(str) rescue false }
|
40
|
+
Constraint.new(name: "EndsWith(#{str})", function: f)
|
41
|
+
end
|
42
|
+
|
43
|
+
def Lambda(arity)
|
44
|
+
f = -> do
|
45
|
+
_1.arity == arity rescue false
|
46
|
+
end
|
47
|
+
Constraint.new(name: "Lambda(#{arity})", function: f)
|
48
|
+
end
|
49
|
+
|
50
|
+
def NilOr(constraint = nil, &blk)
|
51
|
+
constraint = Maker.make_constraint(constraint, &blk)
|
52
|
+
f = -> { _1.nil? || constraint.(_1) }
|
53
|
+
Constraint.new(name: "NilOr(#{constraint})", function: f)
|
54
|
+
end
|
55
|
+
|
56
|
+
def Not(constraint = nil, &blk)
|
57
|
+
constraint = Maker.make_constraint(constraint, &blk)
|
58
|
+
f = -> { !constraint.(_1) }
|
59
|
+
Constraint.new(name: "Not(#{constraint})", function: f)
|
60
|
+
end
|
61
|
+
|
62
|
+
def PairOf(fst, snd)
|
63
|
+
fst_constraint = Maker.make_constraint(fst)
|
64
|
+
snd_constraint = Maker.make_constraint(snd)
|
65
|
+
f = -> do
|
66
|
+
Lab42::Pair === _1 && fst_constraint.(_1.first) && snd_constraint.(_1.second)
|
67
|
+
end
|
68
|
+
Constraint.new(name: "PairOf(#{fst_constraint}, #{snd_constraint})", function: f)
|
69
|
+
end
|
70
|
+
|
71
|
+
def StartsWith(str)
|
72
|
+
f = -> { _1.start_with?(str) rescue false }
|
73
|
+
Constraint.new(name: "StartsWith(#{str})", function: f)
|
74
|
+
end
|
75
|
+
|
76
|
+
def TripleOf(fst, snd, trd)
|
77
|
+
fst_constraint = Maker.make_constraint(fst)
|
78
|
+
snd_constraint = Maker.make_constraint(snd)
|
79
|
+
trd_constraint = Maker.make_constraint(trd)
|
80
|
+
f = -> do
|
81
|
+
Lab42::Triple === _1 && fst_constraint.(_1.first) && snd_constraint.(_1.second) && trd_constraint.(_1.third)
|
82
|
+
end
|
83
|
+
Constraint.new(name: "TripleOf(#{fst_constraint}, #{snd_constraint}, #{trd_constraint})", function: f)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
# SPDX-License-Identifier: Apache-2.0
|
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require "lab42/data_class/constraint"
|
3
4
|
module Lab42
|
4
5
|
module DataClass
|
5
6
|
class Proxy
|
@@ -7,9 +8,17 @@ module Lab42
|
|
7
8
|
module Maker
|
8
9
|
extend self
|
9
10
|
|
10
|
-
def make_constraint(constraint)
|
11
|
+
def make_constraint(constraint, &blk)
|
12
|
+
raise ArgumentError, "must not pass a callable #{constraint} and a block" if constraint && blk
|
13
|
+
|
14
|
+
_make_constraint(constraint || blk)
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def _make_constraint(constraint)
|
11
20
|
case constraint
|
12
|
-
when Proc, Method
|
21
|
+
when Lab42::DataClass::Constraint, Proc, Method
|
13
22
|
constraint
|
14
23
|
when Symbol
|
15
24
|
-> { _1.send(constraint) }
|
@@ -26,8 +35,6 @@ module Lab42
|
|
26
35
|
end
|
27
36
|
end
|
28
37
|
|
29
|
-
private
|
30
|
-
|
31
38
|
def _make_member_constraint(constraint)
|
32
39
|
if constraint.respond_to?(:member?)
|
33
40
|
-> { constraint.member?(_1) }
|
@@ -30,12 +30,11 @@ module Lab42
|
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
|
-
def check!(
|
34
|
-
@actual_params = params
|
33
|
+
def check!(params, merge_with = defaults)
|
35
34
|
raise ArgumentError, "missing initializers for #{_missing_initializers}" unless _missing_initializers.empty?
|
36
35
|
raise ArgumentError, "illegal initializers #{_illegal_initializers}" unless _illegal_initializers.empty?
|
37
36
|
|
38
|
-
_check_constraints!(
|
37
|
+
_check_constraints!(merge_with.merge(params))
|
39
38
|
end
|
40
39
|
|
41
40
|
def define_class!
|
@@ -63,6 +62,10 @@ module Lab42
|
|
63
62
|
_init(data_class, defaults.merge(params))
|
64
63
|
end
|
65
64
|
|
65
|
+
def set_actual_params(params)
|
66
|
+
@actual_params = params
|
67
|
+
end
|
68
|
+
|
66
69
|
def to_hash(data_class_instance)
|
67
70
|
all_attributes
|
68
71
|
.inject({}) { |result, (k, _)| result.merge(k => data_class_instance[k]) }
|
@@ -96,15 +99,40 @@ module Lab42
|
|
96
99
|
|
97
100
|
def _define_derived_attribute(name, &blk)
|
98
101
|
->(*) do
|
102
|
+
if instance_methods.include?(name)
|
103
|
+
begin
|
104
|
+
remove_method(name)
|
105
|
+
rescue StandardError
|
106
|
+
nil
|
107
|
+
end
|
108
|
+
end
|
99
109
|
define_method(name) { blk.call(self) }
|
100
110
|
end
|
101
111
|
end
|
102
112
|
|
103
113
|
def _define_freezing_constructor
|
114
|
+
proxy = self
|
115
|
+
->(*) do
|
116
|
+
define_method :new do |**params, &b|
|
117
|
+
allocate.tap do |o|
|
118
|
+
proxy.set_actual_params(params)
|
119
|
+
proxy.check!(params)
|
120
|
+
o.send(:initialize, **params, &b)
|
121
|
+
end.freeze
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def _define_merging_constructor
|
127
|
+
proxy = self
|
104
128
|
->(*) do
|
105
|
-
define_method :
|
106
|
-
|
129
|
+
define_method :_new_from_merge do |new_params, params|
|
130
|
+
allocate.tap do |o|
|
131
|
+
proxy.check!(new_params, {})
|
132
|
+
o.send(:initialize, **params)
|
133
|
+
end.freeze
|
107
134
|
end
|
135
|
+
private :_new_from_merge
|
108
136
|
end
|
109
137
|
end
|
110
138
|
|
@@ -112,7 +140,6 @@ module Lab42
|
|
112
140
|
proxy = self
|
113
141
|
->(*) do
|
114
142
|
define_method :initialize do |**params|
|
115
|
-
proxy.check!(**params)
|
116
143
|
proxy.init(self, **params)
|
117
144
|
proxy.validate!(self)
|
118
145
|
end
|
@@ -123,7 +150,7 @@ module Lab42
|
|
123
150
|
->(*) do
|
124
151
|
define_method :merge do |**params|
|
125
152
|
values = to_h.merge(params)
|
126
|
-
self.class.
|
153
|
+
self.class.send(:_new_from_merge, params, values)
|
127
154
|
end
|
128
155
|
end
|
129
156
|
end
|
@@ -137,6 +164,7 @@ module Lab42
|
|
137
164
|
|
138
165
|
def _define_singleton_methods(singleton)
|
139
166
|
singleton.module_eval(&_define_freezing_constructor)
|
167
|
+
singleton.module_eval(&_define_merging_constructor)
|
140
168
|
singleton.module_eval(&_define_to_proc)
|
141
169
|
singleton.module_eval(&_define_with_constraint)
|
142
170
|
singleton.module_eval(&_define_derived)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lab42_data_class
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.7.
|
4
|
+
version: 0.7.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Dober
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
An Immutable DataClass for Ruby
|
@@ -24,7 +24,10 @@ files:
|
|
24
24
|
- LICENSE
|
25
25
|
- README.md
|
26
26
|
- lib/lab42/data_class.rb
|
27
|
+
- lib/lab42/data_class/builtin_constraints.rb
|
28
|
+
- lib/lab42/data_class/constraint.rb
|
27
29
|
- lib/lab42/data_class/constraint_error.rb
|
30
|
+
- lib/lab42/data_class/constraints/kernel.rb
|
28
31
|
- lib/lab42/data_class/duplicate_definition_error.rb
|
29
32
|
- lib/lab42/data_class/kernel.rb
|
30
33
|
- lib/lab42/data_class/proxy.rb
|
@@ -44,7 +47,7 @@ homepage: https://github.com/robertdober/lab42_data_class
|
|
44
47
|
licenses:
|
45
48
|
- Apache-2.0
|
46
49
|
metadata: {}
|
47
|
-
post_install_message:
|
50
|
+
post_install_message:
|
48
51
|
rdoc_options: []
|
49
52
|
require_paths:
|
50
53
|
- lib
|
@@ -60,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
63
|
version: '0'
|
61
64
|
requirements: []
|
62
65
|
rubygems_version: 3.3.3
|
63
|
-
signing_key:
|
66
|
+
signing_key:
|
64
67
|
specification_version: 4
|
65
68
|
summary: Finally a dataclass in ruby
|
66
69
|
test_files: []
|