ree_lib 1.0.68 → 1.0.70

Sign up to get free protection for your applications and to get access to all the features.
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