ree_lib 1.0.70 → 1.0.72

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: 40e7e6a91b65f1bab58b667f1eebf153ac5fd1c85852e189af8d3a6d2ea8b163
4
- data.tar.gz: 5ac2658d206e2aa8963fd90ed4ca4ef071b701a0d02414d571dcc95df825a88e
3
+ metadata.gz: 0421ad28472f902b4c53091515c749bdcb6aba9ef96ed42009abe27d115edf48
4
+ data.tar.gz: 3909bfecb3e92e05708a9be5effb672fc8042e2f53ed4aadb426539f0eba8574
5
5
  SHA512:
6
- metadata.gz: 221b1612a9ddc52b73f6cd34a1f1228009a3459646d0f129281d5c4ae16557e1044359cb13e44085bf1e727ae07ce3be7cfae9e1728fae8260ed42f888a52010
7
- data.tar.gz: e296d1413246f6813ec865ae1395eec11f71f2066d755d815ccac8a260278f122c20e6ca0c680204245a693aa9668dfaab46c0187e25e51288be6c4d523c5e7a
6
+ metadata.gz: bb696f99d8af84de496f0e6a3bf616256853302d952409832fd89eb24830c0f29cb2cead19b245eee883a2c9dc7d358633bccc308be56369c2d8aeb569a66c7d
7
+ data.tar.gz: 0accc79d4259f341f4fbf6306103e28521b070119b2ee6be3e7bb98e08802b78ad857f476524a128d9c51cd7ca02fb59298ac70886b70a1304de8d39455d13d5
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- ree_lib (1.0.70)
4
+ ree_lib (1.0.72)
5
5
  binding_of_caller (~> 1.0.0)
6
6
  i18n (~> 1.12.0)
7
7
  loofah (~> 2.18.0)
@@ -3,14 +3,12 @@ module ReeDao
3
3
  include Ree::LinkDSL
4
4
  include ReeDao::AssociationMethods
5
5
 
6
- link :demodulize, from: :ree_string
7
6
  link :group_by, from: :ree_array
8
7
  link :index_by, from: :ree_array
9
- link :underscore, from: :ree_string
10
8
 
11
9
  attr_reader :parent, :parent_dao, :list, :global_opts
12
10
 
13
- contract(ReeDao::Associations, Sequel::Dataset, Array, Ksplat[RestKeys => Any] => Any)
11
+ contract(ReeDao::Associations, Nilor[Sequel::Dataset], Array, Ksplat[RestKeys => Any] => Any)
14
12
  def initialize(parent, parent_dao, list, **global_opts)
15
13
  @parent = parent
16
14
  @parent_dao = parent_dao
@@ -51,8 +49,7 @@ module ReeDao
51
49
 
52
50
  dao = if scope.is_a?(Array)
53
51
  return [] if scope.empty?
54
- name = underscore(demodulize(scope.first.class.name))
55
- find_dao(name, parent, nil)
52
+ nil
56
53
  else
57
54
  find_dao(assoc_name, parent, scope)
58
55
  end
@@ -125,7 +122,7 @@ module ReeDao
125
122
  **global_opts
126
123
  )
127
124
 
128
- if parent_dao.db.in_transaction? || ReeDao::Associations.sync_mode?
125
+ if parent_dao.nil? || parent_dao.db.in_transaction? || ReeDao::Associations.sync_mode?
129
126
  associations.instance_exec(assoc_list, &block)
130
127
  else
131
128
  threads = associations.instance_exec(assoc_list, &block)
@@ -145,7 +142,7 @@ module ReeDao
145
142
  end
146
143
 
147
144
  contract(
148
- Sequel::Dataset,
145
+ Nilor[Sequel::Dataset],
149
146
  Symbol,
150
147
  Array,
151
148
  Kwargs[
@@ -170,7 +167,11 @@ module ReeDao
170
167
  if reverse
171
168
  # has_one
172
169
  if !foreign_key
173
- foreign_key = "#{parent_dao.first_source_table.to_s.gsub(/s$/,'')}_id".to_sym
170
+ if parent_dao.nil?
171
+ raise ArgumentError.new("foreign_key should be provided for :#{assoc_name} association")
172
+ end
173
+
174
+ foreign_key = foreign_key_from_dao(parent_dao)
174
175
  end
175
176
 
176
177
  root_ids = list.map(&:id).uniq
@@ -206,7 +207,7 @@ module ReeDao
206
207
  end
207
208
 
208
209
  contract(
209
- Sequel::Dataset,
210
+ Nilor[Sequel::Dataset],
210
211
  Symbol,
211
212
  Array,
212
213
  Kwargs[
@@ -228,7 +229,13 @@ module ReeDao
228
229
  assoc_dao = nil
229
230
  assoc_dao = find_dao(assoc_name, parent, scope)
230
231
 
231
- foreign_key ||= "#{parent_dao.first_source_table.to_s.gsub(/s$/, '')}_id".to_sym
232
+ if !foreign_key
233
+ if parent_dao.nil?
234
+ raise ArgumentError.new("foreign_key should be provided for :#{assoc_name} association")
235
+ end
236
+
237
+ foreign_key = foreign_key_from_dao(parent_dao)
238
+ end
232
239
 
233
240
  root_ids = list.map(&:"#{primary_key}")
234
241
 
@@ -343,5 +350,11 @@ module ReeDao
343
350
 
344
351
  parent.agg_caller.send(method, *args, &block)
345
352
  end
353
+
354
+ private
355
+
356
+ def foreign_key_from_dao(dao)
357
+ "#{dao.first_source_table.to_s.gsub(/s$/, '')}_id".to_sym
358
+ end
346
359
  end
347
360
  end
@@ -87,13 +87,13 @@ module ReeDao
87
87
  Optblock => Any
88
88
  )
89
89
  def association(assoc_type, assoc_name, __opts, &block)
90
- if parent_dao.db.in_transaction? || self.class.sync_mode?
90
+ if parent_dao.nil? || parent_dao.db.in_transaction? || self.class.sync_mode?
91
91
  return if association_is_not_included?(assoc_name) || list.empty?
92
92
 
93
93
  association = Association.new(self, parent_dao, list, **global_opts)
94
94
 
95
95
  if assoc_type == :field
96
- association.handle_field(assoc_name, __opts)
96
+ association.handle_field(__opts)
97
97
  else
98
98
  association.load(assoc_type, assoc_name, **get_assoc_opts(__opts), &block)
99
99
  end
@@ -48,7 +48,8 @@ class ReeDao::PgJsonb < ReeMapper::AbstractWrapper
48
48
  Float,
49
49
  String,
50
50
  Bool,
51
- NilClass
51
+ NilClass,
52
+ Rational,
52
53
  ]
53
54
  ).throws(ReeMapper::TypeError)
54
55
  def db_load(value, name:, role: nil, fields_filters: [])
@@ -26,3 +26,11 @@ module ReeDao
26
26
  ENV.has_key?("REE_DAO_SYNC_ASSOCIATIONS") && ENV["REE_DAO_SYNC_ASSOCIATIONS"] == "true"
27
27
  end
28
28
  end
29
+
30
+ # ReeEnum::Value#sql_literal is used to properly serialize enum values
31
+ # for database queries
32
+ class ReeEnum::Value
33
+ def sql_literal(*)
34
+ mapped_value.to_s
35
+ end
36
+ end
@@ -130,8 +130,7 @@ RSpec.describe :agg do
130
130
  end
131
131
 
132
132
  def some_method(list)
133
- # puts list.map(&:id)
134
- # puts list.map { _1.class.name }
133
+ list.each { _1.some_field = :some_value if _1.respond_to?(:some_field=) }
135
134
  end
136
135
 
137
136
  def passport_opts
@@ -978,4 +977,20 @@ RSpec.describe :agg do
978
977
  res = agg(users, users.where(organization_id: organization.id))
979
978
  expect(res.count).to eq(2)
980
979
  }
980
+
981
+ context "when sync mode enabled" do
982
+ it {
983
+ organization = ReeDaoAggTest::Organization.new(name: "Test Org")
984
+ organizations.put(organization)
985
+ user = ReeDaoAggTest::User.new(name: "John", age: 33, organization_id: organization.id)
986
+ users.put(user)
987
+
988
+ allow(user).to receive(:some_field=)
989
+ expect(user).to receive(:some_field=).with(:some_value)
990
+
991
+ ENV['REE_DAO_SYNC_ASSOCIATIONS'] = "true"
992
+ res = agg_users.([user])
993
+ ENV.delete('REE_DAO_SYNC_ASSOCIATIONS')
994
+ }
995
+ end
981
996
  end
@@ -29,6 +29,7 @@ RSpec.describe 'ReeDao::PgJsonb' do
29
29
  pg_jsonb? :number, integer
30
30
  pg_jsonb? :boolean, bool
31
31
  pg_jsonb? :any, any
32
+ pg_jsonb? :rational, rational
32
33
  end
33
34
  }
34
35
 
@@ -39,13 +40,15 @@ RSpec.describe 'ReeDao::PgJsonb' do
39
40
  numbers: [1, 2],
40
41
  figures: [{ coords: 'x=1,y=1' }],
41
42
  number: 1,
42
- boolean: true
43
+ boolean: true,
44
+ rational: Rational("1/3"),
43
45
  })).to eq({
44
46
  payload: { key: 'key' },
45
47
  numbers: [1, 2],
46
48
  figures: [{ coords: 'x=1,y=1' }],
47
49
  number: 1,
48
- boolean: true
50
+ boolean: true,
51
+ rational: "1/3",
49
52
  })
50
53
  }
51
54
 
@@ -69,13 +72,15 @@ RSpec.describe 'ReeDao::PgJsonb' do
69
72
  numbers: Sequel::Postgres::JSONBArray.new([1, 2]),
70
73
  figures: Sequel::Postgres::JSONBArray.new([{ coords: 'x=1,y=1' }]),
71
74
  number: 1,
72
- boolean: true
75
+ boolean: true,
76
+ rational: "1/3"
73
77
  })).to eq({
74
78
  payload: { key: 'key' },
75
79
  numbers: [1, 2],
76
80
  figures: [{ coords: 'x=1,y=1' }],
77
81
  number: 1,
78
- boolean: true
82
+ boolean: true,
83
+ rational: Rational("1/3"),
79
84
  })
80
85
  }
81
86
 
@@ -16,10 +16,6 @@ class ReeEnum::Value
16
16
  value
17
17
  end
18
18
 
19
- def to_sql
20
- mapped_value
21
- end
22
-
23
19
  def as_json(*args)
24
20
  to_s
25
21
  end
@@ -5,8 +5,8 @@ class ReeI18n::SetLocale
5
5
 
6
6
  fn :set_locale
7
7
 
8
- contract(Symbol => Symbol).throws(I18n::InvalidLocale)
8
+ contract(Or[Symbol, String] => Symbol).throws(I18n::InvalidLocale)
9
9
  def call(locale)
10
- I18n.locale = locale
10
+ I18n.locale = locale.to_sym
11
11
  end
12
12
  end
@@ -27,6 +27,7 @@ class ReeMapper::BuildMapperFactory
27
27
  klass.register_type(:integer, ReeMapper::Integer.new)
28
28
  klass.register_type(:string, ReeMapper::String.new)
29
29
  klass.register_type(:any, ReeMapper::Any.new)
30
+ klass.register_type(:rational, ReeMapper::Rational.new)
30
31
 
31
32
  klass.register_wrapper(:array, ReeMapper::Array)
32
33
 
@@ -12,8 +12,8 @@ class ReeMapper::Float < ReeMapper::AbstractType
12
12
 
13
13
  contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Float).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
14
  def cast(value, name:, role: nil)
15
- if value.is_a?(Float)
16
- value
15
+ if value.is_a?(Numeric)
16
+ value.to_f
17
17
  elsif value.is_a?(String)
18
18
  begin
19
19
  Float(value)
@@ -0,0 +1,39 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ReeMapper::Rational < ReeMapper::AbstractType
4
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Rational).throws(ReeMapper::TypeError)
5
+ def serialize(value, name:, role: nil)
6
+ if value.is_a?(Rational)
7
+ value
8
+ else
9
+ raise ReeMapper::TypeError, "`#{name}` should be a rational"
10
+ end
11
+ end
12
+
13
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Rational).throws(ReeMapper::CoercionError, ReeMapper::TypeError)
14
+ def cast(value, name:, role: nil)
15
+ if value.is_a?(Rational)
16
+ value
17
+ elsif value.is_a?(String)
18
+ begin
19
+ Rational(value)
20
+ rescue ArgumentError, ZeroDivisionError => e
21
+ raise ReeMapper::CoercionError, "`#{name}` is invalid rational"
22
+ end
23
+ elsif value.is_a?(Numeric)
24
+ Rational(value)
25
+ else
26
+ raise ReeMapper::TypeError, "`#{name}` should be a rational"
27
+ end
28
+ end
29
+
30
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => String)
31
+ def db_dump(value, name:, role: nil)
32
+ serialize(value, name: name, role: role).to_s
33
+ end
34
+
35
+ contract(Any, Kwargs[name: String, role: Nilor[Symbol, ArrayOf[Symbol]]] => Rational)
36
+ def db_load(value, name:, role: nil)
37
+ cast(value, name: name, role: role)
38
+ end
39
+ end
@@ -34,6 +34,7 @@ module ReeMapper
34
34
  require_relative 'ree_mapper/types/float'
35
35
  require_relative 'ree_mapper/types/integer'
36
36
  require_relative 'ree_mapper/types/string'
37
+ require_relative 'ree_mapper/types/rational'
37
38
 
38
39
  require_relative 'ree_mapper/strategy_outputs/strategy_output'
39
40
  require_relative 'ree_mapper/strategy_outputs/object_output'
@@ -32,7 +32,11 @@ RSpec.describe 'ReeMapper::Float' do
32
32
  }
33
33
 
34
34
  it {
35
- expect(mapper.db_load({ float: BigDecimal("1.1") })).to eq({ float: 1.1 })
35
+ expect(mapper.cast({ float: BigDecimal("1.1") })).to eq({ float: 1.1 })
36
+ }
37
+
38
+ it {
39
+ expect(mapper.cast({ float: 1 })).to eq({ float: 1.0 })
36
40
  }
37
41
 
38
42
  it {
@@ -40,7 +44,7 @@ RSpec.describe 'ReeMapper::Float' do
40
44
  }
41
45
 
42
46
  it {
43
- expect { mapper.db_load({ float: '1.1a' }) }.to raise_error(ReeMapper::CoercionError, '`float` is invalid float')
47
+ expect { mapper.cast({ float: '1.1a' }) }.to raise_error(ReeMapper::CoercionError, '`float` is invalid float')
44
48
  }
45
49
 
46
50
  it {
@@ -97,6 +101,10 @@ RSpec.describe 'ReeMapper::Float' do
97
101
  expect(mapper.db_load({ float: BigDecimal("1.1") })).to eq({ float: 1.1 })
98
102
  }
99
103
 
104
+ it {
105
+ expect(mapper.db_load({ float: 1 })).to eq({ float: 1.0 })
106
+ }
107
+
100
108
  it {
101
109
  expect { mapper.db_load({ float: 'a1.1' }) }.to raise_error(ReeMapper::CoercionError, '`float` is invalid float')
102
110
  }
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+ require 'bigdecimal'
3
+
4
+ RSpec.describe 'ReeMapper::Rational' do
5
+ link :build_mapper_factory, from: :ree_mapper
6
+ link :build_mapper_strategy, from: :ree_mapper
7
+
8
+ let(:mapper_factory) {
9
+ build_mapper_factory(
10
+ strategies: [
11
+ build_mapper_strategy(method: :cast, dto: Hash),
12
+ build_mapper_strategy(method: :serialize, dto: Hash),
13
+ build_mapper_strategy(method: :db_dump, dto: Hash),
14
+ build_mapper_strategy(method: :db_load, dto: Hash)
15
+ ]
16
+ )
17
+ }
18
+
19
+ let(:mapper) {
20
+ mapper_factory.call.use(:cast).use(:serialize).use(:db_dump).use(:db_load) {
21
+ rational :rational
22
+ }
23
+ }
24
+
25
+ describe '#cast' do
26
+ it {
27
+ expect(mapper.cast({ rational: Rational("1/3") })).to eq({ rational: Rational("1/3") })
28
+ }
29
+
30
+ it {
31
+ expect(mapper.cast({ rational: 0.33 })).to eq({ rational: Rational(0.33) })
32
+ }
33
+
34
+ it {
35
+ expect(mapper.cast({ rational: '0.33' })).to eq({ rational: Rational('0.33') })
36
+ }
37
+
38
+ it {
39
+ expect(mapper.cast({ rational: BigDecimal("0.33") })).to eq({ rational: Rational(BigDecimal("0.33")) })
40
+ }
41
+
42
+ it {
43
+ expect { mapper.cast({ rational: 'a333' }) }.to raise_error(ReeMapper::CoercionError, '`rational` is invalid rational')
44
+ }
45
+
46
+ it {
47
+ expect { mapper.cast({ rational: '333a' }) }.to raise_error(ReeMapper::CoercionError, '`rational` is invalid rational')
48
+ }
49
+
50
+ it {
51
+ expect { mapper.cast({ rational: Object.new }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
52
+ }
53
+ end
54
+
55
+ describe '#serialize' do
56
+ it {
57
+ expect(mapper.serialize({ rational: Rational("1/3") })).to eq({ rational: Rational("1/3") })
58
+ }
59
+
60
+ it {
61
+ expect { mapper.serialize({ rational: '1/3' }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
62
+ }
63
+
64
+ it {
65
+ expect { mapper.serialize({ rational: nil }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
66
+ }
67
+
68
+ it {
69
+ expect { mapper.serialize({ rational: Object.new }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
70
+ }
71
+ end
72
+
73
+ describe '#db_dump' do
74
+ it {
75
+ expect(mapper.db_dump({ rational: Rational("1/3") })).to eq({ rational: "1/3" })
76
+ }
77
+
78
+ it {
79
+ expect { mapper.db_dump({ rational: '1/3' }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
80
+ }
81
+
82
+ it {
83
+ expect { mapper.db_dump({ rational: nil }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
84
+ }
85
+
86
+ it {
87
+ expect { mapper.db_dump({ rational: Object.new }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
88
+ }
89
+ end
90
+
91
+ describe '#db_load' do
92
+ it {
93
+ expect(mapper.db_load({ rational: Rational("1/3") })).to eq({ rational: Rational("1/3") })
94
+ }
95
+
96
+ it {
97
+ expect(mapper.db_load({ rational: 0.33 })).to eq({ rational: Rational(0.33) })
98
+ }
99
+
100
+ it {
101
+ expect(mapper.db_load({ rational: '0.33' })).to eq({ rational: Rational('0.33') })
102
+ }
103
+
104
+ it {
105
+ expect(mapper.db_load({ rational: BigDecimal("0.33") })).to eq({ rational: Rational(BigDecimal("0.33")) })
106
+ }
107
+
108
+ it {
109
+ expect { mapper.db_load({ rational: 'a333' }) }.to raise_error(ReeMapper::CoercionError, '`rational` is invalid rational')
110
+ }
111
+
112
+ it {
113
+ expect { mapper.db_load({ rational: '333a' }) }.to raise_error(ReeMapper::CoercionError, '`rational` is invalid rational')
114
+ }
115
+
116
+ it {
117
+ expect { mapper.db_load({ rational: Object.new }) }.to raise_error(ReeMapper::TypeError, "`rational` should be a rational")
118
+ }
119
+ end
120
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ReeLib
4
- VERSION = "1.0.70"
4
+ VERSION = "1.0.72"
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.70
4
+ version: 1.0.72
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-26 00:00:00.000000000 Z
11
+ date: 2023-08-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ree
@@ -1022,6 +1022,7 @@ files:
1022
1022
  - lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/date_time.rb
1023
1023
  - lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/float.rb
1024
1024
  - lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/integer.rb
1025
+ - lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/rational.rb
1025
1026
  - lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/string.rb
1026
1027
  - lib/ree_lib/packages/ree_mapper/package/ree_mapper/types/time.rb
1027
1028
  - lib/ree_lib/packages/ree_mapper/package/ree_mapper/wrappers/abstract_wrapper.rb
@@ -1042,6 +1043,7 @@ files:
1042
1043
  - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/float_spec.rb
1043
1044
  - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/hash_spec.rb
1044
1045
  - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/integer_spec.rb
1046
+ - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/rational_spec.rb
1045
1047
  - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/string_spec.rb
1046
1048
  - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/time_spec.rb
1047
1049
  - lib/ree_lib/packages/ree_mapper/spec/ree_mapper/types/type_options_spec.rb