ree_lib 1.0.68 → 1.0.70
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/Gemfile.lock +4 -4
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/association.rb +26 -31
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/association_methods.rb +11 -16
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/associations.rb +7 -9
- data/lib/ree_lib/packages/ree_dao/package/ree_dao/functions/agg.rb +6 -20
- data/lib/ree_lib/packages/ree_dao/schemas/ree_dao/functions/agg.schema.json +2 -17
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/agg_benchmark_spec.rb +5 -5
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/agg_spec.rb +9 -9
- data/lib/ree_lib/packages/ree_dao/spec/ree_dao/functions/load_agg/ree_dao_agg_test.rb +4 -4
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/contractable.rb +2 -2
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/dsl.rb +33 -27
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/enumerable.rb +20 -32
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/value.rb +18 -33
- data/lib/ree_lib/packages/ree_enum/package/ree_enum/values.rb +44 -18
- data/lib/ree_lib/packages/ree_enum/spec/ree_enum/dsl_spec.rb +19 -8
- data/lib/ree_lib/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 40e7e6a91b65f1bab58b667f1eebf153ac5fd1c85852e189af8d3a6d2ea8b163
|
4
|
+
data.tar.gz: 5ac2658d206e2aa8963fd90ed4ca4ef071b701a0d02414d571dcc95df825a88e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 221b1612a9ddc52b73f6cd34a1f1228009a3459646d0f129281d5c4ae16557e1044359cb13e44085bf1e727ae07ce3be7cfae9e1728fae8260ed42f888a52010
|
7
|
+
data.tar.gz: e296d1413246f6813ec865ae1395eec11f71f2066d755d815ccac8a260278f122c20e6ca0c680204245a693aa9668dfaab46c0187e25e51288be6c4d523c5e7a
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ree_lib (1.0.
|
4
|
+
ree_lib (1.0.70)
|
5
5
|
binding_of_caller (~> 1.0.0)
|
6
6
|
i18n (~> 1.12.0)
|
7
7
|
loofah (~> 2.18.0)
|
@@ -37,10 +37,10 @@ GEM
|
|
37
37
|
loofah (2.18.0)
|
38
38
|
crass (~> 1.0.2)
|
39
39
|
nokogiri (>= 1.5.9)
|
40
|
-
mini_portile2 (2.8.1)
|
41
40
|
msgpack (1.6.0)
|
42
|
-
nokogiri (1.
|
43
|
-
|
41
|
+
nokogiri (1.15.4-x86_64-darwin)
|
42
|
+
racc (~> 1.4)
|
43
|
+
nokogiri (1.15.4-x86_64-linux)
|
44
44
|
racc (~> 1.4)
|
45
45
|
oj (3.13.23)
|
46
46
|
pg (1.4.6)
|
@@ -8,12 +8,12 @@ module ReeDao
|
|
8
8
|
link :index_by, from: :ree_array
|
9
9
|
link :underscore, from: :ree_string
|
10
10
|
|
11
|
-
attr_reader :parent, :
|
11
|
+
attr_reader :parent, :parent_dao, :list, :global_opts
|
12
12
|
|
13
|
-
contract(ReeDao::Associations,
|
14
|
-
def initialize(parent,
|
13
|
+
contract(ReeDao::Associations, Sequel::Dataset, Array, Ksplat[RestKeys => Any] => Any)
|
14
|
+
def initialize(parent, parent_dao, list, **global_opts)
|
15
15
|
@parent = parent
|
16
|
-
@
|
16
|
+
@parent_dao = parent_dao
|
17
17
|
@list = list
|
18
18
|
@global_opts = global_opts
|
19
19
|
end
|
@@ -36,7 +36,7 @@ module ReeDao
|
|
36
36
|
Or[:belongs_to, :has_one, :has_many],
|
37
37
|
Symbol,
|
38
38
|
Ksplat[RestKeys => Any],
|
39
|
-
Optblock =>
|
39
|
+
Optblock => Array
|
40
40
|
)
|
41
41
|
def load_association(assoc_type, assoc_name, **__opts, &block)
|
42
42
|
__opts[:autoload_children] ||= false
|
@@ -47,21 +47,17 @@ module ReeDao
|
|
47
47
|
**__opts
|
48
48
|
)
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
dao_name = if dao
|
53
|
-
dao.first_source_table
|
54
|
-
elsif __opts[:scope].is_a?(Array)
|
55
|
-
name = underscore(demodulize(__opts[:scope].first.class.name))
|
50
|
+
scope = __opts[:scope]
|
56
51
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
52
|
+
dao = if scope.is_a?(Array)
|
53
|
+
return [] if scope.empty?
|
54
|
+
name = underscore(demodulize(scope.first.class.name))
|
55
|
+
find_dao(name, parent, nil)
|
56
|
+
else
|
57
|
+
find_dao(assoc_name, parent, scope)
|
62
58
|
end
|
63
59
|
|
64
|
-
process_block(assoc_index, __opts[:autoload_children], __opts[:to_dto],
|
60
|
+
process_block(assoc_index, __opts[:autoload_children], __opts[:to_dto], dao, &block) if block_given?
|
65
61
|
|
66
62
|
list
|
67
63
|
end
|
@@ -75,7 +71,7 @@ module ReeDao
|
|
75
71
|
case type
|
76
72
|
when :belongs_to
|
77
73
|
one_to_one(
|
78
|
-
|
74
|
+
parent_dao,
|
79
75
|
assoc_name,
|
80
76
|
list,
|
81
77
|
scope: __opts[:scope],
|
@@ -86,7 +82,7 @@ module ReeDao
|
|
86
82
|
)
|
87
83
|
when :has_one
|
88
84
|
one_to_one(
|
89
|
-
|
85
|
+
parent_dao,
|
90
86
|
assoc_name,
|
91
87
|
list,
|
92
88
|
scope: __opts[:scope],
|
@@ -98,7 +94,7 @@ module ReeDao
|
|
98
94
|
)
|
99
95
|
when :has_many
|
100
96
|
one_to_many(
|
101
|
-
|
97
|
+
parent_dao,
|
102
98
|
assoc_name,
|
103
99
|
list,
|
104
100
|
scope: __opts[:scope],
|
@@ -110,8 +106,8 @@ module ReeDao
|
|
110
106
|
end
|
111
107
|
end
|
112
108
|
|
113
|
-
contract(Or[Hash, Array], Bool, Nilor[Proc],
|
114
|
-
def process_block(assoc, autoload_children, to_dto,
|
109
|
+
contract(Or[Hash, Array], Bool, Nilor[Proc], Sequel::Dataset, Block => Any)
|
110
|
+
def process_block(assoc, autoload_children, to_dto, parent_dao, &block)
|
115
111
|
assoc_list = assoc.is_a?(Array) ? assoc : assoc.values.flatten
|
116
112
|
|
117
113
|
if to_dto
|
@@ -124,13 +120,12 @@ module ReeDao
|
|
124
120
|
parent.agg_caller,
|
125
121
|
assoc_list,
|
126
122
|
parent.local_vars,
|
127
|
-
|
123
|
+
parent_dao,
|
128
124
|
autoload_children,
|
129
125
|
**global_opts
|
130
126
|
)
|
131
|
-
parent_dao = find_dao(parent_dao_name, parent.agg_caller)
|
132
127
|
|
133
|
-
if
|
128
|
+
if parent_dao.db.in_transaction? || ReeDao::Associations.sync_mode?
|
134
129
|
associations.instance_exec(assoc_list, &block)
|
135
130
|
else
|
136
131
|
threads = associations.instance_exec(assoc_list, &block)
|
@@ -150,7 +145,7 @@ module ReeDao
|
|
150
145
|
end
|
151
146
|
|
152
147
|
contract(
|
153
|
-
|
148
|
+
Sequel::Dataset,
|
154
149
|
Symbol,
|
155
150
|
Array,
|
156
151
|
Kwargs[
|
@@ -162,7 +157,7 @@ module ReeDao
|
|
162
157
|
reverse: Bool
|
163
158
|
] => Or[Hash, Array]
|
164
159
|
)
|
165
|
-
def one_to_one(
|
160
|
+
def one_to_one(parent_dao, assoc_name, list, scope: nil, primary_key: :id, foreign_key: nil, setter: nil, to_dto: nil, reverse: true)
|
166
161
|
return {} if list.empty?
|
167
162
|
|
168
163
|
primary_key ||= :id
|
@@ -175,7 +170,7 @@ module ReeDao
|
|
175
170
|
if reverse
|
176
171
|
# has_one
|
177
172
|
if !foreign_key
|
178
|
-
foreign_key = "#{
|
173
|
+
foreign_key = "#{parent_dao.first_source_table.to_s.gsub(/s$/,'')}_id".to_sym
|
179
174
|
end
|
180
175
|
|
181
176
|
root_ids = list.map(&:id).uniq
|
@@ -211,7 +206,7 @@ module ReeDao
|
|
211
206
|
end
|
212
207
|
|
213
208
|
contract(
|
214
|
-
|
209
|
+
Sequel::Dataset,
|
215
210
|
Symbol,
|
216
211
|
Array,
|
217
212
|
Kwargs[
|
@@ -222,7 +217,7 @@ module ReeDao
|
|
222
217
|
to_dto: Nilor[Proc]
|
223
218
|
] => Or[Hash, Array]
|
224
219
|
)
|
225
|
-
def one_to_many(
|
220
|
+
def one_to_many(parent_dao, assoc_name, list, primary_key: nil, foreign_key: nil, scope: nil, setter: nil, to_dto: nil)
|
226
221
|
return {} if list.empty?
|
227
222
|
|
228
223
|
primary_key ||= :id
|
@@ -233,7 +228,7 @@ module ReeDao
|
|
233
228
|
assoc_dao = nil
|
234
229
|
assoc_dao = find_dao(assoc_name, parent, scope)
|
235
230
|
|
236
|
-
foreign_key ||= "#{
|
231
|
+
foreign_key ||= "#{parent_dao.first_source_table.to_s.gsub(/s$/, '')}_id".to_sym
|
237
232
|
|
238
233
|
root_ids = list.map(&:"#{primary_key}")
|
239
234
|
|
@@ -9,25 +9,20 @@ module ReeDao
|
|
9
9
|
end
|
10
10
|
|
11
11
|
module InstanceMethods
|
12
|
+
SUFFIXES = ["", "s", "es", "dao", "s_dao", "es_dao"].freeze
|
13
|
+
|
12
14
|
def find_dao(assoc_name, parent_caller, scope = nil)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
SUFFIXES.each do |suffix|
|
16
|
+
dao_from_name = parent_caller.instance_variable_get("@#{assoc_name}#{suffix}")
|
17
|
+
return dao_from_name if dao_from_name
|
18
|
+
end
|
19
|
+
|
20
|
+
if scope.is_a?(Sequel::Dataset)
|
21
|
+
return scope.unfiltered
|
22
|
+
end
|
23
|
+
|
23
24
|
raise ArgumentError, "can't find DAO for :#{assoc_name}, provide correct scope or association name"
|
24
25
|
end
|
25
|
-
|
26
|
-
def dao_in_transaction?(dao)
|
27
|
-
return false if dao.nil?
|
28
|
-
|
29
|
-
dao.db.in_transaction?
|
30
|
-
end
|
31
26
|
end
|
32
27
|
end
|
33
28
|
end
|
@@ -3,23 +3,23 @@ module ReeDao
|
|
3
3
|
include Ree::LinkDSL
|
4
4
|
include ReeDao::AssociationMethods
|
5
5
|
|
6
|
-
attr_reader :agg_caller, :list, :local_vars, :only, :except, :
|
6
|
+
attr_reader :agg_caller, :list, :local_vars, :only, :except, :parent_dao, :autoload_children, :global_opts
|
7
7
|
|
8
|
-
def initialize(agg_caller, list, local_vars,
|
8
|
+
def initialize(agg_caller, list, local_vars, parent_dao, autoload_children = false, **opts)
|
9
9
|
@agg_caller = agg_caller
|
10
10
|
@list = list
|
11
11
|
@local_vars = local_vars
|
12
12
|
@global_opts = opts || {}
|
13
13
|
@only = opts[:only] if opts[:only]
|
14
14
|
@except = opts[:except] if opts[:except]
|
15
|
-
@
|
15
|
+
@parent_dao = parent_dao
|
16
16
|
@autoload_children = autoload_children
|
17
17
|
|
18
18
|
if @only && @except
|
19
19
|
shared_keys = @only.intersection(@except)
|
20
20
|
|
21
21
|
if shared_keys.size > 0
|
22
|
-
raise ArgumentError.new("you can't use both :only and :except for #{shared_keys.map { "\"#{_1}\"" }.join(", ")} keys")
|
22
|
+
raise ArgumentError.new("you can't use both :only and :except for #{shared_keys.map { "\"#{_1}\"" }.join(", ")} keys")
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -87,12 +87,10 @@ module ReeDao
|
|
87
87
|
Optblock => Any
|
88
88
|
)
|
89
89
|
def association(assoc_type, assoc_name, __opts, &block)
|
90
|
-
parent_dao
|
91
|
-
|
92
|
-
if dao_in_transaction?(parent_dao) || self.class.sync_mode?
|
90
|
+
if parent_dao.db.in_transaction? || self.class.sync_mode?
|
93
91
|
return if association_is_not_included?(assoc_name) || list.empty?
|
94
92
|
|
95
|
-
association = Association.new(self,
|
93
|
+
association = Association.new(self, parent_dao, list, **global_opts)
|
96
94
|
|
97
95
|
if assoc_type == :field
|
98
96
|
association.handle_field(assoc_name, __opts)
|
@@ -104,7 +102,7 @@ module ReeDao
|
|
104
102
|
return { association_threads: @assoc_threads, field_threads: @field_threads }
|
105
103
|
end
|
106
104
|
|
107
|
-
association = Association.new(self,
|
105
|
+
association = Association.new(self, parent_dao, list, **global_opts)
|
108
106
|
|
109
107
|
if assoc_type == :field
|
110
108
|
field_proc = __opts
|
@@ -2,18 +2,15 @@
|
|
2
2
|
|
3
3
|
class ReeDao::Agg
|
4
4
|
include Ree::FnDSL
|
5
|
-
include ReeDao::AssociationMethods
|
6
5
|
|
7
6
|
fn :agg do
|
8
|
-
link :demodulize, from: :ree_string
|
9
|
-
link :underscore, from: :ree_string
|
10
7
|
link "ree_dao/associations", -> { Associations }
|
11
8
|
link "ree_dao/contract/dao_dataset_contract", -> { DaoDatasetContract }
|
12
9
|
link "ree_dao/contract/entity_contract", -> { EntityContract }
|
13
10
|
end
|
14
11
|
|
15
12
|
contract(
|
16
|
-
|
13
|
+
DaoDatasetContract,
|
17
14
|
Or[Sequel::Dataset, ArrayOf[Integer], ArrayOf[EntityContract], Integer],
|
18
15
|
Ksplat[
|
19
16
|
only?: ArrayOf[Symbol],
|
@@ -23,26 +20,16 @@ class ReeDao::Agg
|
|
23
20
|
],
|
24
21
|
Optblock => ArrayOf[Any]
|
25
22
|
)
|
26
|
-
def call(dao
|
23
|
+
def call(dao, ids_or_scope, **opts, &block)
|
27
24
|
scope = if ids_or_scope.is_a?(Array) && ids_or_scope.any? { _1.is_a?(Integer) }
|
28
|
-
raise ArgumentError.new("Dao should be provided") if dao.nil?
|
29
25
|
return [] if ids_or_scope.empty?
|
30
|
-
|
31
26
|
dao.where(id: ids_or_scope)
|
32
27
|
elsif ids_or_scope.is_a?(Integer)
|
33
|
-
raise ArgumentError.new("Dao should be provided") if dao.nil?
|
34
|
-
|
35
28
|
dao.where(id: ids_or_scope)
|
36
29
|
else
|
37
30
|
ids_or_scope
|
38
31
|
end
|
39
32
|
|
40
|
-
if dao
|
41
|
-
dao_name = dao.first_source_table
|
42
|
-
else
|
43
|
-
dao_name = underscore(demodulize(scope.first.class.name)).to_sym
|
44
|
-
end
|
45
|
-
|
46
33
|
list = scope.is_a?(Sequel::Dataset) ? scope.all : scope
|
47
34
|
|
48
35
|
if opts[:to_dto]
|
@@ -51,7 +38,7 @@ class ReeDao::Agg
|
|
51
38
|
end
|
52
39
|
end
|
53
40
|
|
54
|
-
load_associations(
|
41
|
+
load_associations(dao.unfiltered, list, **opts, &block) if block_given?
|
55
42
|
|
56
43
|
if ids_or_scope.is_a?(Array)
|
57
44
|
list.sort_by { ids_or_scope.index(_1.id) }
|
@@ -62,7 +49,7 @@ class ReeDao::Agg
|
|
62
49
|
|
63
50
|
private
|
64
51
|
|
65
|
-
def load_associations(
|
52
|
+
def load_associations(dao, list, **opts, &block)
|
66
53
|
return if list.empty?
|
67
54
|
|
68
55
|
local_vars = block.binding.eval(<<-CODE, __FILE__, __LINE__ + 1)
|
@@ -72,10 +59,9 @@ class ReeDao::Agg
|
|
72
59
|
|
73
60
|
agg_caller = block.binding.eval("self")
|
74
61
|
|
75
|
-
associations = Associations.new(agg_caller, list, local_vars,
|
76
|
-
dao = find_dao(dao_name, agg_caller)
|
62
|
+
associations = Associations.new(agg_caller, list, local_vars, dao, **opts).instance_exec(list, &block)
|
77
63
|
|
78
|
-
if
|
64
|
+
if dao.db.in_transaction? || ReeDao.load_sync_associations_enabled?
|
79
65
|
associations
|
80
66
|
else
|
81
67
|
associations[:association_threads].map do |association, assoc_type, assoc_name, opts, block|
|
@@ -16,8 +16,8 @@
|
|
16
16
|
"args": [
|
17
17
|
{
|
18
18
|
"arg": "dao",
|
19
|
-
"arg_type": "
|
20
|
-
"type": "
|
19
|
+
"arg_type": "req",
|
20
|
+
"type": "PackageName::DaoName::Dao: \"SELECT * FROM `table`\""
|
21
21
|
},
|
22
22
|
{
|
23
23
|
"arg": "ids_or_scope",
|
@@ -38,21 +38,6 @@
|
|
38
38
|
}
|
39
39
|
],
|
40
40
|
"links": [
|
41
|
-
{
|
42
|
-
"target": "demodulize",
|
43
|
-
"package_name": "ree_string",
|
44
|
-
"as": "demodulize",
|
45
|
-
"imports": [
|
46
41
|
|
47
|
-
]
|
48
|
-
},
|
49
|
-
{
|
50
|
-
"target": "underscore",
|
51
|
-
"package_name": "ree_string",
|
52
|
-
"as": "underscore",
|
53
|
-
"imports": [
|
54
|
-
|
55
|
-
]
|
56
|
-
}
|
57
42
|
]
|
58
43
|
}
|
@@ -2,7 +2,7 @@
|
|
2
2
|
require 'faker'
|
3
3
|
require 'benchmark'
|
4
4
|
|
5
|
-
RSpec.
|
5
|
+
RSpec.xdescribe :agg do
|
6
6
|
link :agg, from: :ree_dao
|
7
7
|
link :build_pg_connection, from: :ree_dao
|
8
8
|
|
@@ -115,7 +115,7 @@ RSpec.describe :agg do
|
|
115
115
|
|
116
116
|
aggregate :agg_users_benchmark do
|
117
117
|
link :users, from: :ree_dao_agg_test
|
118
|
-
link :
|
118
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
119
119
|
link :user_passports, from: :ree_dao_agg_test
|
120
120
|
link :books, from: :ree_dao_agg_test
|
121
121
|
link :movies, from: :ree_dao_agg_test
|
@@ -151,7 +151,7 @@ RSpec.describe :agg do
|
|
151
151
|
|
152
152
|
fn :users_sync_fetcher do
|
153
153
|
link :users, from: :ree_dao_agg_test
|
154
|
-
link :
|
154
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
155
155
|
link :user_passports, from: :ree_dao_agg_test
|
156
156
|
link :books, from: :ree_dao_agg_test
|
157
157
|
link :movies, from: :ree_dao_agg_test
|
@@ -183,7 +183,7 @@ RSpec.describe :agg do
|
|
183
183
|
return [] if list.empty?
|
184
184
|
|
185
185
|
if include.include?(:organization)
|
186
|
-
one_to_one(list,
|
186
|
+
one_to_one(list, organizations_dao.order(:id))
|
187
187
|
end
|
188
188
|
|
189
189
|
if include.include?(:books)
|
@@ -233,7 +233,7 @@ RSpec.describe :agg do
|
|
233
233
|
let(:agg_users) { ReeDaoAggTest::AggUsersBenchmark.new }
|
234
234
|
let(:users_sync_fetcher) { ReeDaoAggTest::UsersSyncFetcher.new }
|
235
235
|
|
236
|
-
let(:organizations) { ReeDaoAggTest::
|
236
|
+
let(:organizations) { ReeDaoAggTest::OrganizationsDao.new }
|
237
237
|
let(:users) { ReeDaoAggTest::Users.new }
|
238
238
|
let(:user_passports) { ReeDaoAggTest::UserPassports.new }
|
239
239
|
let(:books) { ReeDaoAggTest::Books.new }
|
@@ -18,7 +18,7 @@ RSpec.describe :agg do
|
|
18
18
|
connection.drop_table(:user_passports, cascade: true) if connection.table_exists?(:user_passports)
|
19
19
|
connection.drop_table(:books, cascade: true) if connection.table_exists?(:books)
|
20
20
|
connection.drop_table(:chapters, cascade: true) if connection.table_exists?(:chapters)
|
21
|
-
connection.drop_table(:
|
21
|
+
connection.drop_table(:avtorki, cascade: true) if connection.table_exists?(:avtorki)
|
22
22
|
connection.drop_table(:reviews, cascade: true) if connection.table_exists?(:reviews)
|
23
23
|
connection.drop_table(:review_authors, cascade: true) if connection.table_exists?(:review_authors)
|
24
24
|
|
@@ -71,7 +71,7 @@ RSpec.describe :agg do
|
|
71
71
|
column :name, 'varchar(256)'
|
72
72
|
end
|
73
73
|
|
74
|
-
connection.create_table :
|
74
|
+
connection.create_table :avtorki do
|
75
75
|
primary_key :id
|
76
76
|
|
77
77
|
foreign_key :book_id, :books, null: false, on_delete: :cascade
|
@@ -88,7 +88,7 @@ RSpec.describe :agg do
|
|
88
88
|
|
89
89
|
aggregate :agg_users do
|
90
90
|
link :users, from: :ree_dao_agg_test
|
91
|
-
link :
|
91
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
92
92
|
link :user_passports, from: :ree_dao_agg_test
|
93
93
|
link :books, from: :ree_dao_agg_test
|
94
94
|
link :chapters, from: :ree_dao_agg_test
|
@@ -160,7 +160,7 @@ RSpec.describe :agg do
|
|
160
160
|
link :books, from: :ree_dao_agg_test
|
161
161
|
link :authors, from: :ree_dao_agg_test
|
162
162
|
link :chapters, from: :ree_dao_agg_test
|
163
|
-
link :
|
163
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
164
164
|
link :agg, from: :ree_dao
|
165
165
|
end
|
166
166
|
|
@@ -268,7 +268,7 @@ RSpec.describe :agg do
|
|
268
268
|
|
269
269
|
aggregate :agg_users_block_test do
|
270
270
|
link :users, from: :ree_dao_agg_test
|
271
|
-
link :
|
271
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
272
272
|
link :books, from: :ree_dao_agg_test
|
273
273
|
link :agg, from: :ree_dao
|
274
274
|
end
|
@@ -297,7 +297,7 @@ RSpec.describe :agg do
|
|
297
297
|
|
298
298
|
aggregate :agg_users_scope_method_test do
|
299
299
|
link :users, from: :ree_dao_agg_test
|
300
|
-
link :
|
300
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
301
301
|
link :books, from: :ree_dao_agg_test
|
302
302
|
link :agg, from: :ree_dao
|
303
303
|
end
|
@@ -345,7 +345,7 @@ RSpec.describe :agg do
|
|
345
345
|
|
346
346
|
aggregate :agg_users_without_dao do
|
347
347
|
link :users, from: :ree_dao_agg_test
|
348
|
-
link :
|
348
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
349
349
|
link :books, from: :ree_dao_agg_test
|
350
350
|
link :agg, from: :ree_dao
|
351
351
|
end
|
@@ -362,7 +362,7 @@ RSpec.describe :agg do
|
|
362
362
|
|
363
363
|
aggregate :agg_users_only_except_keys do
|
364
364
|
link :users, from: :ree_dao_agg_test
|
365
|
-
link :
|
365
|
+
link :organizations_dao, from: :ree_dao_agg_test
|
366
366
|
link :books, from: :ree_dao_agg_test
|
367
367
|
link :agg, from: :ree_dao
|
368
368
|
end
|
@@ -384,7 +384,7 @@ RSpec.describe :agg do
|
|
384
384
|
let(:agg_users_with_dto) { ReeDaoAggTest::AggUsersWithDto.new }
|
385
385
|
let(:agg_users_only_dataset) { ReeDaoAggTest::AggUsersOnlyDataset.new }
|
386
386
|
let(:user_agg_only_except_keys) { ReeDaoAggTest::AggUsersOnlyExceptCase.new }
|
387
|
-
let(:organizations) { ReeDaoAggTest::
|
387
|
+
let(:organizations) { ReeDaoAggTest::OrganizationsDao.new }
|
388
388
|
let(:users) { ReeDaoAggTest::Users.new }
|
389
389
|
let(:user_passports) { ReeDaoAggTest::UserPassports.new }
|
390
390
|
let(:books) { ReeDaoAggTest::Books.new }
|
@@ -179,7 +179,7 @@ class ReeDaoAggTest::Organization
|
|
179
179
|
id: Nilor[Integer],
|
180
180
|
name: String
|
181
181
|
)
|
182
|
-
|
182
|
+
|
183
183
|
contract(Array[ReeDaoAggTest::User] => nil)
|
184
184
|
def set_users(users)
|
185
185
|
@users = users; nil
|
@@ -354,10 +354,10 @@ class ReeDaoAggTest::Users
|
|
354
354
|
filter :by_name, -> (name) { where(name: name) }
|
355
355
|
end
|
356
356
|
|
357
|
-
class ReeDaoAggTest::
|
357
|
+
class ReeDaoAggTest::OrganizationsDao
|
358
358
|
include ReeDao::DSL
|
359
359
|
|
360
|
-
dao :
|
360
|
+
dao :organizations_dao do
|
361
361
|
link :db
|
362
362
|
end
|
363
363
|
|
@@ -538,7 +538,7 @@ class ReeDaoAggTest::Authors
|
|
538
538
|
link :db
|
539
539
|
end
|
540
540
|
|
541
|
-
table :
|
541
|
+
table :avtorki
|
542
542
|
|
543
543
|
schema ReeDaoAggTest::Author do
|
544
544
|
integer :id, null: true
|
@@ -4,10 +4,10 @@ module ReeEnum::Contractable
|
|
4
4
|
include Ree::Contracts::Truncatable
|
5
5
|
|
6
6
|
def valid?(value)
|
7
|
-
value.is_a?(ReeEnum::Value) && value.enum_name ==
|
7
|
+
value.is_a?(ReeEnum::Value) && value.enum_name == get_enum_name && get_values.each.include?(value)
|
8
8
|
end
|
9
9
|
|
10
10
|
def message(value, name, lvl = 1)
|
11
|
-
|
11
|
+
"expected one of #{self.name}, got #{value.class} => #{truncate(value.inspect)}"
|
12
12
|
end
|
13
13
|
end
|
@@ -52,28 +52,17 @@ module ReeEnum
|
|
52
52
|
] => ReeEnum::Value
|
53
53
|
).throws(ReeMapper::CoercionError)
|
54
54
|
def cast(value, name:, role: nil)
|
55
|
-
if value.is_a?(String)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
end
|
61
|
-
|
62
|
-
enum_val
|
63
|
-
elsif value.is_a?(Integer)
|
64
|
-
enum_val = @enum.values.all.detect { |v| v.to_i == value }
|
65
|
-
|
66
|
-
if !enum_val
|
67
|
-
raise ReeMapper::CoercionError, "`#{name}` should be one of #{@enum.values.all.map(&:to_s).inspect}"
|
68
|
-
end
|
69
|
-
|
70
|
-
enum_val
|
71
|
-
else
|
72
|
-
enum_val = @enum.values.all.detect { |v| v == value }
|
73
|
-
return enum_val if enum_val
|
55
|
+
enum_value = if value.is_a?(String)
|
56
|
+
@enum.get_values.by_value(value)
|
57
|
+
elsif value.is_a?(ReeEnum::Value)
|
58
|
+
@enum.get_values.each.find { _1 == value }
|
59
|
+
end
|
74
60
|
|
75
|
-
|
61
|
+
if enum_value.nil?
|
62
|
+
raise ReeMapper::CoercionError, "`#{name}` should be one of #{enum_inspection}"
|
76
63
|
end
|
64
|
+
|
65
|
+
enum_value
|
77
66
|
end
|
78
67
|
|
79
68
|
contract(
|
@@ -81,21 +70,38 @@ module ReeEnum
|
|
81
70
|
Kwargs[
|
82
71
|
name: String,
|
83
72
|
role: Nilor[Symbol, ArrayOf[Symbol]]
|
84
|
-
] => Integer
|
73
|
+
] => Or[Integer, String]
|
85
74
|
)
|
86
75
|
def db_dump(value, name:, role: nil)
|
87
|
-
value.
|
76
|
+
value.mapped_value
|
88
77
|
end
|
89
78
|
|
90
79
|
contract(
|
91
|
-
Integer,
|
80
|
+
Or[Integer, String],
|
92
81
|
Kwargs[
|
93
82
|
name: String,
|
94
83
|
role: Nilor[Symbol, ArrayOf[Symbol]]
|
95
84
|
] => ReeEnum::Value
|
96
|
-
).throws(ReeMapper::
|
85
|
+
).throws(ReeMapper::CoercionError)
|
97
86
|
def db_load(value, name:, role: nil)
|
98
|
-
|
87
|
+
enum_val = @enum.get_values.by_mapped_value(value)
|
88
|
+
|
89
|
+
if !enum_val
|
90
|
+
raise ReeMapper::CoercionError, "`#{name}` should be one of #{enum_inspection}"
|
91
|
+
end
|
92
|
+
|
93
|
+
enum_val
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def enum_inspection
|
99
|
+
@enum_inspect ||= truncate(@enum.get_values.each.map(&:to_s).inspect)
|
100
|
+
end
|
101
|
+
|
102
|
+
def truncate(str, limit = 180)
|
103
|
+
return str if str.length <= limit
|
104
|
+
"#{str[0..limit]}..."
|
99
105
|
end
|
100
106
|
end
|
101
107
|
|
@@ -113,7 +119,7 @@ module ReeEnum
|
|
113
119
|
->(*) {
|
114
120
|
{
|
115
121
|
type: 'string',
|
116
|
-
enum:
|
122
|
+
enum: get_values.each.map(&:to_s)
|
117
123
|
}
|
118
124
|
}
|
119
125
|
)
|
@@ -128,7 +134,7 @@ module ReeEnum
|
|
128
134
|
)
|
129
135
|
|
130
136
|
mapper_factory.register_type(
|
131
|
-
self.
|
137
|
+
self.get_enum_name, type_for_mapper
|
132
138
|
)
|
133
139
|
end
|
134
140
|
end
|
@@ -5,20 +5,6 @@ require_relative 'values'
|
|
5
5
|
require_relative 'contractable'
|
6
6
|
|
7
7
|
module ReeEnum::Enumerable
|
8
|
-
module CommonMethods
|
9
|
-
def by_value(value)
|
10
|
-
values.by_value(value)
|
11
|
-
end
|
12
|
-
|
13
|
-
def by_number(number)
|
14
|
-
values.by_number(number)
|
15
|
-
end
|
16
|
-
|
17
|
-
def all
|
18
|
-
values.all
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
8
|
def self.included(base)
|
23
9
|
base.extend(ClassMethods)
|
24
10
|
end
|
@@ -26,43 +12,45 @@ module ReeEnum::Enumerable
|
|
26
12
|
module ClassMethods
|
27
13
|
include ReeEnum::Contractable
|
28
14
|
|
15
|
+
RESTRICTED_METHODS = [
|
16
|
+
:setup_enum, :get_values, :get_enum_name,
|
17
|
+
:val, :self, :class, :alias
|
18
|
+
].freeze
|
19
|
+
|
29
20
|
def setup_enum(enum_name)
|
30
21
|
@values ||= ReeEnum::Values.new(self, enum_name)
|
31
22
|
end
|
32
23
|
|
33
|
-
def
|
24
|
+
def get_values
|
34
25
|
@values
|
35
26
|
end
|
36
27
|
|
37
|
-
def
|
38
|
-
|
39
|
-
@values.enum_name
|
28
|
+
def get_enum_name
|
29
|
+
@values&.enum_name
|
40
30
|
end
|
41
31
|
|
42
|
-
|
32
|
+
def val(value, mapped_value = value.to_s, method: value.to_sym)
|
33
|
+
value = value.to_s
|
43
34
|
|
44
|
-
|
45
|
-
|
46
|
-
raise ArgumentError.new(":new is not allowed as enum value")
|
35
|
+
if RESTRICTED_METHODS.include?(method)
|
36
|
+
raise ArgumentError.new("#{method.inspect} is not allowed as enum method")
|
47
37
|
end
|
48
|
-
|
49
|
-
enum_value = values.add(value, number: number, label: label)
|
50
38
|
|
51
|
-
|
52
|
-
|
39
|
+
enum_value = @values.add(value, mapped_value, method)
|
40
|
+
|
41
|
+
define_method(enum_value.method) do
|
42
|
+
get_values.by_value(enum_value.value)
|
53
43
|
end
|
54
44
|
|
55
|
-
define_singleton_method
|
56
|
-
by_value(enum_value.value)
|
45
|
+
define_singleton_method(enum_value.method) do
|
46
|
+
get_values.by_value(enum_value.value)
|
57
47
|
end
|
58
48
|
|
59
49
|
enum_value
|
60
50
|
end
|
61
51
|
end
|
62
52
|
|
63
|
-
def
|
64
|
-
self.class.
|
53
|
+
def get_values
|
54
|
+
self.class.get_values
|
65
55
|
end
|
66
|
-
|
67
|
-
include CommonMethods
|
68
56
|
end
|
@@ -1,60 +1,45 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ReeEnum::Value
|
4
|
-
attr_reader :enum_class, :enum_name, :value, :
|
4
|
+
attr_reader :enum_class, :enum_name, :value, :method, :mapped_value
|
5
5
|
|
6
|
-
contract(Class, Symbol,
|
7
|
-
def initialize(enum_class, enum_name, value,
|
6
|
+
contract(Class, Symbol, String, Or[Integer, String], Symbol => Any)
|
7
|
+
def initialize(enum_class, enum_name, value, mapped_value, method)
|
8
8
|
@enum_class = enum_class
|
9
9
|
@enum_name = enum_name
|
10
10
|
@value = value
|
11
|
-
@
|
12
|
-
@
|
11
|
+
@method = method
|
12
|
+
@mapped_value = mapped_value
|
13
13
|
end
|
14
14
|
|
15
15
|
def to_s
|
16
|
-
|
16
|
+
value
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
20
|
-
|
21
|
-
end
|
22
|
-
|
23
|
-
def to_i
|
24
|
-
@number
|
19
|
+
def to_sql
|
20
|
+
mapped_value
|
25
21
|
end
|
26
22
|
|
27
23
|
def as_json(*args)
|
28
24
|
to_s
|
29
25
|
end
|
30
26
|
|
31
|
-
|
32
|
-
@label
|
33
|
-
end
|
34
|
-
|
35
|
-
contract(Or[ReeEnum::Value, Symbol, Integer, Any] => Bool)
|
27
|
+
contract(Or[ReeEnum::Value, String, Symbol, Integer, Any] => Bool)
|
36
28
|
def ==(compare)
|
37
29
|
if compare.is_a?(self.class)
|
38
|
-
|
30
|
+
value == compare.value
|
31
|
+
elsif compare.is_a?(Symbol)
|
32
|
+
value == compare.to_s
|
33
|
+
elsif compare.is_a?(String)
|
34
|
+
value == compare || mapped_value == compare
|
35
|
+
elsif compare.is_a?(Integer)
|
36
|
+
mapped_value == compare
|
39
37
|
else
|
40
|
-
|
38
|
+
false
|
41
39
|
end
|
42
40
|
end
|
43
41
|
|
44
|
-
contract(Or[ReeEnum::Value, String, Integer] => Bool)
|
45
|
-
def <=>(other)
|
46
|
-
if other.is_a?(self.class)
|
47
|
-
@number <=> other.number
|
48
|
-
elsif other.is_a?(Symbol)
|
49
|
-
@value == other
|
50
|
-
elsif other.is_a?(Integer)
|
51
|
-
@number == other
|
52
|
-
else
|
53
|
-
raise ArgumentError.new("unable to compare ReeEnum::Value with other classes")
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
42
|
def inspect
|
58
|
-
"#{enum_class.name}##{
|
43
|
+
"#{enum_class.name}##{value}"
|
59
44
|
end
|
60
45
|
end
|
@@ -6,41 +6,67 @@ class ReeEnum::Values
|
|
6
6
|
def initialize(klass, enum_name)
|
7
7
|
@klass = klass
|
8
8
|
@enum_name = enum_name
|
9
|
-
@collection =
|
9
|
+
@collection = []
|
10
|
+
@collection_by_value = {}
|
11
|
+
@collection_by_mapped_value = {}
|
10
12
|
end
|
11
13
|
|
12
|
-
def
|
13
|
-
@collection
|
14
|
+
def to_a
|
15
|
+
@collection
|
14
16
|
end
|
15
17
|
|
16
|
-
|
18
|
+
def each(&)
|
19
|
+
@collection.each(&)
|
20
|
+
end
|
21
|
+
|
22
|
+
contract(Or[Symbol, String] => Nilor[ReeEnum::Value])
|
17
23
|
def by_value(value)
|
18
|
-
|
19
|
-
|
24
|
+
@collection_by_value[value.to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
contract(Or[Symbol, String] => ReeEnum::Value).throws(ArgumentError)
|
28
|
+
def by_value!(value)
|
29
|
+
by_value(value) ||
|
30
|
+
(raise ArgumentError.new("constant for value #{value.inspect} is not found in #{self.inspect}"))
|
31
|
+
end
|
32
|
+
|
33
|
+
contract(Or[Integer, String] => Nilor[ReeEnum::Value])
|
34
|
+
def by_mapped_value(mapped_value)
|
35
|
+
@collection_by_mapped_value[mapped_value]
|
20
36
|
end
|
21
37
|
|
22
|
-
contract(Integer => ReeEnum::Value).throws(ArgumentError)
|
23
|
-
def
|
24
|
-
|
25
|
-
|
38
|
+
contract(Or[Integer, String] => ReeEnum::Value).throws(ArgumentError)
|
39
|
+
def by_mapped_value!(mapped_value)
|
40
|
+
by_mapped_value(mapped_value) ||
|
41
|
+
(raise ArgumentError.new("constant for value #{mapped_value.inspect} is not found in #{self.inspect}"))
|
26
42
|
end
|
27
43
|
|
28
44
|
def inspect
|
29
|
-
@collection.
|
45
|
+
@collection.map(&:inspect).inspect
|
30
46
|
end
|
31
47
|
|
32
|
-
contract(
|
33
|
-
def add(value,
|
34
|
-
if @collection.
|
48
|
+
contract(String, Or[Integer, String], Symbol => ReeEnum::Value)
|
49
|
+
def add(value, mapped_value, method)
|
50
|
+
if @collection.any? { _1.method == method }
|
51
|
+
raise ArgumentError, "#{@klass}: method #{method.inspect} was already added"
|
52
|
+
end
|
53
|
+
|
54
|
+
if @collection_by_value.key?(value)
|
35
55
|
raise ArgumentError, "#{@klass}: value #{value.inspect} was already added"
|
36
56
|
end
|
37
57
|
|
38
|
-
if @
|
39
|
-
raise ArgumentError, "
|
58
|
+
if @collection_by_mapped_value.key?(mapped_value)
|
59
|
+
raise ArgumentError, "#{@klass}: mapped_value(#{mapped_value.inspect}) for #{value.inspect} was already added"
|
40
60
|
end
|
41
61
|
|
42
|
-
|
43
|
-
@klass, @enum_name, value,
|
62
|
+
enum_value = ReeEnum::Value.new(
|
63
|
+
@klass, @enum_name, value, mapped_value, method
|
44
64
|
)
|
65
|
+
|
66
|
+
@collection << enum_value
|
67
|
+
@collection_by_value[value] = enum_value
|
68
|
+
@collection_by_mapped_value[mapped_value] = enum_value
|
69
|
+
|
70
|
+
enum_value
|
45
71
|
end
|
46
72
|
end
|
@@ -32,11 +32,20 @@ RSpec.describe ReeEnum::DSL do
|
|
32
32
|
|
33
33
|
enum :types
|
34
34
|
|
35
|
-
val :account
|
35
|
+
val :account
|
36
36
|
|
37
37
|
register_as_mapper_type
|
38
38
|
end
|
39
39
|
|
40
|
+
class Reflexives
|
41
|
+
include ReeEnum::DSL
|
42
|
+
|
43
|
+
enum :reflexives
|
44
|
+
|
45
|
+
val :self, method: :myself
|
46
|
+
val :yourself
|
47
|
+
end
|
48
|
+
|
40
49
|
class TestMapper
|
41
50
|
include ReeMapper::DSL
|
42
51
|
|
@@ -75,11 +84,11 @@ RSpec.describe ReeEnum::DSL do
|
|
75
84
|
expect(o.first).to eq(0)
|
76
85
|
expect(o.second).to eq(:second)
|
77
86
|
expect(o.second).to eq(1)
|
78
|
-
expect(o.by_value(:first)).to eq(o.first)
|
79
|
-
expect(o.by_value(:second)).to eq(o.second)
|
80
|
-
expect(o.
|
81
|
-
expect(o.
|
82
|
-
expect(o.
|
87
|
+
expect(o.get_values.by_value(:first)).to eq(o.first)
|
88
|
+
expect(o.get_values.by_value(:second)).to eq(o.second)
|
89
|
+
expect(o.get_values.by_mapped_value(0)).to eq(o.first)
|
90
|
+
expect(o.get_values.by_mapped_value(1)).to eq(o.second)
|
91
|
+
expect(o.get_values.to_a).to eq([o.first, o.second])
|
83
92
|
end
|
84
93
|
|
85
94
|
expect {
|
@@ -146,18 +155,20 @@ RSpec.describe ReeEnum::DSL do
|
|
146
155
|
).to eq(
|
147
156
|
{
|
148
157
|
state: 0,
|
149
|
-
type:
|
158
|
+
type: "account"
|
150
159
|
}
|
151
160
|
)
|
152
161
|
|
153
162
|
dto = mapper.db_load({
|
154
163
|
state: 0,
|
155
|
-
type:
|
164
|
+
type: "account",
|
156
165
|
})
|
157
166
|
|
158
167
|
expect(dto.state).to eq(TestReeEnum::States.first)
|
159
168
|
expect(dto.state).to be_a(ReeEnum::Value)
|
160
169
|
expect(dto.type).to eq(TestReeEnum::Types.account)
|
161
170
|
expect(dto.type).to be_a(ReeEnum::Value)
|
171
|
+
|
172
|
+
expect(TestReeEnum::Reflexives.myself).to eq(:self)
|
162
173
|
}
|
163
174
|
end
|
data/lib/ree_lib/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ree_lib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.70
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ruslan Gatiyatov
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08-
|
11
|
+
date: 2023-08-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ree
|