fast_serializer_ruby 0.6.0 → 0.6.2
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/.gitignore +2 -0
- data/Gemfile +3 -2
- data/Gemfile.lock +28 -19
- data/README.md +3 -3
- data/fast_serializer.gemspec +1 -0
- data/lib/fast_serializer/configuration.rb +6 -15
- data/lib/fast_serializer/json_model/array.rb +4 -0
- data/lib/fast_serializer/json_model/attribute.rb +47 -39
- data/lib/fast_serializer/json_model/has_many_relationship.rb +5 -3
- data/lib/fast_serializer/json_model/has_one_relationship.rb +4 -1
- data/lib/fast_serializer/json_model/node.rb +6 -2
- data/lib/fast_serializer/json_model/object.rb +12 -4
- data/lib/fast_serializer/json_model/relationship.rb +20 -3
- data/lib/fast_serializer/schema.rb +69 -50
- data/lib/fast_serializer/schema/mixin.rb +21 -10
- data/lib/fast_serializer/utils.rb +9 -1
- data/lib/fast_serializer/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4adafc96834175b06d1d49a72269b461f0d72419286a03e3c6422d145e027672
|
|
4
|
+
data.tar.gz: 5422eeac009a270dffbc56a7234b74da8c6a38eb56fbca9a66121f96ee129e3c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: b6571bed32c87ef3dacb6ad00a6d0054aa547f8afe4f196b1a9186d6d6eedc649aaa81c8f22a72114e74547a9ec8d61a9df0229415ff92370a58c06e3ad3c91b
|
|
7
|
+
data.tar.gz: 0567dc3d3513358831e4571833daeb941ebc94660d945240038669e3f2c20deedb99d16337055336b88afe1110b6061800b994ab7fe8f6a40ef54cfd1bfa6c06
|
data/.gitignore
CHANGED
data/Gemfile
CHANGED
|
@@ -6,8 +6,8 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
|
|
|
6
6
|
|
|
7
7
|
gemspec
|
|
8
8
|
|
|
9
|
-
group :development do
|
|
10
|
-
gem '
|
|
9
|
+
group :development, :test do
|
|
10
|
+
gem 'rake'
|
|
11
11
|
gem 'pry'
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -15,6 +15,7 @@ group :test do
|
|
|
15
15
|
gem 'active_model_serializers', '~> 0.10.0'
|
|
16
16
|
gem 'factory_bot'
|
|
17
17
|
gem 'faker'
|
|
18
|
+
gem 'activesupport', '< 6'
|
|
18
19
|
gem 'allocation_stats'
|
|
19
20
|
gem 'simplecov', '~> 0.17.1'
|
|
20
21
|
gem 'benchmark-memory', '~> 0.1'
|
data/Gemfile.lock
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
fast_serializer_ruby (0.6.
|
|
4
|
+
fast_serializer_ruby (0.6.2)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
@@ -32,28 +32,29 @@ GEM
|
|
|
32
32
|
minitest (~> 5.1)
|
|
33
33
|
tzinfo (~> 1.1)
|
|
34
34
|
allocation_stats (0.1.5)
|
|
35
|
-
benchmark-malloc (0.
|
|
35
|
+
benchmark-malloc (0.2.0)
|
|
36
36
|
benchmark-memory (0.1.2)
|
|
37
37
|
memory_profiler (~> 0.9)
|
|
38
|
-
benchmark-perf (0.
|
|
39
|
-
benchmark-trend (0.
|
|
38
|
+
benchmark-perf (0.6.0)
|
|
39
|
+
benchmark-trend (0.4.0)
|
|
40
40
|
builder (3.2.4)
|
|
41
|
-
byebug (11.0.1)
|
|
42
41
|
case_transform (0.2)
|
|
43
42
|
activesupport
|
|
44
43
|
coderay (1.1.2)
|
|
45
|
-
concurrent-ruby (1.1.
|
|
44
|
+
concurrent-ruby (1.1.6)
|
|
46
45
|
crass (1.0.6)
|
|
47
46
|
diff-lcs (1.3)
|
|
48
47
|
docile (1.3.2)
|
|
49
48
|
erubi (1.9.0)
|
|
50
49
|
factory_bot (5.1.1)
|
|
51
50
|
activesupport (>= 4.2.0)
|
|
52
|
-
faker (2.10.
|
|
51
|
+
faker (2.10.2)
|
|
53
52
|
i18n (>= 1.6, < 2)
|
|
53
|
+
ffi (1.12.2-java)
|
|
54
54
|
i18n (1.8.2)
|
|
55
55
|
concurrent-ruby (~> 1.0)
|
|
56
56
|
json (2.3.0)
|
|
57
|
+
json (2.3.0-java)
|
|
57
58
|
jsonapi-renderer (0.2.2)
|
|
58
59
|
loofah (2.4.0)
|
|
59
60
|
crass (~> 1.0.2)
|
|
@@ -62,15 +63,17 @@ GEM
|
|
|
62
63
|
method_source (0.9.2)
|
|
63
64
|
mini_portile2 (2.4.0)
|
|
64
65
|
minitest (5.14.0)
|
|
65
|
-
nokogiri (1.10.
|
|
66
|
+
nokogiri (1.10.9)
|
|
66
67
|
mini_portile2 (~> 2.4.0)
|
|
68
|
+
nokogiri (1.10.9-java)
|
|
67
69
|
pry (0.12.2)
|
|
68
70
|
coderay (~> 1.1.0)
|
|
69
71
|
method_source (~> 0.9.0)
|
|
70
|
-
pry
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
72
|
+
pry (0.12.2-java)
|
|
73
|
+
coderay (~> 1.1.0)
|
|
74
|
+
method_source (~> 0.9.0)
|
|
75
|
+
spoon (~> 0.0)
|
|
76
|
+
rack (2.2.2)
|
|
74
77
|
rack-test (1.1.0)
|
|
75
78
|
rack (>= 1.0, < 3)
|
|
76
79
|
rails-dom-testing (2.0.3)
|
|
@@ -78,18 +81,19 @@ GEM
|
|
|
78
81
|
nokogiri (>= 1.6)
|
|
79
82
|
rails-html-sanitizer (1.3.0)
|
|
80
83
|
loofah (~> 2.3)
|
|
84
|
+
rake (13.0.1)
|
|
81
85
|
rspec (3.9.0)
|
|
82
86
|
rspec-core (~> 3.9.0)
|
|
83
87
|
rspec-expectations (~> 3.9.0)
|
|
84
88
|
rspec-mocks (~> 3.9.0)
|
|
85
|
-
rspec-benchmark (0.
|
|
86
|
-
benchmark-malloc (~> 0.
|
|
87
|
-
benchmark-perf (~> 0.
|
|
88
|
-
benchmark-trend (~> 0.
|
|
89
|
-
rspec (>= 3.0
|
|
89
|
+
rspec-benchmark (0.6.0)
|
|
90
|
+
benchmark-malloc (~> 0.2)
|
|
91
|
+
benchmark-perf (~> 0.6)
|
|
92
|
+
benchmark-trend (~> 0.4)
|
|
93
|
+
rspec (>= 3.0)
|
|
90
94
|
rspec-core (3.9.1)
|
|
91
95
|
rspec-support (~> 3.9.1)
|
|
92
|
-
rspec-expectations (3.9.
|
|
96
|
+
rspec-expectations (3.9.1)
|
|
93
97
|
diff-lcs (>= 1.2.0, < 2.0)
|
|
94
98
|
rspec-support (~> 3.9.0)
|
|
95
99
|
rspec-mocks (3.9.1)
|
|
@@ -101,22 +105,27 @@ GEM
|
|
|
101
105
|
json (>= 1.8, < 3)
|
|
102
106
|
simplecov-html (~> 0.10.0)
|
|
103
107
|
simplecov-html (0.10.2)
|
|
108
|
+
spoon (0.0.6)
|
|
109
|
+
ffi
|
|
104
110
|
thread_safe (0.3.6)
|
|
111
|
+
thread_safe (0.3.6-java)
|
|
105
112
|
tzinfo (1.2.6)
|
|
106
113
|
thread_safe (~> 0.1)
|
|
107
114
|
|
|
108
115
|
PLATFORMS
|
|
116
|
+
java
|
|
109
117
|
ruby
|
|
110
118
|
|
|
111
119
|
DEPENDENCIES
|
|
112
120
|
active_model_serializers (~> 0.10.0)
|
|
121
|
+
activesupport (< 6)
|
|
113
122
|
allocation_stats
|
|
114
123
|
benchmark-memory (~> 0.1)
|
|
115
124
|
factory_bot
|
|
116
125
|
faker
|
|
117
126
|
fast_serializer_ruby!
|
|
118
127
|
pry
|
|
119
|
-
|
|
128
|
+
rake
|
|
120
129
|
rspec (~> 3.0)
|
|
121
130
|
rspec-benchmark
|
|
122
131
|
simplecov (~> 0.17.1)
|
data/README.md
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
This library intends to solve such a typical and on the other hand important problem as efficient ruby object to hash transformation.
|
|
10
10
|
|
|
11
11
|
## Performance 🚀
|
|
12
|
-
- running on ruby 2.
|
|
13
|
-
- running on ruby 2.
|
|
14
|
-
- running on jruby 9.2.7.0 **is at least
|
|
12
|
+
- running on ruby 2.7 is **at least 6 times faster** than AMS (benchmarks was borrowed from fast_jsonapi repository)
|
|
13
|
+
- running on ruby 2.7 it consumes **6 times less RAM**
|
|
14
|
+
- running on jruby 9.2.7.0 **is at least 4 times faster** than AMS after warming up
|
|
15
15
|
|
|
16
16
|
## Compatibility 👌
|
|
17
17
|
I tried to keep the API as close as possible to active_model_serializer implementation because we all got used to it.
|
data/fast_serializer.gemspec
CHANGED
|
@@ -33,6 +33,7 @@ Gem::Specification.new do |spec|
|
|
|
33
33
|
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
34
34
|
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{(test|spec|features|git|rspec|travis)/}) }
|
|
35
35
|
end
|
|
36
|
+
|
|
36
37
|
spec.bindir = 'bin'
|
|
37
38
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
|
38
39
|
spec.require_paths = ['lib']
|
|
@@ -4,35 +4,26 @@ require 'json'
|
|
|
4
4
|
|
|
5
5
|
module FastSerializer
|
|
6
6
|
class Configuration
|
|
7
|
-
|
|
8
|
-
RubyVer = Struct.new(:major, :feature, :fix) do
|
|
9
|
-
|
|
10
|
-
def is_2_4_or_less
|
|
11
|
-
major == 2 && feature <= 4
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
attr_reader :coder, :ruby_ver
|
|
7
|
+
attr_reader :coder
|
|
16
8
|
attr_accessor :strict
|
|
17
9
|
|
|
18
10
|
def initialize
|
|
19
11
|
@coder = JSON
|
|
20
12
|
@strict = false
|
|
21
|
-
@ruby_ver = RubyVer.new(*RUBY_VERSION.split(".").map(&:to_i))
|
|
22
13
|
end
|
|
23
14
|
|
|
24
15
|
def coder=(obj)
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
else
|
|
28
|
-
raise ArgumentError, "must respond to #load and #dump methods"
|
|
16
|
+
unless obj.respond_to?(:dump) && obj.respond_to?(:load)
|
|
17
|
+
raise ArgumentError, 'must respond to #load and #dump methods'
|
|
29
18
|
end
|
|
19
|
+
|
|
20
|
+
@coder = obj
|
|
30
21
|
end
|
|
31
22
|
end
|
|
32
23
|
|
|
33
24
|
class << self
|
|
34
25
|
def config
|
|
35
|
-
@
|
|
26
|
+
@config ||= Configuration.new
|
|
36
27
|
end
|
|
37
28
|
|
|
38
29
|
def configure(&block)
|
|
@@ -11,8 +11,9 @@ module FastSerializer
|
|
|
11
11
|
:cond_method_name,
|
|
12
12
|
:injected
|
|
13
13
|
|
|
14
|
-
def initialize(
|
|
14
|
+
def initialize(*)
|
|
15
15
|
super
|
|
16
|
+
|
|
16
17
|
@mixin = nil
|
|
17
18
|
@method_name = nil
|
|
18
19
|
@injected = false
|
|
@@ -20,32 +21,8 @@ module FastSerializer
|
|
|
20
21
|
@cond = nil
|
|
21
22
|
@cond = @opts[:if] || @opts[:unless] || @cond
|
|
22
23
|
|
|
23
|
-
if method.is_a?(Proc)
|
|
24
|
-
|
|
25
|
-
@method_arity = method.arity.abs
|
|
26
|
-
@mixin = Module.new
|
|
27
|
-
|
|
28
|
-
if FastSerializer.config.ruby_ver.is_2_4_or_less
|
|
29
|
-
@mixin.redefine_method @method_name, &method
|
|
30
|
-
else
|
|
31
|
-
@mixin.define_method @method_name, &method
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
if !cond.nil? && cond.is_a?(Proc)
|
|
37
|
-
@cond_method_name = "__#{key}_cond__"
|
|
38
|
-
@cond_arity = cond.arity.abs
|
|
39
|
-
@mixin ||= Module.new
|
|
40
|
-
|
|
41
|
-
if FastSerializer.config.ruby_ver.is_2_4_or_less
|
|
42
|
-
@mixin.redefine_method @cond_method_name, &cond
|
|
43
|
-
else
|
|
44
|
-
@mixin.define_method @cond_method_name, &cond
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
end
|
|
48
|
-
|
|
24
|
+
init_with_proc if method.is_a?(Proc)
|
|
25
|
+
init_with_cond if !cond.nil? && cond.is_a?(Proc)
|
|
49
26
|
end
|
|
50
27
|
|
|
51
28
|
def injectable?
|
|
@@ -57,32 +34,39 @@ module FastSerializer
|
|
|
57
34
|
self.injected = true
|
|
58
35
|
end
|
|
59
36
|
|
|
37
|
+
# @param resource [Object]
|
|
38
|
+
# @param params [Hash]
|
|
39
|
+
# @param context [Hash]
|
|
40
|
+
# @return [Object]
|
|
60
41
|
def serialize(resource, params, context)
|
|
42
|
+
can_execute_on_mixin = injected && !method_name.nil? && !context.nil?
|
|
61
43
|
|
|
62
|
-
val = if
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
resource.public_send(method)
|
|
70
|
-
end
|
|
44
|
+
val = if can_execute_on_mixin
|
|
45
|
+
call_method_on_context(context, method_name, method_arity, resource, params)
|
|
46
|
+
elsif method.is_a?(Proc)
|
|
47
|
+
call_proc_binding_to_context(context, method, method_arity, resource, params)
|
|
48
|
+
else
|
|
49
|
+
resource.public_send(method)
|
|
50
|
+
end
|
|
71
51
|
|
|
72
52
|
val.freeze
|
|
73
53
|
|
|
74
54
|
val
|
|
75
55
|
end
|
|
76
56
|
|
|
57
|
+
# @param resource [Object]
|
|
58
|
+
# @param params [Hash]
|
|
59
|
+
# @param context [Hash]
|
|
60
|
+
# @return [Boolean]
|
|
77
61
|
def included?(resource, params, context)
|
|
78
62
|
return true if cond.nil?
|
|
79
63
|
|
|
80
|
-
|
|
81
|
-
call_method_on_context(context, cond_method_name, cond_arity, resource, params)
|
|
64
|
+
can_execute_on_mixin = injected && !cond_method_name.nil? && !context.nil?
|
|
82
65
|
|
|
66
|
+
res = if can_execute_on_mixin
|
|
67
|
+
call_method_on_context(context, cond_method_name, cond_arity, resource, params)
|
|
83
68
|
elsif cond.is_a?(Proc)
|
|
84
69
|
call_proc_binding_to_context(context, cond, cond_arity, resource, params)
|
|
85
|
-
|
|
86
70
|
else
|
|
87
71
|
context.public_send(cond)
|
|
88
72
|
end
|
|
@@ -94,6 +78,30 @@ module FastSerializer
|
|
|
94
78
|
|
|
95
79
|
private
|
|
96
80
|
|
|
81
|
+
def init_with_cond
|
|
82
|
+
@cond_method_name = "__#{key}_cond__"
|
|
83
|
+
@cond_arity = cond.arity.abs
|
|
84
|
+
@mixin ||= Module.new
|
|
85
|
+
|
|
86
|
+
if RUBY_VERSION <= '2.5.0'
|
|
87
|
+
@mixin.redefine_method @cond_method_name, &cond
|
|
88
|
+
else
|
|
89
|
+
@mixin.define_method @cond_method_name, &cond
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def init_with_proc
|
|
94
|
+
@method_name = "__#{key}__"
|
|
95
|
+
@method_arity = method.arity.abs
|
|
96
|
+
@mixin = Module.new
|
|
97
|
+
|
|
98
|
+
if RUBY_VERSION <= '2.5.0'
|
|
99
|
+
@mixin.redefine_method @method_name, &method
|
|
100
|
+
else
|
|
101
|
+
@mixin.define_method @method_name, &method
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
|
|
97
105
|
def call_proc_binding_to_context(context, prc, arity, resource, params)
|
|
98
106
|
case arity
|
|
99
107
|
when 1
|
|
@@ -3,16 +3,18 @@
|
|
|
3
3
|
module FastSerializer
|
|
4
4
|
module JsonModel
|
|
5
5
|
class HasManyRelationship < Relationship
|
|
6
|
-
|
|
6
|
+
# @param resource [Object]
|
|
7
|
+
# @param params [Hash]
|
|
8
|
+
# @return [Array<Hash>]
|
|
9
|
+
def serialize(resource, params, _context)
|
|
7
10
|
collection = resource.public_send(method)
|
|
8
11
|
return if collection.nil?
|
|
9
12
|
|
|
10
13
|
if @serializer_klass
|
|
11
14
|
@serializer_klass.new(collection, params).serializable_hash
|
|
12
15
|
elsif @schema
|
|
13
|
-
collection.map { |
|
|
16
|
+
collection.map { |entry| @schema.serialize_resource(entry, params) }
|
|
14
17
|
end
|
|
15
|
-
|
|
16
18
|
end
|
|
17
19
|
end
|
|
18
20
|
end
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
module FastSerializer
|
|
4
4
|
module JsonModel
|
|
5
5
|
class HasOneRelationship < Relationship
|
|
6
|
-
|
|
6
|
+
# @param resource [Object]
|
|
7
|
+
# @param params [Hash]
|
|
8
|
+
# @return [Hash]
|
|
9
|
+
def serialize(resource, params, _)
|
|
7
10
|
relation = resource.public_send(method)
|
|
8
11
|
|
|
9
12
|
if @serializer_klass
|
|
@@ -5,21 +5,25 @@ module FastSerializer
|
|
|
5
5
|
class Node
|
|
6
6
|
attr_accessor :key, :method, :context
|
|
7
7
|
|
|
8
|
+
# @param key [String]
|
|
9
|
+
# @param method [String]
|
|
10
|
+
# @param opts [Hash]
|
|
8
11
|
def initialize(key: nil, method: nil, opts: {}, **_)
|
|
9
12
|
@key = key&.to_sym
|
|
10
13
|
@method = method || key
|
|
11
14
|
@opts = opts || {}
|
|
12
15
|
end
|
|
13
16
|
|
|
17
|
+
# @return [Boolean]
|
|
14
18
|
def injectable?
|
|
15
19
|
false
|
|
16
20
|
end
|
|
17
21
|
|
|
18
|
-
def serialize(_resource, _params,
|
|
22
|
+
def serialize(_resource, _params, _context = nil)
|
|
19
23
|
raise NotImplementedError
|
|
20
24
|
end
|
|
21
25
|
|
|
22
|
-
def included?(_resource, _params,
|
|
26
|
+
def included?(_resource, _params, _context = nil)
|
|
23
27
|
raise NotImplementedError
|
|
24
28
|
end
|
|
25
29
|
end
|
|
@@ -10,23 +10,31 @@ module FastSerializer
|
|
|
10
10
|
@attributes = {}
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# @param attribute [FastSerializer::JsonModel::Node]
|
|
13
14
|
def add_attribute(attribute)
|
|
14
15
|
attributes[attribute.key] = attribute
|
|
15
16
|
end
|
|
16
17
|
|
|
18
|
+
# @param resource [Object]
|
|
19
|
+
# @param params [Hash]
|
|
20
|
+
# @param context [Hash]
|
|
21
|
+
# @return [Hash]
|
|
17
22
|
def serialize(resource, params, context)
|
|
18
23
|
return if resource.nil?
|
|
19
24
|
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
result = {}
|
|
26
|
+
|
|
27
|
+
attributes.each do |_, attribute|
|
|
28
|
+
next unless attribute.included?(resource, params, context)
|
|
22
29
|
|
|
23
30
|
val = attribute.serialize(resource, params, context)
|
|
24
|
-
|
|
31
|
+
result[attribute.key] = val
|
|
25
32
|
end
|
|
26
33
|
|
|
27
|
-
|
|
34
|
+
result
|
|
28
35
|
end
|
|
29
36
|
|
|
37
|
+
# @return [Boolean]
|
|
30
38
|
def included?(*)
|
|
31
39
|
true
|
|
32
40
|
end
|
|
@@ -5,32 +5,49 @@ module FastSerializer
|
|
|
5
5
|
class Relationship < Attribute
|
|
6
6
|
attr_accessor :serialization_schema
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
# @param serializer [FastSerializer::Schema::Mixin]
|
|
9
|
+
# @param schema [FastSerializer::Schema]
|
|
10
|
+
def initialize(serializer: nil, schema: nil, **)
|
|
9
11
|
super
|
|
12
|
+
|
|
10
13
|
@serializer_klass = serializer
|
|
11
14
|
@schema = schema
|
|
12
15
|
|
|
13
|
-
|
|
16
|
+
if @serializer_klass.nil? && @schema.nil?
|
|
17
|
+
raise ArgumentError, 'must provide serializer or schema'
|
|
18
|
+
end
|
|
14
19
|
end
|
|
15
20
|
|
|
21
|
+
# @param resource [Object]
|
|
22
|
+
# @param params [Hash]
|
|
23
|
+
# @param context [Hash]
|
|
24
|
+
# @return [Boolean]
|
|
16
25
|
def included?(resource, params, context)
|
|
17
26
|
super && include_relation?(params)
|
|
18
27
|
end
|
|
19
28
|
|
|
29
|
+
# @param params [Hash]
|
|
30
|
+
# @return [Boolean]
|
|
20
31
|
def include_relation?(params)
|
|
21
32
|
include?(params) && !exclude?(params)
|
|
22
33
|
end
|
|
23
34
|
|
|
35
|
+
# @param params [Hash]
|
|
36
|
+
# @return [Boolean]
|
|
24
37
|
def exclude?(params)
|
|
25
38
|
return false if params[:exclude].nil?
|
|
26
39
|
return false if params[:exclude].empty?
|
|
40
|
+
|
|
27
41
|
params[:exclude_index].key?(key)
|
|
28
42
|
end
|
|
29
43
|
|
|
44
|
+
# @param params [Hash]
|
|
45
|
+
# @return [Boolean]
|
|
30
46
|
def include?(params)
|
|
31
47
|
return true if params[:include].nil?
|
|
32
48
|
return false if params[:include].empty?
|
|
33
|
-
|
|
49
|
+
|
|
50
|
+
params[:include_index].key?(key)
|
|
34
51
|
end
|
|
35
52
|
end
|
|
36
53
|
end
|
|
@@ -3,13 +3,9 @@
|
|
|
3
3
|
require 'forwardable'
|
|
4
4
|
|
|
5
5
|
module FastSerializer
|
|
6
|
-
|
|
7
6
|
class Schema
|
|
8
|
-
|
|
9
7
|
attr_reader :_root, :serialization_schema, :params, :strict
|
|
10
8
|
|
|
11
|
-
public
|
|
12
|
-
|
|
13
9
|
def initialize(params = {}, root = nil, strict = nil)
|
|
14
10
|
@root = root
|
|
15
11
|
@strict = strict || FastSerializer.config.strict
|
|
@@ -24,79 +20,98 @@ module FastSerializer
|
|
|
24
20
|
end
|
|
25
21
|
|
|
26
22
|
def include=(list)
|
|
27
|
-
return
|
|
23
|
+
return unless list
|
|
24
|
+
return if list.empty?
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
@params[:include_index] = @params[:include].map { |key| [key, nil] }.to_h
|
|
32
|
-
end
|
|
26
|
+
@params[:include] = list.map(&:to_sym)
|
|
27
|
+
@params[:include_index] = @params[:include].map { |key| [key, nil] }.to_h
|
|
33
28
|
end
|
|
34
29
|
|
|
35
30
|
def exclude=(list)
|
|
36
|
-
return
|
|
31
|
+
return unless list
|
|
32
|
+
return if list.empty?
|
|
37
33
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@params[:exclude_index] = @params[:exclude].map { |key| [key, nil] }.to_h
|
|
41
|
-
end
|
|
34
|
+
@params[:exclude] = list.map(&:to_sym)
|
|
35
|
+
@params[:exclude_index] = @params[:exclude].map { |key| [key, nil] }.to_h
|
|
42
36
|
end
|
|
43
37
|
|
|
44
|
-
#
|
|
38
|
+
# Defines a list of attributes for serialization
|
|
39
|
+
#
|
|
40
|
+
# @param attribute_names [Array<String, Symbol>] a list of attributes to serialize
|
|
41
|
+
# each of these attributes value is fetched calling a corresponding method from a resource instance
|
|
42
|
+
# passed to the serializer
|
|
45
43
|
def attributes(*attribute_names)
|
|
46
44
|
attribute_names.each do |attribute_name|
|
|
47
|
-
serialization_schema.add_attribute
|
|
48
|
-
key:
|
|
49
|
-
method: attribute_name,
|
|
45
|
+
serialization_schema.add_attribute(
|
|
46
|
+
JsonModel::Attribute.new(key: attribute_name, method: attribute_name)
|
|
50
47
|
)
|
|
51
48
|
end
|
|
52
49
|
end
|
|
53
50
|
|
|
54
|
-
#
|
|
55
|
-
#
|
|
56
|
-
# @param [
|
|
51
|
+
# Defines an attribute for serialization
|
|
52
|
+
#
|
|
53
|
+
# @param attribute_name [String, Symbol] an attribute name
|
|
54
|
+
# @param opts [Hash] attribute options
|
|
55
|
+
# @option opts [Proc] :if conditional clause. accepts a proc/lambda which has to return a boolean
|
|
56
|
+
# @option opts [Proc] :unless (see opts:if)
|
|
57
|
+
# @param block [Proc] result is used as the attribute value
|
|
58
|
+
#
|
|
57
59
|
def attribute(attribute_name, opts = {}, &block)
|
|
58
|
-
serialization_schema.add_attribute
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
serialization_schema.add_attribute(
|
|
61
|
+
JsonModel::Attribute.new(
|
|
62
|
+
key: attribute_name,
|
|
63
|
+
method: block,
|
|
64
|
+
opts: opts
|
|
65
|
+
)
|
|
62
66
|
)
|
|
63
67
|
end
|
|
64
68
|
|
|
65
|
-
#
|
|
66
|
-
#
|
|
69
|
+
# Defines an attribute for serialization
|
|
70
|
+
#
|
|
71
|
+
# @param attribute_name [String, Symbol] an attribute name
|
|
72
|
+
# @param opts [Hash] attribute options
|
|
73
|
+
# @option opts [Proc] :if conditional clause. accepts a proc/lambda which has to return a boolean
|
|
74
|
+
# @option opts [Proc] :unless (see opts:if)
|
|
75
|
+
# @option opts [FastSerializer::Schema::Mixin, nil] :serializer a serializer class with injected module or a inherited class
|
|
76
|
+
# @option opts [FastSerializer::Schema] :schema
|
|
77
|
+
#
|
|
67
78
|
def has_one(attribute_name, opts = {})
|
|
68
79
|
serialization_schema.add_attribute JsonModel::HasOneRelationship.new(
|
|
69
|
-
key:
|
|
70
|
-
method:
|
|
71
|
-
opts:
|
|
72
|
-
schema:
|
|
73
|
-
serializer: opts.delete(:serializer)
|
|
80
|
+
key: opts.delete(:key) || attribute_name,
|
|
81
|
+
method: opts.delete(:method) || attribute_name,
|
|
82
|
+
opts: opts,
|
|
83
|
+
schema: opts.delete(:schema),
|
|
84
|
+
serializer: opts.delete(:serializer)
|
|
74
85
|
)
|
|
75
86
|
end
|
|
76
87
|
|
|
77
88
|
alias belongs_to has_one
|
|
78
89
|
|
|
79
|
-
# @param [String]
|
|
80
|
-
# @param [Hash]
|
|
90
|
+
# @param attribute_name [String]
|
|
91
|
+
# @param opts [Hash] attribute options
|
|
81
92
|
def has_many(attribute_name, opts = {})
|
|
82
|
-
serialization_schema.add_attribute
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
93
|
+
serialization_schema.add_attribute(
|
|
94
|
+
JsonModel::HasManyRelationship.new(
|
|
95
|
+
key: opts.delete(:key) || attribute_name,
|
|
96
|
+
method: opts.delete(:method) || attribute_name,
|
|
97
|
+
opts: opts,
|
|
98
|
+
schema: opts.delete(:schema),
|
|
99
|
+
serializer: opts.delete(:serializer)
|
|
100
|
+
)
|
|
88
101
|
)
|
|
89
102
|
end
|
|
90
103
|
|
|
91
104
|
# @param [String] attribute_name
|
|
92
105
|
# @param [Hash] opts - attribute options
|
|
93
106
|
def list(attribute_name, opts = {})
|
|
94
|
-
serialization_schema.add_attribute
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
serialization_schema.add_attribute(
|
|
108
|
+
JsonModel::Array.new(
|
|
109
|
+
key: attribute_name,
|
|
110
|
+
method: attribute_name,
|
|
111
|
+
opts: opts,
|
|
112
|
+
schema: opts.delete(:schema),
|
|
113
|
+
serializer: opts.delete(:serializer)
|
|
114
|
+
)
|
|
100
115
|
)
|
|
101
116
|
end
|
|
102
117
|
|
|
@@ -116,11 +131,15 @@ module FastSerializer
|
|
|
116
131
|
end
|
|
117
132
|
|
|
118
133
|
def serialize_resource(resource, params = {}, context = self)
|
|
119
|
-
|
|
134
|
+
Utils.ref_merge(self.params, params)
|
|
135
|
+
_params_dup = FastSerializer::Utils.symbolize_keys(self.params)
|
|
120
136
|
meta = _params_dup.delete(:meta)
|
|
121
137
|
|
|
122
|
-
is_collection =
|
|
123
|
-
|
|
138
|
+
is_collection = if params.key?(:is_collection)
|
|
139
|
+
params.delete(:is_collection)
|
|
140
|
+
else
|
|
141
|
+
resource.respond_to?(:size) && !resource.respond_to?(:each_pair)
|
|
142
|
+
end
|
|
124
143
|
|
|
125
144
|
root = (_root || _params_dup.delete(:root))
|
|
126
145
|
|
|
@@ -139,7 +158,7 @@ module FastSerializer
|
|
|
139
158
|
|
|
140
159
|
end
|
|
141
160
|
|
|
142
|
-
res
|
|
161
|
+
res = { root => res } if root && !root.empty?
|
|
143
162
|
|
|
144
163
|
res[:meta] = meta if res.is_a?(Hash) && meta
|
|
145
164
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module FastSerializer
|
|
2
4
|
class Schema
|
|
3
5
|
module Mixin
|
|
4
|
-
|
|
5
6
|
module ClassMethods
|
|
6
7
|
attr_accessor :__schema__, :__patched__
|
|
7
8
|
|
|
8
9
|
def inherited(subclass)
|
|
9
|
-
subclass.__schema__ =
|
|
10
|
+
subclass.__schema__ = __schema__.deep_copy
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def method_missing(method, *args, &block)
|
|
@@ -16,6 +17,18 @@ module FastSerializer
|
|
|
16
17
|
super
|
|
17
18
|
end
|
|
18
19
|
end
|
|
20
|
+
|
|
21
|
+
def respond_to_missing?(method_name, include_private = false)
|
|
22
|
+
__schema__.respond_to?(method_name) || super
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def __patch_with_attribute_definition
|
|
26
|
+
injectable_attributes = __schema__.serialization_schema.attributes.select { |_key, attribute| attribute.injectable? }
|
|
27
|
+
injectable_attributes.each { |_, attribute| attribute.inject(self) }
|
|
28
|
+
self.__patched__ = true
|
|
29
|
+
|
|
30
|
+
__patched__.freeze
|
|
31
|
+
end
|
|
19
32
|
end
|
|
20
33
|
|
|
21
34
|
module InstanceMethods
|
|
@@ -26,16 +39,14 @@ module FastSerializer
|
|
|
26
39
|
self.params = params || {}
|
|
27
40
|
end
|
|
28
41
|
|
|
29
|
-
|
|
42
|
+
alias object resource
|
|
30
43
|
|
|
31
44
|
def serializable_hash(opts = {})
|
|
32
|
-
|
|
45
|
+
Utils.ref_merge(params, opts)
|
|
46
|
+
self.params = params
|
|
33
47
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
injectable_attributes.each { |key, attribute| attribute.inject(self.class) }
|
|
37
|
-
self.class.__patched__ = true
|
|
38
|
-
self.class.__patched__.freeze
|
|
48
|
+
unless self.class.__patched__
|
|
49
|
+
self.class.__patch_with_attribute_definition
|
|
39
50
|
end
|
|
40
51
|
|
|
41
52
|
self.class.__schema__.serialize_resource(resource, params, self)
|
|
@@ -57,4 +68,4 @@ module FastSerializer
|
|
|
57
68
|
end
|
|
58
69
|
end
|
|
59
70
|
end
|
|
60
|
-
end
|
|
71
|
+
end
|
|
@@ -1,9 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module FastSerializer
|
|
2
4
|
module Utils
|
|
3
5
|
def self.symbolize_keys(hash)
|
|
4
6
|
res = {}
|
|
5
|
-
hash.each { |key,
|
|
7
|
+
hash.each { |key, value| res[key.to_sym] = value }
|
|
6
8
|
hash
|
|
7
9
|
end
|
|
10
|
+
|
|
11
|
+
def self.ref_merge(hash_a, hash_b)
|
|
12
|
+
hash_b.each do |key, value|
|
|
13
|
+
hash_a[key] = value
|
|
14
|
+
end
|
|
15
|
+
end
|
|
8
16
|
end
|
|
9
17
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: fast_serializer_ruby
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Evgeny Stepanov
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2020-
|
|
11
|
+
date: 2020-03-17 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: This library intends to solve such a typical and on the other hand important
|
|
14
14
|
problem as efficient ruby object to hash transformation.
|
|
@@ -66,7 +66,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
66
66
|
- !ruby/object:Gem::Version
|
|
67
67
|
version: '0'
|
|
68
68
|
requirements: []
|
|
69
|
-
rubygems_version: 3.
|
|
69
|
+
rubygems_version: 3.1.2
|
|
70
70
|
signing_key:
|
|
71
71
|
specification_version: 4
|
|
72
72
|
summary: fast_serializer is a lightweight ruby objects serializer.
|