serega 0.10.0 → 0.11.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 +319 -141
- data/VERSION +1 -1
- data/lib/serega/attribute.rb +37 -105
- data/lib/serega/attribute_normalizer.rb +176 -0
- data/lib/serega/config.rb +26 -9
- data/lib/serega/object_serializer.rb +11 -10
- data/lib/serega/plan.rb +128 -0
- data/lib/serega/plan_point.rb +94 -0
- data/lib/serega/plugins/batch/batch.rb +187 -41
- data/lib/serega/plugins/batch/lib/loader.rb +4 -4
- data/lib/serega/plugins/batch/lib/loaders.rb +3 -3
- data/lib/serega/plugins/batch/lib/plugins_extensions/activerecord_preloads.rb +2 -2
- data/lib/serega/plugins/batch/lib/plugins_extensions/formatters.rb +19 -1
- data/lib/serega/plugins/batch/lib/plugins_extensions/preloads.rb +6 -4
- data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +9 -5
- data/lib/serega/plugins/formatters/formatters.rb +28 -31
- data/lib/serega/plugins/if/if.rb +24 -6
- data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +11 -13
- data/lib/serega/plugins/preloads/lib/main_preload_path.rb +2 -2
- data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +21 -15
- data/lib/serega/plugins/preloads/preloads.rb +72 -40
- data/lib/serega/plugins/presenter/presenter.rb +0 -9
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +11 -1
- data/lib/serega/plugins.rb +3 -3
- data/lib/serega/utils/enum_deep_dup.rb +18 -18
- data/lib/serega/utils/enum_deep_freeze.rb +35 -0
- data/lib/serega/utils/to_hash.rb +17 -9
- data/lib/serega.rb +22 -15
- metadata +6 -6
- data/lib/serega/map.rb +0 -91
- data/lib/serega/map_point.rb +0 -66
- data/lib/serega/plugins/batch/lib/batch_option_model.rb +0 -73
- data/lib/serega/plugins/preloads/lib/enum_deep_freeze.rb +0 -26
data/lib/serega/map.rb
DELETED
@@ -1,91 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
#
|
5
|
-
# Constructs map of attributes that should be serialized.
|
6
|
-
# We will traverse this map to construct serialized response.
|
7
|
-
#
|
8
|
-
class SeregaMap
|
9
|
-
#
|
10
|
-
# SeregaMap class methods
|
11
|
-
#
|
12
|
-
module ClassMethods
|
13
|
-
#
|
14
|
-
# Constructs map of attributes that should be serialized.
|
15
|
-
#
|
16
|
-
# @param opts Serialization parameters
|
17
|
-
# @option opts [Hash] :only The only attributes to serialize
|
18
|
-
# @option opts [Hash] :except Attributes to hide
|
19
|
-
# @option opts [Hash] :with Attributes (usually hidden) to serialize additionally
|
20
|
-
#
|
21
|
-
# @return [Array<Serega::SeregaMapPoint>] map
|
22
|
-
#
|
23
|
-
def call(opts)
|
24
|
-
max_cache_size = serializer_class.config.max_cached_map_per_serializer_count
|
25
|
-
return map_for(opts) if max_cache_size.zero?
|
26
|
-
|
27
|
-
cached_map_for(opts, max_cache_size)
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def map_for(opts)
|
33
|
-
construct_map(serializer_class, **modifiers(opts))
|
34
|
-
end
|
35
|
-
|
36
|
-
def cached_map_for(opts, max_cache_size)
|
37
|
-
@cache ||= {}
|
38
|
-
cache_key = construct_cache_key(opts)
|
39
|
-
|
40
|
-
map = @cache[cache_key] ||= map_for(opts)
|
41
|
-
@cache.shift if @cache.length > max_cache_size
|
42
|
-
map
|
43
|
-
end
|
44
|
-
|
45
|
-
def modifiers(opts)
|
46
|
-
{
|
47
|
-
only: opts[:only] || FROZEN_EMPTY_HASH,
|
48
|
-
except: opts[:except] || FROZEN_EMPTY_HASH,
|
49
|
-
with: opts[:with] || FROZEN_EMPTY_HASH
|
50
|
-
}
|
51
|
-
end
|
52
|
-
|
53
|
-
def construct_map(serializer_class, only:, except:, with:)
|
54
|
-
map = []
|
55
|
-
serializer_class.attributes.each do |name, attribute|
|
56
|
-
next unless attribute.visible?(only: only, except: except, with: with)
|
57
|
-
|
58
|
-
nested_points =
|
59
|
-
if attribute.relation?
|
60
|
-
construct_map(
|
61
|
-
attribute.serializer,
|
62
|
-
only: only[name] || FROZEN_EMPTY_HASH,
|
63
|
-
with: with[name] || FROZEN_EMPTY_HASH,
|
64
|
-
except: except[name] || FROZEN_EMPTY_HASH
|
65
|
-
)
|
66
|
-
end
|
67
|
-
|
68
|
-
map << serializer_class::SeregaMapPoint.new(attribute, nested_points)
|
69
|
-
end
|
70
|
-
map
|
71
|
-
end
|
72
|
-
|
73
|
-
def construct_cache_key(opts, cache_key = nil)
|
74
|
-
return nil if opts.empty?
|
75
|
-
|
76
|
-
cache_key ||= +""
|
77
|
-
|
78
|
-
opts.each do |key, nested_opts|
|
79
|
-
cache_key.insert(-1, SeregaUtils::SymbolName.call(key))
|
80
|
-
cache_key.insert(-1, "-")
|
81
|
-
construct_cache_key(nested_opts, cache_key)
|
82
|
-
end
|
83
|
-
|
84
|
-
cache_key
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
extend ClassMethods
|
89
|
-
extend Serega::SeregaHelpers::SerializerClassHelper
|
90
|
-
end
|
91
|
-
end
|
data/lib/serega/map_point.rb
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
#
|
5
|
-
# Combines attribute and nested attributes
|
6
|
-
#
|
7
|
-
class SeregaMapPoint
|
8
|
-
#
|
9
|
-
# SeregaMapPoint instance methods
|
10
|
-
#
|
11
|
-
module InstanceMethods
|
12
|
-
extend Forwardable
|
13
|
-
|
14
|
-
# Shows current attribute
|
15
|
-
# @return [Serega::SeregaAttribute] Current attribute
|
16
|
-
attr_reader :attribute
|
17
|
-
|
18
|
-
# Shows nested points
|
19
|
-
# @return [NilClass, Array<Serega::SeregaMapPoint>] Nested points or nil
|
20
|
-
attr_reader :nested_points
|
21
|
-
|
22
|
-
# @!method name
|
23
|
-
# Attribute `name`
|
24
|
-
# @see Serega::SeregaAttribute::AttributeInstanceMethods#name
|
25
|
-
# @!method value
|
26
|
-
# Attribute `value` block
|
27
|
-
# @see Serega::SeregaAttribute::AttributeInstanceMethods#value
|
28
|
-
# @!method many
|
29
|
-
# Attribute `many` option
|
30
|
-
# @see Serega::SeregaAttribute::AttributeInstanceMethods#many
|
31
|
-
def_delegators :@attribute, :name, :value, :many
|
32
|
-
|
33
|
-
#
|
34
|
-
# Initializes map point
|
35
|
-
#
|
36
|
-
# @param attribute [Serega::SeregaAttribute] Attribute to construct map point
|
37
|
-
# @param nested_points [NilClass, Array<Serega::SeregaMapPoint>] Nested map points for provided attribute
|
38
|
-
#
|
39
|
-
# @return [Serega::SeregaMapPoint] New map point
|
40
|
-
#
|
41
|
-
def initialize(attribute, nested_points)
|
42
|
-
@attribute = attribute
|
43
|
-
@nested_points = nested_points
|
44
|
-
end
|
45
|
-
|
46
|
-
#
|
47
|
-
# Checks if attribute has nested points (is a link to another serializer)
|
48
|
-
#
|
49
|
-
# @return [Boolean] whether attribute has nested points
|
50
|
-
#
|
51
|
-
def has_nested_points?
|
52
|
-
!nested_points.nil?
|
53
|
-
end
|
54
|
-
|
55
|
-
#
|
56
|
-
# @return [Serega::SeregaObjectSerializer] object serializer for nested points
|
57
|
-
#
|
58
|
-
def nested_object_serializer
|
59
|
-
attribute.serializer::SeregaObjectSerializer
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
extend Serega::SeregaHelpers::SerializerClassHelper
|
64
|
-
include InstanceMethods
|
65
|
-
end
|
66
|
-
end
|
@@ -1,73 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Batch
|
6
|
-
#
|
7
|
-
# Combines options and methods needed to load batch for specific attribute
|
8
|
-
#
|
9
|
-
class BatchOptionModel
|
10
|
-
attr_reader :attribute, :opts, :loaders, :many
|
11
|
-
|
12
|
-
#
|
13
|
-
# Initializes BatchOptionModel
|
14
|
-
#
|
15
|
-
# @param map_point [Serega::SeregaMapPoint] Map point for attribute with :batch option
|
16
|
-
# @param loaders [Array] Array of all loaders defined in serialize class
|
17
|
-
# @param many [Boolean] Option :many, defined on attribute
|
18
|
-
#
|
19
|
-
# @return [void]
|
20
|
-
def initialize(attribute)
|
21
|
-
@attribute = attribute
|
22
|
-
@opts = attribute.batch
|
23
|
-
@loaders = attribute.class.serializer_class.config.batch_loaders
|
24
|
-
@many = attribute.many
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns proc that will be used to batch load registered keys values
|
28
|
-
# @return [#call] batch loader
|
29
|
-
def loader
|
30
|
-
@batch_loader ||= begin
|
31
|
-
loader = opts[:loader]
|
32
|
-
loader = loaders.fetch(loader) if loader.is_a?(Symbol)
|
33
|
-
loader
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# Returns proc that will be used to find batch_key for current attribute.
|
38
|
-
# @return [Object] key (uid) of batch loaded object
|
39
|
-
def key
|
40
|
-
@batch_key ||= begin
|
41
|
-
key = opts[:key]
|
42
|
-
|
43
|
-
if key.is_a?(Symbol)
|
44
|
-
proc do |object|
|
45
|
-
handle_no_method_error { object.public_send(key) }
|
46
|
-
end
|
47
|
-
else
|
48
|
-
key
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
# Returns default value to use if batch loader does not return value for some key
|
54
|
-
# @return [Object] default value for missing key
|
55
|
-
def default_value
|
56
|
-
if opts.key?(:default)
|
57
|
-
opts[:default]
|
58
|
-
elsif many
|
59
|
-
FROZEN_EMPTY_ARRAY
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def handle_no_method_error
|
66
|
-
yield
|
67
|
-
rescue NoMethodError => error
|
68
|
-
raise error, "NoMethodError when serializing '#{attribute.name}' attribute in #{attribute.class.serializer_class}\n\n#{error.message}", error.backtrace
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
class Serega
|
4
|
-
module SeregaPlugins
|
5
|
-
module Preloads
|
6
|
-
#
|
7
|
-
# Utility to freeze nested hashes and arrays
|
8
|
-
#
|
9
|
-
class EnumDeepFreeze
|
10
|
-
class << self
|
11
|
-
#
|
12
|
-
# Freezes nested enumerable data
|
13
|
-
#
|
14
|
-
# @param data[Hash, Array] data to freeze
|
15
|
-
#
|
16
|
-
# @return [Hash, Array] same deeply frozen data
|
17
|
-
#
|
18
|
-
def call(data)
|
19
|
-
data.each_entry { |entry| call(entry) } if data.is_a?(Enumerable)
|
20
|
-
data.freeze
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|