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.
Files changed (34) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +319 -141
  3. data/VERSION +1 -1
  4. data/lib/serega/attribute.rb +37 -105
  5. data/lib/serega/attribute_normalizer.rb +176 -0
  6. data/lib/serega/config.rb +26 -9
  7. data/lib/serega/object_serializer.rb +11 -10
  8. data/lib/serega/plan.rb +128 -0
  9. data/lib/serega/plan_point.rb +94 -0
  10. data/lib/serega/plugins/batch/batch.rb +187 -41
  11. data/lib/serega/plugins/batch/lib/loader.rb +4 -4
  12. data/lib/serega/plugins/batch/lib/loaders.rb +3 -3
  13. data/lib/serega/plugins/batch/lib/plugins_extensions/activerecord_preloads.rb +2 -2
  14. data/lib/serega/plugins/batch/lib/plugins_extensions/formatters.rb +19 -1
  15. data/lib/serega/plugins/batch/lib/plugins_extensions/preloads.rb +6 -4
  16. data/lib/serega/plugins/batch/lib/validations/check_opt_batch.rb +9 -5
  17. data/lib/serega/plugins/formatters/formatters.rb +28 -31
  18. data/lib/serega/plugins/if/if.rb +24 -6
  19. data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +11 -13
  20. data/lib/serega/plugins/preloads/lib/main_preload_path.rb +2 -2
  21. data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +21 -15
  22. data/lib/serega/plugins/preloads/preloads.rb +72 -40
  23. data/lib/serega/plugins/presenter/presenter.rb +0 -9
  24. data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +11 -1
  25. data/lib/serega/plugins.rb +3 -3
  26. data/lib/serega/utils/enum_deep_dup.rb +18 -18
  27. data/lib/serega/utils/enum_deep_freeze.rb +35 -0
  28. data/lib/serega/utils/to_hash.rb +17 -9
  29. data/lib/serega.rb +22 -15
  30. metadata +6 -6
  31. data/lib/serega/map.rb +0 -91
  32. data/lib/serega/map_point.rb +0 -66
  33. data/lib/serega/plugins/batch/lib/batch_option_model.rb +0 -73
  34. 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
@@ -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