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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a34603f1dd69c0e4eecca51ac58f30e000fd673da8f157901eb085671b7d9e04
4
- data.tar.gz: ddd8255a1b09641a1d88869e8c664415b44c1a3e8669c907459fd14bcd709743
3
+ metadata.gz: 40e7e6a91b65f1bab58b667f1eebf153ac5fd1c85852e189af8d3a6d2ea8b163
4
+ data.tar.gz: 5ac2658d206e2aa8963fd90ed4ca4ef071b701a0d02414d571dcc95df825a88e
5
5
  SHA512:
6
- metadata.gz: 1e07c24f16571cbdadf18a7f5013a87d488d230663f89524d927dd1998835365293b83e42bce61e8ceac2871762b16102130efe26419e2ef5270bc5ee2597db7
7
- data.tar.gz: 6ca2018732da00c6205c048bb1011738694174a8b76930973625567db74e6bca9ad86aea6764e503ddb4f915853ce603160e0bd194f229587c018ac7e98cd156
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.68)
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.13.10)
43
- mini_portile2 (~> 2.8.0)
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, :parent_dao_name, :list, :global_opts
11
+ attr_reader :parent, :parent_dao, :list, :global_opts
12
12
 
13
- contract(ReeDao::Associations, Symbol, Array, Ksplat[RestKeys => Any] => Any)
14
- def initialize(parent, parent_dao_name, list, **global_opts)
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
- @parent_dao_name = parent_dao_name
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 => Nilor[Array]
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
- dao = find_dao(assoc_name, parent, __opts[:scope])
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
- if name.end_with?("s")
58
- "#{name}es"
59
- else
60
- "#{name}s"
61
- end
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], dao_name, &block) if block_given?
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
- parent_dao_name,
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
- parent_dao_name,
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
- parent_dao_name,
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], Symbol, Block => Any)
114
- def process_block(assoc, autoload_children, to_dto, parent_dao_name, &block)
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
- parent_dao_name,
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 dao_in_transaction?(parent_dao) || ReeDao::Associations.sync_mode?
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
- Symbol,
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(parent_assoc_name, assoc_name, list, scope: nil, primary_key: :id, foreign_key: nil, setter: nil, to_dto: nil, reverse: true)
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 = "#{parent_assoc_name.to_s.gsub(/s$/,'')}_id".to_sym
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
- Symbol,
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(parent_assoc_name, assoc_name, list, primary_key: nil, foreign_key: nil, scope: nil, setter: nil, to_dto: nil)
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 ||= "#{parent_assoc_name.to_s.gsub(/s$/, '')}_id".to_sym
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
- dao_from_name = parent_caller.instance_variable_get("@#{assoc_name}") || parent_caller.instance_variable_get("@#{assoc_name}s")
14
- return dao_from_name if dao_from_name
15
-
16
- raise ArgumentError, "can't find DAO for :#{assoc_name}, provide correct scope or association name" if scope.nil?
17
- return nil if scope.is_a?(Array)
18
-
19
- table_name = scope.first_source_table
20
- dao_from_scope = parent_caller.instance_variable_get("@#{table_name}")
21
- return dao_from_scope if dao_from_scope
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, :parent_dao_name, :autoload_children, :global_opts
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, parent_dao_name, autoload_children = false, **opts)
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
- @parent_dao_name = parent_dao_name
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 = find_dao(parent_dao_name, agg_caller)
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, parent_dao_name, list, **global_opts)
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, parent_dao_name, list, **global_opts)
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
- Nilor[DaoDatasetContract],
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 = nil, ids_or_scope, **opts, &block)
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(dao_name, list, **opts, &block) if block_given?
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(dao_name, list, **opts, &block)
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, dao_name, **opts).instance_exec(list, &block)
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 dao_in_transaction?(dao) || ReeDao.load_sync_associations_enabled?
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": "opt",
20
- "type": "Nilor[PackageName::DaoName::Dao: \"SELECT * FROM `table`\"]"
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.describe :agg do
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 :organizations, from: :ree_dao_agg_test
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 :organizations, from: :ree_dao_agg_test
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, organizations.order(:id))
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::Organizations.new }
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(:authors, cascade: true) if connection.table_exists?(:authors)
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 :authors do
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 :organizations, from: :ree_dao_agg_test
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 :organizations, from: :ree_dao_agg_test
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 :organizations, from: :ree_dao_agg_test
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 :organizations, from: :ree_dao_agg_test
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 :organizations, from: :ree_dao_agg_test
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 :organizations, from: :ree_dao_agg_test
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::Organizations.new }
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::Organizations
357
+ class ReeDaoAggTest::OrganizationsDao
358
358
  include ReeDao::DSL
359
359
 
360
- dao :organizations do
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 :authors
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 == self.enum_name && all.include?(value)
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
- return "expected one of #{self.name}, got #{value.class} => #{truncate(value.inspect)}"
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
- enum_val = @enum.values.all.detect { |v| v.to_s == value }
57
-
58
- if !enum_val
59
- raise ReeMapper::CoercionError, "`#{name}` should be one of #{@enum.values.all.map(&:to_s).inspect}"
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
- raise ReeMapper::CoercionError, "`#{name}` should be one of #{@enum.values.all.map(&:to_s).inspect}"
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.to_i
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::TypeError)
85
+ ).throws(ReeMapper::CoercionError)
97
86
  def db_load(value, name:, role: nil)
98
- cast(value, name: name, role: role)
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: values.all.map(&:to_s)
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.enum_name, type_for_mapper
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 values
24
+ def get_values
34
25
  @values
35
26
  end
36
27
 
37
- def enum_name
38
- return if !@values
39
- @values.enum_name
28
+ def get_enum_name
29
+ @values&.enum_name
40
30
  end
41
31
 
42
- include CommonMethods
32
+ def val(value, mapped_value = value.to_s, method: value.to_sym)
33
+ value = value.to_s
43
34
 
44
- def val(value, number, label = nil)
45
- if value == :new
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
- define_method "#{enum_value.value}" do
52
- by_value(enum_value.value)
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 "#{enum_value.value}" do
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 values
64
- self.class.values
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, :label, :number
4
+ attr_reader :enum_class, :enum_name, :value, :method, :mapped_value
5
5
 
6
- contract(Class, Symbol, Symbol, Integer, Nilor[String] => Any)
7
- def initialize(enum_class, enum_name, value, number, label)
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
- @label = label
12
- @number = number
11
+ @method = method
12
+ @mapped_value = mapped_value
13
13
  end
14
14
 
15
15
  def to_s
16
- @value.to_s
16
+ value
17
17
  end
18
18
 
19
- def to_sym
20
- @value
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
- def label
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
- @value == compare.value
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
- @value == compare || @number == compare
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}##{@value.to_s}"
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 all
13
- @collection.values.sort_by(&:number)
14
+ def to_a
15
+ @collection
14
16
  end
15
17
 
16
- contract(Symbol => ReeEnum::Value).throws(ArgumentError)
18
+ def each(&)
19
+ @collection.each(&)
20
+ end
21
+
22
+ contract(Or[Symbol, String] => Nilor[ReeEnum::Value])
17
23
  def by_value(value)
18
- type = @collection.values.detect {|c| c.value == value}
19
- type || (raise ArgumentError.new("constant for value #{value.inspect} is not found in #{self.inspect}"))
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 by_number(number)
24
- type = @collection.values.detect {|c| c.number == number}
25
- type || (raise ArgumentError.new("constant for value #{number.inspect} is not found in #{self.inspect}"))
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.values.map(&:inspect).inspect
45
+ @collection.map(&:inspect).inspect
30
46
  end
31
47
 
32
- contract(Symbol, Kwargs[number: Integer, label: Nilor[String]] => ReeEnum::Value)
33
- def add(value, number:, label: nil)
34
- if @collection.has_key?(value)
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 @collection.values.any? {|v| v.number == number}
39
- raise ArgumentError, "number for #{value.inspect} was already added"
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
- @collection[value] = ReeEnum::Value.new(
43
- @klass, @enum_name, value, number, label
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, 0
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.by_number(0)).to eq(o.first)
81
- expect(o.by_number(1)).to eq(o.second)
82
- expect(o.all).to eq([o.first, o.second])
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: 0
158
+ type: "account"
150
159
  }
151
160
  )
152
161
 
153
162
  dto = mapper.db_load({
154
163
  state: 0,
155
- type: 0,
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReeLib
4
- VERSION = "1.0.68"
4
+ VERSION = "1.0.70"
5
5
  end
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.68
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-25 00:00:00.000000000 Z
11
+ date: 2023-08-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ree