serega 0.1.4 → 0.3.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/VERSION +1 -1
- data/lib/serega/attribute.rb +17 -4
- data/lib/serega/config.rb +69 -27
- data/lib/serega/convert.rb +7 -7
- data/lib/serega/convert_item.rb +4 -4
- data/lib/serega/errors.rb +12 -0
- data/lib/serega/helpers/serializer_class_helper.rb +1 -1
- data/lib/serega/json/adapter.rb +17 -0
- data/lib/serega/json/json.rb +17 -0
- data/lib/serega/json/oj.rb +17 -0
- data/lib/serega/map.rb +25 -15
- data/lib/serega/plugins/activerecord_preloads/activerecord_preloads.rb +3 -3
- data/lib/serega/plugins/activerecord_preloads/lib/preloader.rb +2 -2
- data/lib/serega/plugins/context_metadata/context_metadata.rb +34 -11
- data/lib/serega/plugins/formatters/formatters.rb +35 -6
- data/lib/serega/plugins/hide_nil/hide_nil.rb +7 -7
- data/lib/serega/plugins/metadata/meta_attribute.rb +5 -5
- data/lib/serega/plugins/metadata/metadata.rb +30 -5
- data/lib/serega/plugins/metadata/validations/check_block.rb +4 -4
- data/lib/serega/plugins/metadata/validations/check_opt_hide_empty.rb +3 -3
- data/lib/serega/plugins/metadata/validations/check_opt_hide_nil.rb +3 -3
- data/lib/serega/plugins/metadata/validations/check_opts.rb +3 -3
- data/lib/serega/plugins/metadata/validations/check_path.rb +3 -3
- data/lib/serega/plugins/preloads/lib/enum_deep_freeze.rb +1 -1
- data/lib/serega/plugins/preloads/lib/format_user_preloads.rb +1 -1
- data/lib/serega/plugins/preloads/lib/main_preload_path.rb +1 -1
- data/lib/serega/plugins/preloads/lib/preloads_constructor.rb +2 -2
- data/lib/serega/plugins/preloads/preloads.rb +63 -5
- data/lib/serega/plugins/preloads/validations/check_opt_preload.rb +17 -0
- data/lib/serega/plugins/preloads/validations/check_opt_preload_path.rb +4 -4
- data/lib/serega/plugins/presenter/presenter.rb +6 -6
- data/lib/serega/plugins/root/root.rb +48 -8
- data/lib/serega/plugins/string_modifiers/parse_string_modifiers.rb +1 -1
- data/lib/serega/plugins/string_modifiers/string_modifiers.rb +7 -7
- data/lib/serega/plugins.rb +7 -7
- data/lib/serega/utils/enum_deep_dup.rb +1 -1
- data/lib/serega/utils/to_hash.rb +2 -2
- data/lib/serega/validations/attribute/check_block.rb +3 -3
- data/lib/serega/validations/attribute/check_name.rb +3 -3
- data/lib/serega/validations/attribute/check_opt_const.rb +5 -5
- data/lib/serega/validations/attribute/check_opt_delegate.rb +57 -0
- data/lib/serega/validations/attribute/check_opt_hide.rb +2 -2
- data/lib/serega/validations/attribute/check_opt_key.rb +5 -5
- data/lib/serega/validations/attribute/check_opt_many.rb +2 -2
- data/lib/serega/validations/attribute/check_opt_serializer.rb +3 -3
- data/lib/serega/validations/attribute/check_opt_value.rb +7 -7
- data/lib/serega/validations/check_attribute_params.rb +4 -3
- data/lib/serega/validations/check_initiate_params.rb +23 -10
- data/lib/serega/validations/check_serialize_params.rb +16 -10
- data/lib/serega/{plugins/validate_modifiers/validate.rb → validations/initiate/check_modifiers.rb} +5 -5
- data/lib/serega/validations/utils/check_allowed_keys.rb +2 -2
- data/lib/serega/validations/utils/check_opt_is_bool.rb +2 -2
- data/lib/serega/validations/utils/check_opt_is_hash.rb +2 -2
- data/lib/serega/validations/utils/check_opt_is_string_or_symbol.rb +2 -2
- data/lib/serega.rb +52 -72
- metadata +9 -6
- data/lib/serega/plugins/validate_modifiers/validate_modifiers.rb +0 -44
- data/lib/serega/utils/as_json.rb +0 -35
- data/lib/serega/utils/to_json.rb +0 -22
@@ -1,19 +1,26 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Metadata
|
6
6
|
def self.plugin_name
|
7
7
|
:metadata
|
8
8
|
end
|
9
9
|
|
10
10
|
def self.before_load_plugin(serializer_class, **opts)
|
11
|
-
|
11
|
+
if serializer_class.plugin_used?(:root)
|
12
|
+
root = serializer_class.config.root
|
13
|
+
root.one = opts[:root_one] if opts.key?(:root_one)
|
14
|
+
root.many = opts[:root_many] if opts.key?(:root_many)
|
15
|
+
else
|
16
|
+
serializer_class.plugin(:root, **opts)
|
17
|
+
end
|
12
18
|
end
|
13
19
|
|
14
20
|
def self.load_plugin(serializer_class, **_opts)
|
15
21
|
serializer_class.extend(ClassMethods)
|
16
|
-
serializer_class::
|
22
|
+
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
23
|
+
serializer_class::SeregaConvert.include(SeregaConvertInstanceMethods)
|
17
24
|
|
18
25
|
require_relative "./meta_attribute"
|
19
26
|
require_relative "./validations/check_block"
|
@@ -28,7 +35,25 @@ class Serega
|
|
28
35
|
end
|
29
36
|
|
30
37
|
def self.after_load_plugin(serializer_class, **_opts)
|
31
|
-
serializer_class.config[
|
38
|
+
serializer_class.config.opts[:metadata] = {attribute_keys: %i[path hide_nil hide_empty]}
|
39
|
+
end
|
40
|
+
|
41
|
+
class MetadataConfig
|
42
|
+
attr_reader :opts
|
43
|
+
|
44
|
+
def initialize(opts)
|
45
|
+
@opts = opts
|
46
|
+
end
|
47
|
+
|
48
|
+
def attribute_keys
|
49
|
+
opts.fetch(:attribute_keys)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
module ConfigInstanceMethods
|
54
|
+
def metadata
|
55
|
+
MetadataConfig.new(opts.fetch(:metadata))
|
56
|
+
end
|
32
57
|
end
|
33
58
|
|
34
59
|
module ClassMethods
|
@@ -79,7 +104,7 @@ class Serega
|
|
79
104
|
end
|
80
105
|
end
|
81
106
|
|
82
|
-
module
|
107
|
+
module SeregaConvertInstanceMethods
|
83
108
|
def to_h
|
84
109
|
hash = super
|
85
110
|
add_metadata(hash)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Metadata
|
6
6
|
class MetaAttribute
|
7
7
|
class CheckBlock
|
@@ -25,17 +25,17 @@ class Serega
|
|
25
25
|
#
|
26
26
|
# @param block [Proc] Block that returns serialized meta attribute value
|
27
27
|
#
|
28
|
-
# @raise [
|
28
|
+
# @raise [SeregaError] SeregaError that block has invalid arguments
|
29
29
|
#
|
30
30
|
# @return [void]
|
31
31
|
#
|
32
32
|
def call(block)
|
33
|
-
raise
|
33
|
+
raise SeregaError, "Block must be provided when defining meta attribute" unless block
|
34
34
|
|
35
35
|
params = block.parameters
|
36
36
|
return if (params.count <= 2) && params.all? { |par| ALLOWED_PARAM_TYPES.include?(par[0]) }
|
37
37
|
|
38
|
-
raise
|
38
|
+
raise SeregaError, "Block can have maximum 2 regular parameters (no **keyword or *array args)"
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Metadata
|
6
6
|
class MetaAttribute
|
7
7
|
class CheckOptHideEmpty
|
@@ -11,7 +11,7 @@ class Serega
|
|
11
11
|
#
|
12
12
|
# @param opts [Hash] Attribute options
|
13
13
|
#
|
14
|
-
# @raise [
|
14
|
+
# @raise [SeregaError] SeregaError that option has invalid value
|
15
15
|
#
|
16
16
|
# @return [void]
|
17
17
|
#
|
@@ -21,7 +21,7 @@ class Serega
|
|
21
21
|
value = opts[:hide_empty]
|
22
22
|
return if value == true
|
23
23
|
|
24
|
-
raise
|
24
|
+
raise SeregaError, "Invalid option :hide_empty => #{value.inspect}. Must be true"
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Metadata
|
6
6
|
class MetaAttribute
|
7
7
|
class CheckOptHideNil
|
@@ -11,7 +11,7 @@ class Serega
|
|
11
11
|
#
|
12
12
|
# @param opts [Hash] Attribute options
|
13
13
|
#
|
14
|
-
# @raise [
|
14
|
+
# @raise [SeregaError] SeregaError that option has invalid value
|
15
15
|
#
|
16
16
|
# @return [void]
|
17
17
|
#
|
@@ -21,7 +21,7 @@ class Serega
|
|
21
21
|
value = opts[:hide_nil]
|
22
22
|
return if value == true
|
23
23
|
|
24
|
-
raise
|
24
|
+
raise SeregaError, "Invalid option :hide_nil => #{value.inspect}. Must be true"
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Metadata
|
6
6
|
class MetaAttribute
|
7
7
|
class CheckOpts
|
@@ -13,7 +13,7 @@ class Serega
|
|
13
13
|
# @param opts [Hash] Attribute options
|
14
14
|
# @param attribute_keys [Array<Symbol>] Allowed options keys
|
15
15
|
#
|
16
|
-
# @raise [
|
16
|
+
# @raise [SeregaError] when attribute has invalid options
|
17
17
|
#
|
18
18
|
# @return [void]
|
19
19
|
#
|
@@ -21,7 +21,7 @@ class Serega
|
|
21
21
|
opts.each_key do |key|
|
22
22
|
next if attribute_keys.include?(key.to_sym)
|
23
23
|
|
24
|
-
raise
|
24
|
+
raise SeregaError, "Invalid option #{key.inspect}. Allowed options are: #{attribute_keys.map(&:inspect).join(", ")}"
|
25
25
|
end
|
26
26
|
|
27
27
|
check_each_opt(opts)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Metadata
|
6
6
|
class MetaAttribute
|
7
7
|
class CheckPath
|
@@ -18,7 +18,7 @@ class Serega
|
|
18
18
|
#
|
19
19
|
# @param path [Array<String, Symbol>] Metadata attribute path names
|
20
20
|
#
|
21
|
-
# @raise [
|
21
|
+
# @raise [SeregaError] when metadata attribute name has invalid format
|
22
22
|
# @return [void]
|
23
23
|
#
|
24
24
|
def call(path)
|
@@ -39,7 +39,7 @@ class Serega
|
|
39
39
|
|
40
40
|
return if valid
|
41
41
|
|
42
|
-
raise
|
42
|
+
raise SeregaError, message(name)
|
43
43
|
end
|
44
44
|
|
45
45
|
def message(name)
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Preloads
|
6
6
|
#
|
7
7
|
# Finds relations to preload for provided serializer
|
@@ -29,7 +29,7 @@ class Serega
|
|
29
29
|
next unless current_preloads
|
30
30
|
|
31
31
|
has_nested = nested_map.any?
|
32
|
-
current_preloads =
|
32
|
+
current_preloads = SeregaUtils::EnumDeepDup.call(current_preloads) if has_nested
|
33
33
|
append_current(preloads, current_preloads)
|
34
34
|
next unless has_nested
|
35
35
|
|
@@ -1,11 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
#
|
6
6
|
# Plugin adds `.preloads` method to find relations that must be preloaded
|
7
7
|
#
|
8
8
|
module Preloads
|
9
|
+
DEFAULT_CONFIG = {
|
10
|
+
auto_preload_attributes_with_delegate: false,
|
11
|
+
auto_preload_attributes_with_serializer: false,
|
12
|
+
auto_hide_attributes_with_preload: false
|
13
|
+
}.freeze
|
14
|
+
|
9
15
|
# @return [Symbol] plugin name
|
10
16
|
def self.plugin_name
|
11
17
|
:preloads
|
@@ -21,7 +27,8 @@ class Serega
|
|
21
27
|
#
|
22
28
|
def self.load_plugin(serializer_class, **_opts)
|
23
29
|
serializer_class.include(InstanceMethods)
|
24
|
-
serializer_class::
|
30
|
+
serializer_class::SeregaAttribute.include(AttributeMethods)
|
31
|
+
serializer_class::SeregaConfig.include(ConfigInstanceMethods)
|
25
32
|
|
26
33
|
serializer_class::CheckAttributeParams.include(CheckAttributeParamsInstanceMethods)
|
27
34
|
|
@@ -29,13 +36,20 @@ class Serega
|
|
29
36
|
require_relative "./lib/format_user_preloads"
|
30
37
|
require_relative "./lib/main_preload_path"
|
31
38
|
require_relative "./lib/preloads_constructor"
|
39
|
+
require_relative "./validations/check_opt_preload"
|
32
40
|
require_relative "./validations/check_opt_preload_path"
|
33
41
|
end
|
34
42
|
|
35
43
|
def self.after_load_plugin(serializer_class, **opts)
|
36
44
|
config = serializer_class.config
|
37
|
-
config
|
38
|
-
|
45
|
+
config.attribute_keys << :preload << :preload_path
|
46
|
+
|
47
|
+
preloads_opts = DEFAULT_CONFIG.merge(opts.slice(*DEFAULT_CONFIG.keys))
|
48
|
+
config.opts[:preloads] = {}
|
49
|
+
preloads_config = config.preloads
|
50
|
+
preloads_config.auto_preload_attributes_with_delegate = preloads_opts[:auto_preload_attributes_with_delegate]
|
51
|
+
preloads_config.auto_preload_attributes_with_serializer = preloads_opts[:auto_preload_attributes_with_serializer]
|
52
|
+
preloads_config.auto_hide_attributes_with_preload = preloads_opts[:auto_hide_attributes_with_preload]
|
39
53
|
end
|
40
54
|
|
41
55
|
# Adds #preloads instance method
|
@@ -46,6 +60,35 @@ class Serega
|
|
46
60
|
end
|
47
61
|
end
|
48
62
|
|
63
|
+
class PreloadsConfig
|
64
|
+
attr_reader :opts
|
65
|
+
|
66
|
+
def initialize(opts)
|
67
|
+
@opts = opts
|
68
|
+
end
|
69
|
+
|
70
|
+
%i[
|
71
|
+
auto_preload_attributes_with_delegate
|
72
|
+
auto_preload_attributes_with_serializer
|
73
|
+
auto_hide_attributes_with_preload
|
74
|
+
].each do |method_name|
|
75
|
+
define_method(method_name) do
|
76
|
+
opts.fetch(method_name)
|
77
|
+
end
|
78
|
+
|
79
|
+
define_method("#{method_name}=") do |value|
|
80
|
+
raise SeregaError, "Must have boolean value, #{value.inspect} provided" if (value != true) && (value != false)
|
81
|
+
opts[method_name] = value
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
module ConfigInstanceMethods
|
87
|
+
def preloads
|
88
|
+
PreloadsConfig.new(opts.fetch(:preloads))
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
49
92
|
# Adds #preloads and #preloads_path Attribute instance method
|
50
93
|
module AttributeMethods
|
51
94
|
def preloads
|
@@ -60,15 +103,29 @@ class Serega
|
|
60
103
|
@preloads_path = get_preloads_path
|
61
104
|
end
|
62
105
|
|
106
|
+
def hide
|
107
|
+
res = super
|
108
|
+
return res unless res.nil?
|
109
|
+
|
110
|
+
auto_hide_attribute_with_preloads? || nil
|
111
|
+
end
|
112
|
+
|
63
113
|
private
|
64
114
|
|
115
|
+
def auto_hide_attribute_with_preloads?
|
116
|
+
auto = self.class.serializer_class.config.preloads.auto_hide_attributes_with_preload
|
117
|
+
@auto_hide_attribute_with_preloads = auto && !preloads.nil? && (preloads != false) && (preloads != {})
|
118
|
+
end
|
119
|
+
|
65
120
|
def get_preloads
|
66
121
|
preloads_provided = opts.key?(:preload)
|
67
122
|
preloads =
|
68
123
|
if preloads_provided
|
69
124
|
opts[:preload]
|
70
|
-
elsif relation? && self.class.serializer_class.config
|
125
|
+
elsif relation? && self.class.serializer_class.config.preloads.auto_preload_attributes_with_serializer
|
71
126
|
key
|
127
|
+
elsif opts.key?(:delegate) && self.class.serializer_class.config.preloads.auto_preload_attributes_with_delegate
|
128
|
+
opts[:delegate].fetch(:to)
|
72
129
|
end
|
73
130
|
|
74
131
|
# Nil and empty hash differs as we can preload nested results to
|
@@ -90,6 +147,7 @@ class Serega
|
|
90
147
|
|
91
148
|
def check_opts
|
92
149
|
super
|
150
|
+
CheckOptPreload.call(opts)
|
93
151
|
CheckOptPreloadPath.call(opts)
|
94
152
|
end
|
95
153
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Serega
|
4
|
+
module SeregaPlugins
|
5
|
+
module Preloads
|
6
|
+
class CheckOptPreload
|
7
|
+
class << self
|
8
|
+
def call(opts)
|
9
|
+
return unless opts.key?(:preload)
|
10
|
+
|
11
|
+
raise SeregaError, "Option :preload can not be used together with option :const" if opts.key?(:const)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Preloads
|
6
6
|
class CheckOptPreloadPath
|
7
7
|
class << self
|
@@ -9,13 +9,13 @@ class Serega
|
|
9
9
|
return unless opts.key?(:preload_path)
|
10
10
|
|
11
11
|
value = opts[:preload_path]
|
12
|
-
raise
|
13
|
-
raise
|
12
|
+
raise SeregaError, "Invalid option :preload_path => #{value.inspect}. Can be provided only when :preload option provided" unless opts[:preload]
|
13
|
+
raise SeregaError, "Invalid option :preload_path => #{value.inspect}. Can be provided only when :serializer option provided" unless opts[:serializer]
|
14
14
|
|
15
15
|
path = Array(value).map!(&:to_sym)
|
16
16
|
preloads = FormatUserPreloads.call(opts[:preload])
|
17
17
|
allowed_paths = paths(preloads)
|
18
|
-
raise
|
18
|
+
raise SeregaError, "Invalid option :preload_path => #{value.inspect}. Can be one of #{allowed_paths.inspect[1..-2]}" unless allowed_paths.include?(path)
|
19
19
|
end
|
20
20
|
|
21
21
|
private
|
@@ -4,7 +4,7 @@ require "delegate"
|
|
4
4
|
require "forwardable"
|
5
5
|
|
6
6
|
class Serega
|
7
|
-
module
|
7
|
+
module SeregaPlugins
|
8
8
|
#
|
9
9
|
# Plugin Presenter adds possibility to use declare Presenter for your objects inside serializer
|
10
10
|
#
|
@@ -35,7 +35,7 @@ class Serega
|
|
35
35
|
#
|
36
36
|
def self.load_plugin(serializer_class, **_opts)
|
37
37
|
serializer_class.extend(ClassMethods)
|
38
|
-
serializer_class::
|
38
|
+
serializer_class::SeregaConvertItem.extend(SeregaConvertItemClassMethods)
|
39
39
|
end
|
40
40
|
|
41
41
|
#
|
@@ -69,7 +69,7 @@ class Serega
|
|
69
69
|
end
|
70
70
|
end
|
71
71
|
|
72
|
-
extend
|
72
|
+
extend SeregaHelpers::SerializerClassHelper
|
73
73
|
extend Forwardable
|
74
74
|
include InstanceMethods
|
75
75
|
end
|
@@ -85,7 +85,7 @@ class Serega
|
|
85
85
|
end
|
86
86
|
|
87
87
|
# Overrides {Serega::ClassMethods#attribute} method, additionally adds method
|
88
|
-
# to Presenter to not hit {Serega::
|
88
|
+
# to Presenter to not hit {Serega::SeregaPlugins::Presenter::Presenter#method_missing}
|
89
89
|
# @see Serega::ClassMethods#attribute
|
90
90
|
def attribute(_name, **_opts, &_block)
|
91
91
|
super.tap do |attribute|
|
@@ -94,8 +94,8 @@ class Serega
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
-
# Includes methods to override
|
98
|
-
module
|
97
|
+
# Includes methods to override SeregaConvertItem class
|
98
|
+
module SeregaConvertItemClassMethods
|
99
99
|
#
|
100
100
|
# Replaces serialized object with Presenter.new(object)
|
101
101
|
#
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module Root
|
6
6
|
# @return [Symbol] Default response root key
|
7
7
|
ROOT_DEFAULT = :data
|
@@ -12,12 +12,17 @@ class Serega
|
|
12
12
|
|
13
13
|
def self.load_plugin(serializer_class, **_opts)
|
14
14
|
serializer_class.extend(ClassMethods)
|
15
|
-
serializer_class::
|
15
|
+
serializer_class::SeregaConfig.include(SeregaConfigInstanceMethods)
|
16
|
+
serializer_class::SeregaConvert.include(SeregaConvertInstanceMethods)
|
16
17
|
end
|
17
18
|
|
18
19
|
def self.after_load_plugin(serializer_class, **opts)
|
19
|
-
serializer_class.
|
20
|
-
|
20
|
+
config = serializer_class.config
|
21
|
+
default = opts[:root] || ROOT_DEFAULT
|
22
|
+
one = (opts[:root_one] || default).to_sym
|
23
|
+
many = (opts[:root_many] || default).to_sym
|
24
|
+
config.opts[:root] = {one: one, many: many}
|
25
|
+
config.serialize_keys << :root
|
21
26
|
end
|
22
27
|
|
23
28
|
module ClassMethods
|
@@ -37,11 +42,46 @@ class Serega
|
|
37
42
|
one = one.to_sym if one
|
38
43
|
many = many.to_sym if many
|
39
44
|
|
40
|
-
config
|
45
|
+
config.root = {one: one, many: many}
|
41
46
|
end
|
42
47
|
end
|
43
48
|
|
44
|
-
|
49
|
+
class RootConfig
|
50
|
+
attr_reader :opts
|
51
|
+
|
52
|
+
def initialize(opts)
|
53
|
+
@opts = opts
|
54
|
+
end
|
55
|
+
|
56
|
+
def one
|
57
|
+
opts.fetch(:one)
|
58
|
+
end
|
59
|
+
|
60
|
+
def many
|
61
|
+
opts.fetch(:many)
|
62
|
+
end
|
63
|
+
|
64
|
+
def one=(value)
|
65
|
+
opts[:one] = value
|
66
|
+
end
|
67
|
+
|
68
|
+
def many=(value)
|
69
|
+
opts[:many] = value
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
module SeregaConfigInstanceMethods
|
74
|
+
def root
|
75
|
+
RootConfig.new(opts.fetch(:root))
|
76
|
+
end
|
77
|
+
|
78
|
+
def root=(value)
|
79
|
+
root.one = value.fetch(:one)
|
80
|
+
root.many = value.fetch(:many)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
module SeregaConvertInstanceMethods
|
45
85
|
def to_h
|
46
86
|
hash = super
|
47
87
|
root = build_root(opts)
|
@@ -54,8 +94,8 @@ class Serega
|
|
54
94
|
def build_root(opts)
|
55
95
|
return opts[:root] if opts.key?(:root)
|
56
96
|
|
57
|
-
|
58
|
-
many? ?
|
97
|
+
root = self.class.serializer_class.config.root
|
98
|
+
many? ? root.many : root.one
|
59
99
|
end
|
60
100
|
end
|
61
101
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaPlugins
|
5
5
|
module StringModifiers
|
6
6
|
def self.plugin_name
|
7
7
|
:string_modifiers
|
@@ -16,13 +16,13 @@ class Serega
|
|
16
16
|
private
|
17
17
|
|
18
18
|
def prepare_modifiers(opts)
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
parsed_opts =
|
20
|
+
opts.each_with_object({}) do |(key, value), obj|
|
21
|
+
value = ParseStringModifiers.call(value) if (key == :only) || (key == :except) || (key == :with)
|
22
|
+
obj[key] = value
|
23
|
+
end
|
24
24
|
|
25
|
-
super
|
25
|
+
super(parsed_opts)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
data/lib/serega/plugins.rb
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
class Serega
|
4
4
|
# Module in which all Serega plugins should be stored
|
5
|
-
module
|
5
|
+
module SeregaPlugins
|
6
6
|
@plugins = {}
|
7
7
|
|
8
8
|
class << self
|
@@ -10,7 +10,7 @@ class Serega
|
|
10
10
|
# Registers given plugin to be able to load it using symbol name.
|
11
11
|
#
|
12
12
|
# @example Register plugin
|
13
|
-
# Serega::
|
13
|
+
# Serega::SeregaPlugins.register_plugin(:plugin_name, PluginModule)
|
14
14
|
def register_plugin(name, mod)
|
15
15
|
@plugins[name] = mod
|
16
16
|
end
|
@@ -20,13 +20,13 @@ class Serega
|
|
20
20
|
#
|
21
21
|
# @param name [Symbol, Module] plugin name or plugin itself
|
22
22
|
#
|
23
|
-
# @raise [
|
23
|
+
# @raise [SeregaError] Raises SeregaError when plugin was not found
|
24
24
|
#
|
25
25
|
# @example Find plugin when providing name
|
26
|
-
# Serega::
|
26
|
+
# Serega::SeregaPlugins.find_plugin(:presenter) # => Serega::SeregaPlugins::Presenter
|
27
27
|
#
|
28
28
|
# @example Find plugin when providing plugin itself
|
29
|
-
# Serega::
|
29
|
+
# Serega::SeregaPlugins.find_plugin(Presenter) # => Presenter
|
30
30
|
#
|
31
31
|
# @return [Class<Module>] Plugin core module
|
32
32
|
#
|
@@ -36,7 +36,7 @@ class Serega
|
|
36
36
|
|
37
37
|
require_plugin(name)
|
38
38
|
|
39
|
-
@plugins[name] || raise(
|
39
|
+
@plugins[name] || raise(SeregaError, "Plugin '#{name}' did not register itself correctly")
|
40
40
|
end
|
41
41
|
|
42
42
|
private
|
@@ -44,7 +44,7 @@ class Serega
|
|
44
44
|
def require_plugin(name)
|
45
45
|
require "serega/plugins/#{name}/#{name}"
|
46
46
|
rescue LoadError
|
47
|
-
raise
|
47
|
+
raise SeregaError, "Plugin '#{name}' does not exist"
|
48
48
|
end
|
49
49
|
end
|
50
50
|
end
|
data/lib/serega/utils/to_hash.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class Serega
|
4
|
-
module
|
4
|
+
module SeregaUtils
|
5
5
|
class ToHash
|
6
6
|
module ClassMethods
|
7
7
|
def call(value)
|
@@ -11,7 +11,7 @@ class Serega
|
|
11
11
|
when NilClass, FalseClass then nil_to_hash(value)
|
12
12
|
when String then string_to_hash(value)
|
13
13
|
when Symbol then symbol_to_hash(value)
|
14
|
-
else raise
|
14
|
+
else raise SeregaError, "Cant convert #{value.class} class object to hash"
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|