lab42_data_class 0.7.1 → 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|