userializer 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6ff350c75deb5f250911135a9ea0cd76b0d0edc451186f5a870895818476862d
4
- data.tar.gz: 6faf6e27adbc666f620235d15ec4d8ceb62b54ef39416c6693c81d0f59cf84ff
3
+ metadata.gz: 39db10c77bd519fffda4b6e6c7e613bc1105a951ab39e677dd8d1aaa0aa6f6b0
4
+ data.tar.gz: 5327aa7eb5e03f5abe504e4dde6d4e619df810af3802e896e28a72e9edc5c21f
5
5
  SHA512:
6
- metadata.gz: 55bb0fae587d95804183d68495be2e19da3fe1d3f26acb5604fd0a05a715357a14ac6027af276d42c03f59e12067f54f35b85ee09452c2455987b9bcf4be3b8a
7
- data.tar.gz: d0219c7986d8bb650d247f1d6e43612f84afc6ee58f7919da08767b760c8a720e1a9d5aef343a03a43c89a8981dfdc936507e2036dfefe81c5fbb72ea3806c1c
6
+ metadata.gz: 1fcc67f9270e9c8359dc4488eaf11684fcb952f563a64d41f90cae3d83c1ff31a5c271c2247bc538fa3b5877241d3a7f769a32100c9e04ed9cb327caa15fa92f
7
+ data.tar.gz: 982d8a1495d2c3a6eb83b498b79a6e9d40910f05226b3e4d14a0d5ab1100d04c4145c1d7e14ccd083f5329cf380089300e131848b7d9d2e6692f498793057b91
@@ -0,0 +1,28 @@
1
+ ### What does this PR do?
2
+
3
+ <!-- A brief description of the context of this pull request and its purpose. -->
4
+
5
+ ### What are the observable changes?
6
+ <!-- This question could be adequate with multiple use cases, for example: -->
7
+
8
+ <!-- Frontend: explain the feature created / updated, give instructions telling how to see the change in staging -->
9
+ <!-- Performance: what metric should be impacted, link to the right graphana dashboard for exemple -->
10
+ <!-- Bug: a given issue trail on sentry should stop happening -->
11
+ <!-- Feature: Implements X thrift service / Z HTTP REST API added, provide instructions on how leverage your feature from staging or your workstation -->
12
+
13
+ ### Good PR checklist
14
+
15
+ - [ ] Title makes sense
16
+ - [ ] Is against the correct branch
17
+ - [ ] Only addresses one issue
18
+ - [ ] Properly assigned
19
+ - [ ] Added/updated tests
20
+ - [ ] Added/updated documentation
21
+ - [ ] Properly labeled
22
+
23
+ ### Additional Notes
24
+
25
+ <!--
26
+ You can add anything you want here, an explanation on the way you built your implementation,
27
+ precisions on the origin of the bug, gotchas you need to mention.
28
+ -->
@@ -0,0 +1,25 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - master
7
+ pull_request:
8
+
9
+ jobs:
10
+ test:
11
+ name: Run Tests
12
+ runs-on: ubuntu-20.04
13
+ strategy:
14
+ matrix:
15
+ ruby: [2.7, 3.0.3]
16
+ steps:
17
+ - name: Checkout
18
+ uses: actions/checkout@v2
19
+ - name: Install Ruby
20
+ uses: ruby/setup-ruby@v1
21
+ with:
22
+ ruby-version: ${{ matrix.ruby }}
23
+ bundler-cache: true
24
+ - name: Run the Test Suite
25
+ run: bundle exec rspec --color --require spec_helper --format progress spec
data/README.md CHANGED
@@ -167,6 +167,33 @@ different situations:
167
167
  }
168
168
  ```
169
169
 
170
+ ### CompositeSerializer
171
+
172
+ Imagine you have a compound of different data that you want to return to the same payload.
173
+ For example, you have an **array** of a `Foo` class and a `Bar` value to return.
174
+ You can use a `CompositeSerializer` to serialize both.
175
+
176
+ ```ruby
177
+ array_foo = [Foo.new, Foo.new]
178
+ bar = Bar.new
179
+
180
+ CompositeSerializer.new(
181
+ { key_foo: array_foo, key_bar: bar },
182
+ each_serializer: { key_foo: FooCustomSerializer },
183
+ serializer: { key_bar: BarSerializer },
184
+ root: { key_foo: :foo_root, key_bar: :bar_root }
185
+ ).to_json
186
+ ```
187
+
188
+ this will render:
189
+
190
+ ```json
191
+ {
192
+ "foo_root": [{... foo1 attributes ...}, {... foo2 attributes ...}],
193
+ "bar_root": {... bar attributes ...}
194
+ }
195
+ ```
196
+
170
197
  ## Development
171
198
 
172
199
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -45,6 +45,7 @@ module USerializer
45
45
  @opts = opts
46
46
  @meta = opts[:meta]
47
47
  @except = Set.new([opts[:except]].flatten.compact)
48
+ @only = Set.new([opts[:only]].flatten.compact)
48
49
 
49
50
  @root_key = (opts[:root] || ActiveSupport::Inflector.underscore(
50
51
  obj.class.name
@@ -99,15 +100,20 @@ module USerializer
99
100
  private
100
101
 
101
102
  def attributes
102
- @attributes ||= (self.class.attrs || {}).values.reject do |attr|
103
- @except.include?(attr.key)
103
+ @attributes ||= (self.class.attrs || {}).values.select do |attr|
104
+ allow?(attr.key)
104
105
  end
105
106
  end
106
107
 
107
108
  def relations
108
- @relations ||= (self.class.relations || {}).values.reject do |rel|
109
- @except.include?(rel.key)
109
+ @relations ||= (self.class.relations || {}).values.select do |rel|
110
+ allow?(rel.key)
110
111
  end
111
112
  end
113
+
114
+ def allow?(key)
115
+ return @only.include?(key) if @only.any?
116
+ !@except.include?(key)
117
+ end
112
118
  end
113
119
  end
@@ -0,0 +1,78 @@
1
+ require 'oj'
2
+
3
+ module USerializer
4
+ class CompositeObject
5
+ def initialize(obj, opts = {})
6
+ @obj = obj
7
+ @opts = opts
8
+ @root_key = opts[:root].to_sym
9
+ serializer = opts[:serializer]
10
+ @serializer = if serializer.is_a?(Proc)
11
+ serializer
12
+ elsif serializer
13
+ proc { serializer }
14
+ end
15
+ end
16
+
17
+ def merge_root(res, opts)
18
+ serializer(@obj, opts).merge_root(res, @root_key, true, opts)
19
+ end
20
+
21
+ private
22
+
23
+ def serializer(obj, opts)
24
+ return @serializer.call(obj, opts).new(obj, @opts) if @serializer
25
+ return obj.serialize if obj.respond_to?(:serialize)
26
+
27
+ USerializer.infered_serializer_class(obj.class).new(obj, @opts)
28
+ end
29
+ end
30
+
31
+ class CompositeSerializer
32
+ def initialize(objs, opts = {})
33
+ @opts = opts
34
+ @objs = compose_objs(objs)
35
+ end
36
+
37
+ def merge_root(res, opts)
38
+ @objs.each do |obj|
39
+ obj.merge_root(res, opts)
40
+ end
41
+ end
42
+
43
+ def to_hash
44
+ res = {}
45
+
46
+ merge_root(res, @opts)
47
+ res
48
+ end
49
+
50
+ def serialize(*_args)
51
+ to_hash
52
+ end
53
+
54
+ def to_json(*_args)
55
+ Oj.dump(to_hash, mode: :compat)
56
+ end
57
+
58
+ private
59
+
60
+ def compose_objs(objs)
61
+ objs.map do |(key, obj)|
62
+ opts = options_for(key)
63
+
64
+ if obj.is_a? Enumerable
65
+ ArraySerializer.new(obj, opts)
66
+ else
67
+ CompositeObject.new(obj, opts)
68
+ end
69
+ end
70
+ end
71
+
72
+ def options_for(key)
73
+ @opts.reduce({}) do |acc, (opt_key, values)|
74
+ acc.merge(opt_key.to_sym => values[key.to_sym])
75
+ end.compact.merge(root: key) { |_, x, y| x || y }
76
+ end
77
+ end
78
+ end
@@ -6,7 +6,7 @@ module USerializer
6
6
  @key = key
7
7
 
8
8
  @opts = opts
9
- @id_key = "#{ActiveSupport::Inflector.singularize(key)}_ids".to_sym
9
+ @ids_key = opts[:ids_key] || build_ids_key(key)
10
10
 
11
11
  @embed_key = opts[:embed_key] || :id
12
12
  @conditional_block = opts[:if] || proc { true }
@@ -15,7 +15,7 @@ module USerializer
15
15
  def merge_attributes(res, ser, opts)
16
16
  return unless @conditional_block.call(ser.object, opts)
17
17
 
18
- res[@id_key] = (entities(ser) || []).compact.map do |obj|
18
+ res[@ids_key] = (entities(ser) || []).compact.map do |obj|
19
19
  obj.nil? ? nil : obj.send(@embed_key)
20
20
  end.compact
21
21
  end
@@ -34,5 +34,11 @@ module USerializer
34
34
 
35
35
  obj.send(@opts[:scope])
36
36
  end
37
+
38
+ private
39
+
40
+ def build_ids_key(key)
41
+ "#{ActiveSupport::Inflector.singularize(key)}_ids".to_sym
42
+ end
37
43
  end
38
44
  end
@@ -3,7 +3,7 @@ module USerializer
3
3
  def initialize(key, opts)
4
4
  @key = key
5
5
  @opts = opts
6
- @id_key = "#{key}_id".to_sym
6
+ @id_key = opts[:id_key] || "#{key}_id".to_sym
7
7
  @root_key = opts[:root]&.to_sym
8
8
 
9
9
  serializer = opts[:serializer]
@@ -1,3 +1,3 @@
1
1
  module USerializer
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.2"
3
3
  end
data/lib/userializer.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  require 'userializer/version'
2
2
  require 'userializer/base_serializer'
3
3
  require 'userializer/array_serializer'
4
+ require 'userializer/composite_serializer'
4
5
 
5
6
  module USerializer
6
7
  NS_SEPARATOR = '::'.freeze
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: userializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexis Montagne
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-02-01 00:00:00.000000000 Z
11
+ date: 2022-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -87,7 +87,8 @@ executables: []
87
87
  extensions: []
88
88
  extra_rdoc_files: []
89
89
  files:
90
- - ".circleci/config.yml"
90
+ - ".github/pull_request_template.md"
91
+ - ".github/workflows/ci.yml"
91
92
  - ".gitignore"
92
93
  - ".rspec"
93
94
  - ".travis.yml"
@@ -100,6 +101,7 @@ files:
100
101
  - lib/userializer/array_serializer.rb
101
102
  - lib/userializer/attribute.rb
102
103
  - lib/userializer/base_serializer.rb
104
+ - lib/userializer/composite_serializer.rb
103
105
  - lib/userializer/has_many.rb
104
106
  - lib/userializer/has_one.rb
105
107
  - lib/userializer/version.rb
@@ -122,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
124
  - !ruby/object:Gem::Version
123
125
  version: '0'
124
126
  requirements: []
125
- rubygems_version: 3.0.3
127
+ rubygems_version: 3.1.2
126
128
  signing_key:
127
129
  specification_version: 4
128
130
  summary: Write a short summary, because RubyGems requires one.
data/.circleci/config.yml DELETED
@@ -1,18 +0,0 @@
1
- version: 2
2
- jobs:
3
- run_tests:
4
- docker:
5
- - image: circleci/ruby:2.7
6
-
7
- working_directory: ~/userializer
8
-
9
- steps:
10
- - checkout
11
- - run: bundle install --path=vendor/bundle
12
- - run: bundle exec rspec --color --require spec_helper --format progress spec
13
-
14
- workflows:
15
- version: 2
16
- test:
17
- jobs:
18
- - run_tests