pb-serializer 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -11
- data/lib/pb/serializable.rb +53 -19
- data/lib/pb/serializer/attribute.rb +1 -1
- data/lib/pb/serializer/base.rb +13 -0
- data/lib/pb/serializer/version.rb +1 -1
- data/pb-serializer.gemspec +1 -1
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3d65ab2cd7830751ed61e5cd72eca1d688fac910b544167994780d065e55fa3b
|
4
|
+
data.tar.gz: e991534beffa6fb92b4c23f05bf59b5ba0ef6872cd34dc801148e08ec3f2c075
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a138f78df718b226cbf65cef851380a941c34306ed80bdc2fb65093f0dec804515d0187d3f0b11e4fcd36bbc339dfca08f2beef49989d6417ccf157ddf9da97
|
7
|
+
data.tar.gz: bf343a1d3f7f055370f652616fc6914dc682f2fdc6840c6975614537d5ecf02241974b8df986505f96a517401b676e0756aa2040d181898e8dc866ee76ab305c
|
data/README.md
CHANGED
@@ -6,24 +6,29 @@ class UserSerializer < Pb::Serializer::Base
|
|
6
6
|
|
7
7
|
attribute :id, required: true
|
8
8
|
attribute :name, required: true
|
9
|
-
attribute :posts, required: true
|
9
|
+
attribute :posts, required: true
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
define_primary_loader :user do |subdeps, ids:, **|
|
12
|
+
User.where(id: ids).preload(subdeps).map { |u| new(u) }
|
13
|
+
end
|
14
|
+
|
15
|
+
define_loader :posts, key: -> { id } do |user_ids, subdeps, **|
|
16
|
+
PostSerializer.bulk_load(user_id: user_ids, with: subdeps).group_by { |s| s.post.user_id }
|
16
17
|
end
|
17
18
|
|
18
19
|
dependency :posts
|
19
20
|
computed def post_count
|
20
|
-
|
21
|
+
posts.count
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
25
|
class PostSerializer < Pb::Serializer::Base
|
25
26
|
message YourApp::Post
|
26
27
|
|
28
|
+
define_primary_loader :post do |subdeps, user_ids:, **|
|
29
|
+
Post.where(user_id: user_ids).preload(subdeps).map { |p| new(p) }
|
30
|
+
end
|
31
|
+
|
27
32
|
attribute :id, required: true
|
28
33
|
attribute :title, required: true
|
29
34
|
attribute :body, required: true
|
@@ -34,22 +39,23 @@ class UserGrpcService < YourApp::UserService::Service
|
|
34
39
|
# @param call [GRPC::ActiveCall::SingleReqView]
|
35
40
|
# @return [YourApp::User]
|
36
41
|
def get_users(req, call)
|
37
|
-
|
38
|
-
UserSerializer.serialize(user, with: req.field_mask)
|
42
|
+
UserSerializer.bulk_load_and_serialize(ids: [req.user_id], with: req.field_mask)[0]
|
39
43
|
end
|
40
44
|
|
41
45
|
# @param req [YourApp::ListFriendUsersRequest]
|
42
46
|
# @param call [GRPC::ActiveCall::SingleReqView]
|
43
47
|
# @return [YourApp::ListFriendUsersResponse]
|
44
48
|
def list_friend_users(req, call)
|
45
|
-
|
49
|
+
current_user = User.find(current_user_id)
|
46
50
|
YourApp::ListFriendUsersResponse.new(
|
47
|
-
users: UserSerializer.
|
51
|
+
users: UserSerializer.bulk_load_and_serialize(ids: current_user.friend_ids, with: req.field_mask)
|
48
52
|
)
|
49
53
|
end
|
50
54
|
end
|
51
55
|
```
|
52
56
|
|
57
|
+
More examples are available under [./spec/examples](./spec/examples).
|
58
|
+
|
53
59
|
|
54
60
|
## Installation
|
55
61
|
|
data/lib/pb/serializable.rb
CHANGED
@@ -3,14 +3,11 @@ module Pb
|
|
3
3
|
def self.included(base)
|
4
4
|
base.extend ClassMethods
|
5
5
|
base.include ComputedModel
|
6
|
+
base.singleton_class.prepend Hook
|
6
7
|
end
|
7
8
|
|
8
9
|
def to_pb(with: nil)
|
9
|
-
|
10
|
-
with = ::Pb::Serializer.build_default_mask(self.class.message_class.descriptor)
|
11
|
-
end
|
12
|
-
|
13
|
-
self.class.bulk_load_and_compute(Array(self), with)
|
10
|
+
# TODO: apply masks
|
14
11
|
|
15
12
|
oneof_set = []
|
16
13
|
|
@@ -26,14 +23,14 @@ module Pb
|
|
26
23
|
v = attr.convert_to_pb(v)
|
27
24
|
|
28
25
|
if attr.required && attr.field_descriptor.default == v
|
29
|
-
raise ::Pb::Serializer::ValidationError, "#{
|
26
|
+
raise ::Pb::Serializer::ValidationError, "#{primary_object.class.name}##{attr.name} is required"
|
30
27
|
end
|
31
28
|
|
32
29
|
next if v.nil?
|
33
30
|
|
34
31
|
if attr.oneof?
|
35
32
|
if oneof_set.include?(attr.oneof)
|
36
|
-
raise ::Pb::Serializer::ConflictOneofError, "#{
|
33
|
+
raise ::Pb::Serializer::ConflictOneofError, "#{primary_object.class.name}##{attr.name} is oneof attribute"
|
37
34
|
end
|
38
35
|
oneof_set << attr.oneof
|
39
36
|
end
|
@@ -48,14 +45,47 @@ module Pb
|
|
48
45
|
self.class.oneofs.each do |oneof|
|
49
46
|
next if oneof_set.include?(oneof.name)
|
50
47
|
next unless oneof.required?
|
51
|
-
raise ::Pb::Serializer::ValidationError, "#{
|
48
|
+
raise ::Pb::Serializer::ValidationError, "#{primary_object.class.name}##{oneof.name} is required"
|
52
49
|
end
|
53
50
|
|
54
51
|
o
|
55
52
|
end
|
56
53
|
|
54
|
+
private def primary_object
|
55
|
+
primary_object_name = self.class.__pb_serializer_primary_model_name
|
56
|
+
if primary_object_name
|
57
|
+
send(primary_object_name)
|
58
|
+
elsif kind_of?(Serializer::Base)
|
59
|
+
send(:object)
|
60
|
+
else
|
61
|
+
self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module Hook
|
66
|
+
def define_primary_loader(name)
|
67
|
+
self.__pb_serializer_primary_model_name = name
|
68
|
+
|
69
|
+
super
|
70
|
+
end
|
71
|
+
|
72
|
+
def computed(name)
|
73
|
+
__pb_serializer_attrs << name
|
74
|
+
|
75
|
+
super
|
76
|
+
end
|
77
|
+
|
78
|
+
def define_loader(name, **)
|
79
|
+
__pb_serializer_attrs << name
|
80
|
+
|
81
|
+
super
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
57
85
|
module ClassMethods
|
58
86
|
attr_reader :message_class
|
87
|
+
attr_accessor :__pb_serializer_primary_model_name
|
88
|
+
|
59
89
|
def message(klass)
|
60
90
|
@message_class = klass
|
61
91
|
end
|
@@ -79,21 +109,21 @@ module Pb
|
|
79
109
|
@attr_by_name[name] = attr
|
80
110
|
|
81
111
|
define_method attr.name do
|
82
|
-
|
112
|
+
primary_object.public_send(attr.name)
|
83
113
|
end
|
114
|
+
end
|
84
115
|
|
85
|
-
|
86
|
-
|
116
|
+
# @param with [Array, Google::Protobuf::FieldMask, nil]
|
117
|
+
# @return [Array]
|
118
|
+
def bulk_load_and_serialize(with: nil, **args)
|
119
|
+
bulk_load(with: with, **args).map { |s| s.to_pb(with: with) }
|
87
120
|
end
|
88
121
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
else
|
95
|
-
object.to_pb
|
96
|
-
end
|
122
|
+
def bulk_load(with: nil, **args)
|
123
|
+
with ||= ::Pb::Serializer.build_default_mask(message_class.descriptor)
|
124
|
+
with = with.reject { |c| (__pb_serializer_attrs & (c.kind_of?(Hash) ? c.keys : [c])).empty? }
|
125
|
+
|
126
|
+
bulk_load_and_compute(with, **args)
|
97
127
|
end
|
98
128
|
|
99
129
|
def oneof(name, required: true)
|
@@ -108,6 +138,10 @@ module Pb
|
|
108
138
|
@current_oneof = nil
|
109
139
|
end
|
110
140
|
|
141
|
+
private def __pb_serializer_attrs
|
142
|
+
@__pb_serializer_attrs ||= Set.new
|
143
|
+
end
|
144
|
+
|
111
145
|
# @param fd [Google::Protobuf::FieldDescriptor] a field descriptor
|
112
146
|
# @return [Pb::Serializer::Attribute, nil]
|
113
147
|
def find_attribute_by_field_descriptor(fd)
|
@@ -42,7 +42,7 @@ module Pb
|
|
42
42
|
when "google.protobuf.BytesValue" then Pb.to_bytesval(v)
|
43
43
|
else
|
44
44
|
return nil if v.nil?
|
45
|
-
return serializer_class.
|
45
|
+
return serializer_class.new(v).to_pb if serializer_class
|
46
46
|
return v.to_pb if v.kind_of?(::Pb::Serializable)
|
47
47
|
|
48
48
|
raise "serializer was not found for #{field_descriptor.submsg_name}"
|
data/lib/pb/serializer/base.rb
CHANGED
@@ -3,6 +3,7 @@ module Pb
|
|
3
3
|
class Base
|
4
4
|
def self.inherited(base)
|
5
5
|
base.include ::Pb::Serializable
|
6
|
+
base.singleton_class.prepend Hook
|
6
7
|
end
|
7
8
|
|
8
9
|
attr_reader :object
|
@@ -10,6 +11,18 @@ module Pb
|
|
10
11
|
def initialize(object)
|
11
12
|
@object = object
|
12
13
|
end
|
14
|
+
|
15
|
+
module Hook
|
16
|
+
def define_primary_loader(name, &block)
|
17
|
+
class_eval <<~RUBY
|
18
|
+
def initialize(object)
|
19
|
+
@#{name} = object
|
20
|
+
end
|
21
|
+
RUBY
|
22
|
+
|
23
|
+
super
|
24
|
+
end
|
25
|
+
end
|
13
26
|
end
|
14
27
|
end
|
15
28
|
end
|
data/pb-serializer.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
rails_versions = [">= 5.2", "< 6.1"]
|
30
30
|
spec.add_runtime_dependency "google-protobuf", "~> 3.0"
|
31
31
|
spec.add_runtime_dependency "the_pb", "~> 0.0.1"
|
32
|
-
spec.add_runtime_dependency "computed_model", "~> 0.1
|
32
|
+
spec.add_runtime_dependency "computed_model", "~> 0.2.1"
|
33
33
|
|
34
34
|
spec.add_development_dependency "activerecord", rails_versions
|
35
35
|
spec.add_development_dependency "bundler", "~> 2.0"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pb-serializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- izumin5210
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-03-
|
11
|
+
date: 2020-03-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: google-protobuf
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: 0.1
|
47
|
+
version: 0.2.1
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: 0.1
|
54
|
+
version: 0.2.1
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: activerecord
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -205,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
205
|
- !ruby/object:Gem::Version
|
206
206
|
version: '0'
|
207
207
|
requirements: []
|
208
|
-
rubygems_version: 3.
|
208
|
+
rubygems_version: 3.1.2
|
209
209
|
signing_key:
|
210
210
|
specification_version: 4
|
211
211
|
summary: Serialize objects into Protocol Buffers messages
|