serega 0.17.0 → 0.18.0
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/README.md +124 -77
- data/VERSION +1 -1
- data/lib/serega/object_serializer.rb +1 -1
- data/lib/serega/plugins/batch/batch.rb +11 -56
- data/lib/serega/plugins/batch/lib/batch_config.rb +13 -21
- data/lib/serega/plugins/batch/lib/modules/attribute_normalizer.rb +10 -10
- data/lib/serega/plugins/batch/lib/modules/object_serializer.rb +2 -2
- data/lib/serega/plugins/batch/lib/modules/plan_point.rb +2 -19
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_id_method.rb +43 -0
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb +21 -5
- data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +10 -11
- metadata +4 -4
- data/lib/serega/plugins/batch/lib/validations/check_batch_opt_key.rb +0 -43
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 60cc0f4e593d4600bf316e9c18bd93804008e28deebd5f51c231b632bb3a4eff
|
4
|
+
data.tar.gz: e3bdc8e6a0489a14916d84781dcf61c6a82dedb246a0b5366f324d78ca81d9b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 879f46f3bface078c156ad0c89e71b4abc08945754034235d03a688c5613e549d477ae1d24bfa6d0f2c44de1def6266d9b18677ab9fab53ef8341510075806d5
|
7
|
+
data.tar.gz: 45b302b1efc001b9ff3ef35bb9d71bf05e3dcfffbfd35938cf938448b308e9c6c0f74a8f1c1eeceabf8a3bd0eb759f50dd053948664565fbeef2f4b8502841b2
|
data/README.md
CHANGED
@@ -539,118 +539,165 @@ UserSerializer.to_h(user)
|
|
539
539
|
|
540
540
|
### Plugin :batch
|
541
541
|
|
542
|
-
|
542
|
+
Must be used to omit N+1 when loading attributes values.
|
543
543
|
|
544
|
-
|
544
|
+
User must provide batch loader object to attribute -
|
545
|
+
`attribute :foo, batch: {loader: SomeLoader, id_method: :id}`.
|
545
546
|
|
546
|
-
|
547
|
-
- load counters for multiple objects
|
548
|
-
- make any heavy calculations for multiple objects only once
|
549
|
-
|
550
|
-
After including plugin, attributes gain new `:batch` option:
|
547
|
+
Result must be returned as Hash, where each key is one of provided ids.
|
551
548
|
|
552
549
|
```ruby
|
553
|
-
|
550
|
+
class AppSerializer
|
551
|
+
plugin :batch
|
552
|
+
end
|
553
|
+
|
554
|
+
class UserSerializer < AppSerializer
|
555
|
+
attribute :comments_count,
|
556
|
+
batch: { loader: SomeLoader, id_method: :id }
|
557
|
+
|
558
|
+
attribute :company,
|
559
|
+
batch: { loader: SomeLoader, id_method: :id },
|
560
|
+
serializer: CompanySerializer
|
561
|
+
end
|
554
562
|
```
|
555
563
|
|
556
|
-
|
564
|
+
#### Option :loader
|
557
565
|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
Key is optional if plugin was defined with `default_key` option.
|
562
|
-
- `default` (optional) - Default value for attribute.
|
563
|
-
By default it is `nil` or `[]` when attribute has option `many: true`
|
564
|
-
(ex: `attribute :tags, many: true, batch: { ... }`).
|
566
|
+
Loaders can be defined as a Proc, a callable value or a named Symbol
|
567
|
+
Named loaders should be predefined with
|
568
|
+
`config.batch.define(:loader_name) { |ids| ... })`
|
565
569
|
|
566
|
-
|
567
|
-
defined using `config.batch.define(:loader_name) { ... }` method.
|
570
|
+
Loader can accept 1 to 3 arguments:
|
568
571
|
|
569
|
-
|
572
|
+
1. List of ids (each id will be found by using `:id_method` option)
|
573
|
+
1. Context
|
574
|
+
1. PlanPoint - a special object containing information about current
|
575
|
+
attribute and all children and parent attributes. It can be used to preload
|
576
|
+
required associations to batch values.
|
577
|
+
See [example](examples/batch_loader.rb) how
|
578
|
+
to find required preloads when using with `:preloads` plugin.
|
570
579
|
|
571
|
-
|
572
|
-
|
580
|
+
```ruby
|
581
|
+
class AppSerializer < Serega
|
582
|
+
plugin :batch, id_method: :id
|
583
|
+
end
|
573
584
|
|
574
|
-
|
585
|
+
class UserSerializer < Serega
|
586
|
+
# Define loader as callable object
|
587
|
+
attribute :comments_count,
|
588
|
+
batch: { loader: CountLoader }
|
575
589
|
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
used for all attributes with :batch option specified.
|
590
|
+
# Define loader as a Proc
|
591
|
+
attribute :comments_count,
|
592
|
+
batch: { loader: proc { |ids| CountLoader.call(ids) } }
|
580
593
|
|
581
|
-
|
582
|
-
|
594
|
+
# Define loader as a Symbol
|
595
|
+
config.batch.define(:comments_count_loader) { |ids| CountLoader.call(ids }
|
596
|
+
attribute :comments_count, batch: { loader: :comments_count_loader }
|
597
|
+
end
|
598
|
+
|
599
|
+
class CountLoader
|
600
|
+
def self.call(user_ids)
|
601
|
+
Comment.where(user_id: user_ids).group(:user_id).count
|
602
|
+
end
|
603
|
+
end
|
583
604
|
```
|
584
605
|
|
585
|
-
|
606
|
+
#### Option :id_method
|
607
|
+
|
608
|
+
Batch plugin can be added with global `:id_method` option. It can be a Symbol,
|
609
|
+
Proc or any callable value, which can accept current object and current context.
|
586
610
|
|
587
611
|
```ruby
|
588
|
-
class
|
589
|
-
plugin :batch,
|
612
|
+
class SomeSerializer
|
613
|
+
plugin :batch, id_method: :id
|
590
614
|
end
|
591
615
|
|
592
616
|
class UserSerializer < AppSerializer
|
593
|
-
|
594
|
-
|
617
|
+
attribute :comments_count,
|
618
|
+
batch: { loader: CommentsCountBatchLoader } # no :id_method here anymore
|
619
|
+
|
620
|
+
attribute :company,
|
621
|
+
batch: { loader: UserCompanyBatchLoader }, # no :id_method here anymore
|
622
|
+
serializer: CompanySerializer
|
595
623
|
end
|
624
|
+
|
596
625
|
```
|
597
626
|
|
598
|
-
|
599
|
-
|
600
|
-
`:batch` attributes, but have nested serializers, that have some. For example
|
601
|
-
when you serialize `User -> Album -> Song` and Song has `:batch` attribute, then
|
602
|
-
`:batch` plugin must be added to the User serializer also. \
|
603
|
-
Best way would be to create one parent `AppSerializer < Serega` for all your
|
604
|
-
serializers and add `:batch` plugin only to this parent `AppSerializer`
|
627
|
+
However, global `id_method` option can be overwritten via `config.batch.id_method=`
|
628
|
+
method or in specific attributes with `id_method` option.
|
605
629
|
|
606
630
|
```ruby
|
607
|
-
class
|
608
|
-
plugin :batch,
|
631
|
+
class SomeSerializer
|
632
|
+
plugin :batch, id_method: :id # global id_method is `:id`
|
609
633
|
end
|
610
634
|
|
611
|
-
class
|
612
|
-
|
613
|
-
|
614
|
-
loader: CommentsCountBatchLoader, # callable(keys, context, plan_point)
|
615
|
-
key: :id, # can be skipped (as :id value is same as configured :default_key)
|
616
|
-
default: 0
|
617
|
-
}
|
635
|
+
class UserSerializer < AppSerializer
|
636
|
+
# :user_id will be used as default `id_method` for all batch attributes
|
637
|
+
config.batch.id_method = :user_id
|
618
638
|
|
619
|
-
#
|
620
|
-
# `config.batch.define(:posts_comments_counter) { ... }`
|
621
|
-
#
|
622
|
-
# Loader will receive array of ids, as `default_key: :id` plugin option was specified.
|
623
|
-
# Default value for not found counters is nil, as `:default` option not defined
|
639
|
+
# id_method is :user_id
|
624
640
|
attribute :comments_count,
|
625
|
-
batch: { loader:
|
641
|
+
batch: { loader: CommentsCountBatchLoader }
|
626
642
|
|
627
|
-
# Define batch loader with serializer
|
628
|
-
attribute :comments,
|
629
|
-
serializer: CommentSerializer,
|
630
|
-
batch: {loader: :posts_comments, default: []}
|
631
643
|
|
632
|
-
#
|
633
|
-
|
634
|
-
|
635
|
-
end
|
644
|
+
# id_method is :user_id
|
645
|
+
attribute :company,
|
646
|
+
batch: { loader: UserCompanyBatchLoader }, serializer: CompanySerializer
|
636
647
|
|
637
|
-
#
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
648
|
+
# id_method is :uuid
|
649
|
+
attribute :points_amount,
|
650
|
+
batch: { loader: PointsBatchLoader, id_method: :uuid }
|
651
|
+
end
|
652
|
+
```
|
653
|
+
|
654
|
+
#### Option :default
|
655
|
+
|
656
|
+
The default value for attributes without found value can be specified via
|
657
|
+
`:default` option. By default attributes without found value will be
|
658
|
+
serialized as `nil`. Attribute marked as `many: true` will be
|
659
|
+
serialized as empty array `[]`
|
660
|
+
|
661
|
+
```ruby
|
662
|
+
class UserSerializer < AppSerializer
|
663
|
+
# Missing values become empty arrays, as `many: true` option specified
|
664
|
+
attribute :companies,
|
665
|
+
batch: {loader: proc {}},
|
666
|
+
serializer: CompanySerializer,
|
667
|
+
many: true
|
668
|
+
|
669
|
+
# Missing values become `0` as specified directly
|
670
|
+
attribute :points_amount,
|
671
|
+
batch: { loader: proc {}, default: 0 }
|
672
|
+
end
|
673
|
+
```
|
674
|
+
|
675
|
+
Batch attributes can be marked as hidden by default if plugin specified with
|
676
|
+
`auto_hide` option. Also `auto_hide` option can be changed with
|
677
|
+
`config.batch.auto_hide=` method.
|
678
|
+
|
679
|
+
Look at [select serialized fields](#selecting-fields) for more information
|
680
|
+
about hiding/showing attributes.
|
681
|
+
|
682
|
+
```ruby
|
683
|
+
class AppSerializer
|
684
|
+
plugin :batch, auto_hide: true
|
685
|
+
end
|
686
|
+
|
687
|
+
class UserSerializer < AppSerializer
|
688
|
+
config.batch.auto_hide = false
|
651
689
|
end
|
652
690
|
```
|
653
691
|
|
692
|
+
---
|
693
|
+
⚠️ ATTENTION: `Batch` plugin must be added to all serializers that have
|
694
|
+
`:batch` attributes inside nested serializers. For example when you serialize
|
695
|
+
`User -> Album -> Song` and Song has `batch` attribute, then
|
696
|
+
`batch` plugin must be added to the User serializer also.
|
697
|
+
|
698
|
+
Best way would be to create one parent `AppSerializer < Serega` serializer
|
699
|
+
and add `:batch` plugin once to this parent serializer.
|
700
|
+
|
654
701
|
### Plugin :root
|
655
702
|
|
656
703
|
Allows to add root key to your serialized data
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.18.0
|
@@ -5,62 +5,17 @@ class Serega
|
|
5
5
|
#
|
6
6
|
# Plugin `:batch`
|
7
7
|
#
|
8
|
-
#
|
8
|
+
# Must be used to omit N+1 when loading attributes values.
|
9
9
|
#
|
10
|
-
#
|
11
|
-
# - load associations for multiple objects
|
12
|
-
# - load counters for multiple objects
|
13
|
-
# - make any heavy calculations for multiple objects only once
|
10
|
+
# @example Quick example
|
14
11
|
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
# - `key` (required) [Symbol, Proc, callable] - Defines current object identifier.
|
19
|
-
# Later `loader` will accept array of `keys` to find `values`.
|
20
|
-
# - `loader` (required) [Symbol, Proc, callable] - Defines how to fetch values for
|
21
|
-
# batch of keys. Receives 3 parameters: keys, context, plan_point.
|
22
|
-
# - `default` (optional) - Default value for attribute.
|
23
|
-
# By default it is `nil` or `[]` when attribute has option `many: true`
|
24
|
-
#
|
25
|
-
# If `:loader` was defined using name (as Symbol) then batch loader must be
|
26
|
-
# defined in serializer config: `config.batch.define(:loader_name) { ... }` method.
|
27
|
-
#
|
28
|
-
# *Result of this `:loader` callable must be a **Hash** where*:
|
29
|
-
# - keys - provided keys
|
30
|
-
# - values - values for according keys
|
31
|
-
#
|
32
|
-
# `Batch` plugin can be defined with two specific attributes:
|
33
|
-
# - `auto_hide: true` - Marks attributes with defined :batch as hidden, so it
|
34
|
-
# will not be serialized by default
|
35
|
-
# - `default_key: :id` - Set default object key (in this case :id) that will be used for all attributes with :batch option specified.
|
36
|
-
#
|
37
|
-
# This options (`auto_hide`, `default_key`) also can be set as config options in
|
38
|
-
# any nested serializer.
|
39
|
-
#
|
40
|
-
# @example
|
41
|
-
# class PostSerializer < Serega
|
42
|
-
# plugin :batch, auto_hide: true, default_key: :id
|
43
|
-
#
|
44
|
-
# # Define batch loader via callable class, it must accept three args (keys, context, plan_point)
|
45
|
-
# attribute :comments_count, batch: { loader: PostCommentsCountBatchLoader, default: 0}
|
46
|
-
#
|
47
|
-
# # Define batch loader via Symbol, later we should define this loader via config.batch.define(:posts_comments_counter) { ... }
|
48
|
-
# attribute :comments_count, batch: { loader: :posts_comments_counter, default: 0}
|
49
|
-
#
|
50
|
-
# # Define batch loader with serializer
|
51
|
-
# attribute :comments, serializer: CommentSerializer, batch: { loader: :posts_comments, default: []}
|
52
|
-
#
|
53
|
-
# # Resulted block must return hash like { key => value(s) }
|
54
|
-
# config.batch.define(:posts_comments_counter) do |keys|
|
55
|
-
# Comment.group(:post_id).where(post_id: keys).count
|
56
|
-
# end
|
12
|
+
# class AppSerializer
|
13
|
+
# plugin :batch, id_method: :id
|
14
|
+
# end
|
57
15
|
#
|
58
|
-
#
|
59
|
-
#
|
60
|
-
#
|
61
|
-
# config.batch.define(:posts_comments) do |keys, context, plan_point|
|
62
|
-
# Comment.where(post_id: keys).where(is_spam: false).group_by(&:post_id)
|
63
|
-
# end
|
16
|
+
# class UserSerializer < AppSerializer
|
17
|
+
# attribute :comments_count, batch: { loader: CommentsCountBatchLoader, default: 0 }
|
18
|
+
# attribute :company, serializer: CompanySerializer, batch: { loader: UserCompanyBatchLoader }
|
64
19
|
# end
|
65
20
|
#
|
66
21
|
module Batch
|
@@ -88,7 +43,7 @@ class Serega
|
|
88
43
|
require_relative "lib/modules/config"
|
89
44
|
require_relative "lib/modules/object_serializer"
|
90
45
|
require_relative "lib/modules/plan_point"
|
91
|
-
require_relative "lib/validations/
|
46
|
+
require_relative "lib/validations/check_batch_opt_id_method"
|
92
47
|
require_relative "lib/validations/check_batch_opt_loader"
|
93
48
|
require_relative "lib/validations/check_opt_batch"
|
94
49
|
|
@@ -138,9 +93,9 @@ class Serega
|
|
138
93
|
|
139
94
|
config = serializer_class.config
|
140
95
|
config.attribute_keys << :batch
|
141
|
-
config.opts[:batch] = {loaders: {},
|
96
|
+
config.opts[:batch] = {loaders: {}, id_method: nil, auto_hide: false}
|
142
97
|
config.batch.auto_hide = opts[:auto_hide] if opts.key?(:auto_hide)
|
143
|
-
config.batch.
|
98
|
+
config.batch.id_method = opts[:id_method] if opts.key?(:id_method)
|
144
99
|
end
|
145
100
|
|
146
101
|
#
|
@@ -17,8 +17,8 @@ class Serega
|
|
17
17
|
# Defines batch loader
|
18
18
|
#
|
19
19
|
# @param loader_name [Symbol] Batch loader name, that is used when defining attribute with batch loader.
|
20
|
-
# @param block [Proc] Block that can accept 3 parameters -
|
21
|
-
# and returns hash
|
20
|
+
# @param block [Proc] Block that can accept 3 parameters - ids, context, plan_point
|
21
|
+
# and returns hash with ids as keys and values are batch loaded objects
|
22
22
|
#
|
23
23
|
# @return [void]
|
24
24
|
#
|
@@ -32,7 +32,7 @@ class Serega
|
|
32
32
|
params_count = SeregaUtils::ParamsCount.call(callable, max_count: 3)
|
33
33
|
|
34
34
|
if params_count > 3
|
35
|
-
raise SeregaError, "Batch loader can have maximum 3 parameters (
|
35
|
+
raise SeregaError, "Batch loader can have maximum 3 parameters (ids, context, plan)"
|
36
36
|
end
|
37
37
|
|
38
38
|
loaders[loader_name] = callable
|
@@ -44,16 +44,6 @@ class Serega
|
|
44
44
|
opts[:loaders]
|
45
45
|
end
|
46
46
|
|
47
|
-
#
|
48
|
-
# Finds previously defined batch loader by name
|
49
|
-
#
|
50
|
-
# @param loader_name [Symbol]
|
51
|
-
#
|
52
|
-
# @return [Proc] batch loader block
|
53
|
-
def fetch_loader(loader_name)
|
54
|
-
loaders[loader_name] || (raise SeregaError, "Batch loader with name `#{loader_name.inspect}` was not defined. Define example: config.batch.define(:#{loader_name}) { |keys| ... }")
|
55
|
-
end
|
56
|
-
|
57
47
|
# Shows option to auto hide attributes with :batch specified
|
58
48
|
# @return [Boolean, nil] option value
|
59
49
|
def auto_hide
|
@@ -67,17 +57,19 @@ class Serega
|
|
67
57
|
opts[:auto_hide] = value
|
68
58
|
end
|
69
59
|
|
70
|
-
# Shows
|
71
|
-
# @return [Symbol, nil]
|
72
|
-
def
|
73
|
-
opts[:
|
60
|
+
# Shows method name or callable object needed to get object identifier for batch load
|
61
|
+
# @return [Symbol, #call, nil] Default method name or callable object to get identifier
|
62
|
+
def id_method
|
63
|
+
opts[:id_method]
|
74
64
|
end
|
75
65
|
|
76
|
-
#
|
66
|
+
# Sets new identifier method name or callable value needed for batch loading
|
67
|
+
#
|
68
|
+
# @param value [Symbol, #call] New :id_method value
|
77
69
|
# @return [Boolean] New option value
|
78
|
-
def
|
79
|
-
|
80
|
-
opts[:
|
70
|
+
def id_method=(value)
|
71
|
+
CheckBatchOptIdMethod.call(value)
|
72
|
+
opts[:id_method] = value
|
81
73
|
end
|
82
74
|
end
|
83
75
|
end
|
@@ -44,27 +44,27 @@ class Serega
|
|
44
44
|
|
45
45
|
loader = prepare_batch_loader(batch[:loader])
|
46
46
|
|
47
|
-
|
48
|
-
|
47
|
+
id_method = batch[:id_method] || self.class.serializer_class.config.batch.id_method
|
48
|
+
id_method = prepare_batch_id_method(id_method)
|
49
49
|
|
50
50
|
default = batch.fetch(:default) { many ? FROZEN_EMPTY_ARRAY : nil }
|
51
51
|
|
52
|
-
{loader: loader,
|
52
|
+
{loader: loader, id_method: id_method, default: default}
|
53
53
|
end
|
54
54
|
|
55
|
-
def
|
56
|
-
return proc { |object| object.public_send(
|
55
|
+
def prepare_batch_id_method(id_method)
|
56
|
+
return proc { |object| object.public_send(id_method) } if id_method.is_a?(Symbol)
|
57
57
|
|
58
|
-
params_count = SeregaUtils::ParamsCount.call(
|
58
|
+
params_count = SeregaUtils::ParamsCount.call(id_method, max_count: 2)
|
59
59
|
case params_count
|
60
|
-
when 0 then proc {
|
61
|
-
when 1 then proc { |object|
|
62
|
-
else
|
60
|
+
when 0 then proc { id_method.call }
|
61
|
+
when 1 then proc { |object| id_method.call(object) }
|
62
|
+
else id_method
|
63
63
|
end
|
64
64
|
end
|
65
65
|
|
66
66
|
def prepare_batch_loader(loader)
|
67
|
-
|
67
|
+
loader = self.class.serializer_class.config.batch.loaders.fetch(loader) if loader.is_a?(Symbol)
|
68
68
|
|
69
69
|
params_count = SeregaUtils::ParamsCount.call(loader, max_count: 3)
|
70
70
|
case params_count
|
@@ -19,8 +19,8 @@ class Serega
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def remember_key_for_batch_loading(batch, object, point, container)
|
22
|
-
|
23
|
-
batch_loader(point).remember(
|
22
|
+
id = batch[:id_method].call(object, context)
|
23
|
+
batch_loader(point).remember(id, container)
|
24
24
|
container[point.name] = nil # Reserve attribute place in resulted hash. We will set correct value later
|
25
25
|
end
|
26
26
|
|
@@ -13,25 +13,8 @@ class Serega
|
|
13
13
|
# Returns attribute :batch option with prepared loader
|
14
14
|
# @return [Hash] attribute :batch option
|
15
15
|
#
|
16
|
-
|
17
|
-
|
18
|
-
private
|
19
|
-
|
20
|
-
def set_normalized_vars
|
21
|
-
super
|
22
|
-
@batch = prepare_batch
|
23
|
-
end
|
24
|
-
|
25
|
-
def prepare_batch
|
26
|
-
batch = attribute.batch
|
27
|
-
if batch
|
28
|
-
loader = batch[:loader]
|
29
|
-
if loader.is_a?(Symbol)
|
30
|
-
batch_config = attribute.class.serializer_class.config.batch
|
31
|
-
batch[:loader] = batch_config.fetch_loader(loader)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
batch
|
16
|
+
def batch
|
17
|
+
attribute.batch
|
35
18
|
end
|
36
19
|
end
|
37
20
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Batch
|
6
|
+
#
|
7
|
+
# Validator for option :id_method in attribute :batch option
|
8
|
+
#
|
9
|
+
class CheckBatchOptIdMethod
|
10
|
+
class << self
|
11
|
+
#
|
12
|
+
# Checks option :id_method of attribute :batch option
|
13
|
+
#
|
14
|
+
# @param id [nil, #call] Attribute :batch option :id_method
|
15
|
+
#
|
16
|
+
# @raise [SeregaError] validation error
|
17
|
+
#
|
18
|
+
# @return [void]
|
19
|
+
#
|
20
|
+
def call(id)
|
21
|
+
return if id.is_a?(Symbol)
|
22
|
+
|
23
|
+
raise SeregaError, must_be_callable unless id.respond_to?(:call)
|
24
|
+
|
25
|
+
SeregaValidations::Utils::CheckExtraKeywordArg.call(id, "batch option :id_method")
|
26
|
+
params_count = SeregaUtils::ParamsCount.call(id, max_count: 2)
|
27
|
+
raise SeregaError, params_count_error if params_count > 2
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def params_count_error
|
33
|
+
"Invalid :batch option :id_method. It can accept maximum 2 parameters (object, context)"
|
34
|
+
end
|
35
|
+
|
36
|
+
def must_be_callable
|
37
|
+
"Invalid :batch option :id_method. It must be a Symbol, a Proc or respond to #call"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -17,9 +17,27 @@ class Serega
|
|
17
17
|
#
|
18
18
|
# @return [void]
|
19
19
|
#
|
20
|
-
def call(loader)
|
21
|
-
|
20
|
+
def call(loader, serializer_class)
|
21
|
+
if loader.is_a?(Symbol)
|
22
|
+
check_symbol(loader, serializer_class)
|
23
|
+
else
|
24
|
+
check_callable(loader)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def check_symbol(loader_name, serializer_class)
|
31
|
+
defined_loaders = serializer_class.config.batch.loaders
|
32
|
+
return if defined_loaders[loader_name]
|
22
33
|
|
34
|
+
raise SeregaError, <<~ERR.strip
|
35
|
+
Please define loader before adding it to attribute.
|
36
|
+
Example: `config.batch.define(:#{loader_name}) { |ids| ... }`
|
37
|
+
ERR
|
38
|
+
end
|
39
|
+
|
40
|
+
def check_callable(loader)
|
23
41
|
raise SeregaError, must_be_callable unless loader.respond_to?(:call)
|
24
42
|
|
25
43
|
SeregaValidations::Utils::CheckExtraKeywordArg.call(loader, ":batch option :loader")
|
@@ -27,10 +45,8 @@ class Serega
|
|
27
45
|
raise SeregaError, params_count_error if params_count > 3
|
28
46
|
end
|
29
47
|
|
30
|
-
private
|
31
|
-
|
32
48
|
def params_count_error
|
33
|
-
"Invalid :batch option :loader. It can accept maximum 3 parameters (
|
49
|
+
"Invalid :batch option :loader. It can accept maximum 3 parameters (ids, context, plan)"
|
34
50
|
end
|
35
51
|
|
36
52
|
def must_be_callable
|
@@ -23,30 +23,29 @@ class Serega
|
|
23
23
|
SeregaValidations::Utils::CheckOptIsHash.call(opts, :batch)
|
24
24
|
|
25
25
|
batch = opts[:batch]
|
26
|
-
SeregaValidations::Utils::CheckAllowedKeys.call(batch, %i[
|
27
|
-
|
28
|
-
check_batch_opt_key(batch, serializer_class)
|
29
|
-
check_batch_opt_loader(batch)
|
26
|
+
SeregaValidations::Utils::CheckAllowedKeys.call(batch, %i[id_method loader default], :batch)
|
30
27
|
|
28
|
+
check_batch_opt_id_method(batch, serializer_class)
|
29
|
+
check_batch_opt_loader(batch, serializer_class)
|
31
30
|
check_usage_with_other_params(opts, block)
|
32
31
|
end
|
33
32
|
|
34
33
|
private
|
35
34
|
|
36
|
-
def
|
37
|
-
return if !batch.key?(:
|
35
|
+
def check_batch_opt_id_method(batch, serializer_class)
|
36
|
+
return if !batch.key?(:id_method) && serializer_class.config.batch.id_method
|
38
37
|
|
39
|
-
|
40
|
-
raise SeregaError, "Option :
|
38
|
+
id_method = batch[:id_method]
|
39
|
+
raise SeregaError, "Option :id_method must present inside :batch option" unless id_method
|
41
40
|
|
42
|
-
|
41
|
+
CheckBatchOptIdMethod.call(id_method)
|
43
42
|
end
|
44
43
|
|
45
|
-
def check_batch_opt_loader(batch)
|
44
|
+
def check_batch_opt_loader(batch, serializer_class)
|
46
45
|
loader = batch[:loader]
|
47
46
|
raise SeregaError, "Option :loader must present inside :batch option" unless loader
|
48
47
|
|
49
|
-
CheckBatchOptLoader.call(loader)
|
48
|
+
CheckBatchOptLoader.call(loader, serializer_class)
|
50
49
|
end
|
51
50
|
|
52
51
|
def check_usage_with_other_params(opts, block)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: serega
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.18.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrey Glushkov
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-11-
|
11
|
+
date: 2023-11-11 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: |
|
14
14
|
JSON Serializer
|
@@ -55,7 +55,7 @@ files:
|
|
55
55
|
- lib/serega/plugins/batch/lib/plugins_extensions/activerecord_preloads.rb
|
56
56
|
- lib/serega/plugins/batch/lib/plugins_extensions/formatters.rb
|
57
57
|
- lib/serega/plugins/batch/lib/plugins_extensions/preloads.rb
|
58
|
-
- lib/serega/plugins/batch/lib/validations/
|
58
|
+
- lib/serega/plugins/batch/lib/validations/check_batch_opt_id_method.rb
|
59
59
|
- lib/serega/plugins/batch/lib/validations/check_batch_opt_loader.rb
|
60
60
|
- lib/serega/plugins/batch/lib/validations/check_opt_batch.rb
|
61
61
|
- lib/serega/plugins/camel_case/camel_case.rb
|
@@ -140,7 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
140
140
|
- !ruby/object:Gem::Version
|
141
141
|
version: '0'
|
142
142
|
requirements: []
|
143
|
-
rubygems_version: 3.4.
|
143
|
+
rubygems_version: 3.4.22
|
144
144
|
signing_key:
|
145
145
|
specification_version: 4
|
146
146
|
summary: JSON Serializer
|
@@ -1,43 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Validator for option :key in attribute :batch option
|
8
|
-
#
|
9
|
-
class CheckBatchOptKey
|
10
|
-
class << self
|
11
|
-
#
|
12
|
-
# Checks option :key of attribute :batch option
|
13
|
-
#
|
14
|
-
# @param key [nil, #call] Attribute :batch option :key
|
15
|
-
#
|
16
|
-
# @raise [SeregaError] validation error
|
17
|
-
#
|
18
|
-
# @return [void]
|
19
|
-
#
|
20
|
-
def call(key)
|
21
|
-
return if key.is_a?(Symbol)
|
22
|
-
|
23
|
-
raise SeregaError, must_be_callable unless key.respond_to?(:call)
|
24
|
-
|
25
|
-
SeregaValidations::Utils::CheckExtraKeywordArg.call(key, "batch option :key")
|
26
|
-
params_count = SeregaUtils::ParamsCount.call(key, max_count: 2)
|
27
|
-
raise SeregaError, params_count_error if params_count > 2
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def params_count_error
|
33
|
-
"Invalid :batch option :key. It can accept maximum 2 parameters (object, context)"
|
34
|
-
end
|
35
|
-
|
36
|
-
def must_be_callable
|
37
|
-
"Invalid :batch option :key. It must be a Symbol, a Proc or respond to :call"
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|