pb-serializer 0.1.0 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f67d4a17784718471b0092c70c74d8ad19c3c7dcd7d0003268d0b52ee1cff8b5
4
- data.tar.gz: 970526e14d3bacab347a57fb1a556ea041529cca3e2d9ad0e5aaf4482f4808bb
3
+ metadata.gz: 3d65ab2cd7830751ed61e5cd72eca1d688fac910b544167994780d065e55fa3b
4
+ data.tar.gz: e991534beffa6fb92b4c23f05bf59b5ba0ef6872cd34dc801148e08ec3f2c075
5
5
  SHA512:
6
- metadata.gz: 922d74b4ca48c70e6fc37358a994630fceb3244acb8af39523dc60b8288a25c8f4f44f45c67e663743b01800fb8ec7a60b5f6804598d698ea42531947d5cb81d
7
- data.tar.gz: 87fb4dec4bb9e073d6b461fd1b0d80803e8f1763a021e33746b9e789dfe71566dc9ccdf45ae9ca3834c4aeeb152b53660ee4bb4fedbd1525d4d81304b7f6c233
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, serializer: PostSerializer
9
+ attribute :posts, required: true
10
10
 
11
- define_loader :posts do |users, subdeps, **|
12
- posts = Post.where(user_id: users.map(&:id)).index_by(&:user_id)
13
- users.each do |user|
14
- user.posts = posts[user.id]
15
- end
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
- object.posts.size
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
- user = User.find(id: req.user_id)
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
- friends = User.find(current_user_id).friends
49
+ current_user = User.find(current_user_id)
46
50
  YourApp::ListFriendUsersResponse.new(
47
- users: UserSerializer.serialize_repeated(friends, with: req.field_mask),
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
 
@@ -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
- if with.nil?
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, "#{object.class.name}##{attr.name} is required"
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, "#{object.class.name}##{attr.name} is oneof attribute"
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, "#{object.class.name}##{oneof.name} is required"
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
- object.public_send(attr.name) # FIXME: This does not work without ::Pb::Serializer::Base
112
+ primary_object.public_send(attr.name)
83
113
  end
114
+ end
84
115
 
85
- dependency # FIXME
86
- computed attr.name
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
- # @param object [Object, Array]
90
- # @param message_class [Class]
91
- def serialize(object, with: nil)
92
- if self < ::Pb::Serializer::Base
93
- new(object).to_pb
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.serialize(v) if 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}"
@@ -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
@@ -1,5 +1,5 @@
1
1
  module Pb
2
2
  module Serializer
3
- VERSION = "0.1.0".freeze
3
+ VERSION = "0.2.0".freeze
4
4
  end
5
5
  end
@@ -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.0"
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.1.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-17 00:00:00.000000000 Z
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.0
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.0
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.0.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