seri 1.1.8 → 2.0.1
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/.circleci/config.yml +2 -1
- data/.rubocop.yml +6 -0
- data/Gemfile.lock +25 -16
- data/README.md +7 -5
- data/lib/seri.rb +1 -0
- data/lib/serializer.rb +23 -21
- data/lib/serializer/group_serializer.rb +16 -14
- data/lib/serializer/value.rb +60 -56
- data/lib/serializer/value_fetcher.rb +42 -48
- data/lib/serializer/version.rb +4 -2
- data/seri.gemspec +3 -2
- metadata +22 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b195c3ae8c5ec78fa54317184b782970fe1d22d1b19f446d6297b5959a90b06b
|
4
|
+
data.tar.gz: df3042fb5c2f291fec12b63ece1036a5e75549503ea6896ac8ac167da0cb2e91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 030be24706b3a319c34cf167e4a9f833314235e61fcdb45f41974db8819d4de5d31cd3215d4c3bc5c0bca718bbeb81cf3ce666b0e068347c9ce89db3ed1e07bf
|
7
|
+
data.tar.gz: 3d563d73ab5fc270b27ef032a0b2ab8bf2e2fe5069088f541236e04c0150044bb039214dcc0418e81171de19fc43551ac5e7cbae5a788edcd34f7ec76a1edd0a
|
data/.circleci/config.yml
CHANGED
@@ -4,7 +4,7 @@ jobs:
|
|
4
4
|
build:
|
5
5
|
docker:
|
6
6
|
# specify the version you desire here
|
7
|
-
- image: circleci/ruby:2.
|
7
|
+
- image: circleci/ruby:2.7.1
|
8
8
|
|
9
9
|
working_directory: ~/repo
|
10
10
|
|
@@ -21,6 +21,7 @@ jobs:
|
|
21
21
|
- run:
|
22
22
|
name: install dependencies
|
23
23
|
command: |
|
24
|
+
gem install bundler:1.17.3
|
24
25
|
bundle install --jobs=4 --retry=3 --path vendor/bundle
|
25
26
|
|
26
27
|
- save_cache:
|
data/.rubocop.yml
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
AllCops:
|
2
|
+
NewCops: disable
|
1
3
|
Metrics/BlockLength:
|
2
4
|
Exclude:
|
3
5
|
- 'spec/**/*.rb'
|
4
6
|
Style/Documentation:
|
5
7
|
Enabled: false
|
8
|
+
Style/FrozenStringLiteralComment:
|
9
|
+
Enabled: false
|
6
10
|
# This is causing breaking changes:
|
7
11
|
Style/ExpandPathArguments:
|
8
12
|
Enabled: false
|
13
|
+
Gemspec/RequiredRubyVersion:
|
14
|
+
Enabled: false
|
data/Gemfile.lock
CHANGED
@@ -1,22 +1,27 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
seri (
|
4
|
+
seri (2.0.0)
|
5
5
|
oj (~> 3.7)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
ast (2.4.
|
10
|
+
ast (2.4.1)
|
11
|
+
coderay (1.1.3)
|
11
12
|
diff-lcs (1.3)
|
12
|
-
|
13
|
-
oj (3.10.
|
14
|
-
parallel (1.
|
15
|
-
parser (2.
|
16
|
-
ast (~> 2.4.
|
17
|
-
|
13
|
+
method_source (1.0.0)
|
14
|
+
oj (3.10.14)
|
15
|
+
parallel (1.19.2)
|
16
|
+
parser (2.7.2.0)
|
17
|
+
ast (~> 2.4.1)
|
18
|
+
pry (0.13.1)
|
19
|
+
coderay (~> 1.1)
|
20
|
+
method_source (~> 1.0)
|
18
21
|
rainbow (3.0.0)
|
19
22
|
rake (13.0.1)
|
23
|
+
regexp_parser (1.8.2)
|
24
|
+
rexml (3.2.4)
|
20
25
|
rspec (3.9.0)
|
21
26
|
rspec-core (~> 3.9.0)
|
22
27
|
rspec-expectations (~> 3.9.0)
|
@@ -30,25 +35,29 @@ GEM
|
|
30
35
|
diff-lcs (>= 1.2.0, < 2.0)
|
31
36
|
rspec-support (~> 3.9.0)
|
32
37
|
rspec-support (3.9.2)
|
33
|
-
rubocop (0.
|
34
|
-
jaro_winkler (~> 1.5.1)
|
38
|
+
rubocop (0.93.1)
|
35
39
|
parallel (~> 1.10)
|
36
|
-
parser (>= 2.
|
37
|
-
psych (>= 3.1.0)
|
40
|
+
parser (>= 2.7.1.5)
|
38
41
|
rainbow (>= 2.2.2, < 4.0)
|
42
|
+
regexp_parser (>= 1.8)
|
43
|
+
rexml
|
44
|
+
rubocop-ast (>= 0.6.0)
|
39
45
|
ruby-progressbar (~> 1.7)
|
40
|
-
unicode-display_width (>= 1.4.0, <
|
41
|
-
|
42
|
-
|
46
|
+
unicode-display_width (>= 1.4.0, < 2.0)
|
47
|
+
rubocop-ast (0.8.0)
|
48
|
+
parser (>= 2.7.1.5)
|
49
|
+
ruby-progressbar (1.10.1)
|
50
|
+
unicode-display_width (1.7.0)
|
43
51
|
|
44
52
|
PLATFORMS
|
45
53
|
ruby
|
46
54
|
|
47
55
|
DEPENDENCIES
|
48
56
|
bundler (~> 1.16)
|
57
|
+
pry (~> 0.13)
|
49
58
|
rake (~> 13.0)
|
50
59
|
rspec (~> 3.0)
|
51
|
-
rubocop (~> 0.
|
60
|
+
rubocop (~> 0.82)
|
52
61
|
seri!
|
53
62
|
|
54
63
|
BUNDLED WITH
|
data/README.md
CHANGED
@@ -33,13 +33,15 @@ Or install it yourself as:
|
|
33
33
|
A serializer can be used as such:
|
34
34
|
|
35
35
|
```ruby
|
36
|
+
require 'seri'
|
37
|
+
|
36
38
|
# example class:
|
37
39
|
class Car
|
38
40
|
attr_accessor :mileage
|
39
41
|
end
|
40
42
|
|
41
43
|
# example serializer:
|
42
|
-
class CarSerializer < Serializer
|
44
|
+
class CarSerializer < Seri::Serializer
|
43
45
|
attribute :mileage
|
44
46
|
attribute :brand
|
45
47
|
attribute :mileage_alias, from: :mileage
|
@@ -94,14 +96,14 @@ Result from `#to_json`:
|
|
94
96
|
}
|
95
97
|
```
|
96
98
|
|
97
|
-
In turn there's also a `GroupSerializer` available which can take a group of
|
99
|
+
In turn there's also a `Seri::GroupSerializer` available which can take a group of
|
98
100
|
cars and turn them into a serialized Array. If we extend the example from
|
99
101
|
earlier we can do:
|
100
102
|
|
101
103
|
```ruby
|
102
104
|
# example:
|
103
105
|
cars = [car, car]
|
104
|
-
group_serializer = GroupSerializer.new(cars, serializer: CarSerializer)
|
106
|
+
group_serializer = Seri::GroupSerializer.new(cars, serializer: CarSerializer)
|
105
107
|
|
106
108
|
group_serializer.to_json
|
107
109
|
```
|
@@ -148,11 +150,11 @@ class B
|
|
148
150
|
end
|
149
151
|
end
|
150
152
|
|
151
|
-
class ASerializer < Serializer
|
153
|
+
class ASerializer < Seri::Serializer
|
152
154
|
attribute :some_amazing_attribute
|
153
155
|
end
|
154
156
|
|
155
|
-
class BSerializer < Serializer
|
157
|
+
class BSerializer < Seri::Serializer
|
156
158
|
attribute :lots_of_a, from: :aaa, serializer: ASerializer
|
157
159
|
end
|
158
160
|
```
|
data/lib/seri.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'serializer'
|
data/lib/serializer.rb
CHANGED
@@ -3,34 +3,36 @@ require 'serializer/value'
|
|
3
3
|
require 'serializer/value_fetcher'
|
4
4
|
require 'serializer/group_serializer'
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
module Seri
|
7
|
+
class Serializer
|
8
|
+
Attribute = Struct.new(:key, :condition, :from, :serializer, :options)
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def self.attributes
|
11
|
+
@attributes ||= []
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
def self.attribute(key, condition: nil, from: nil, serializer: nil, **options)
|
15
|
+
attributes.push(Attribute.new(key, condition, from, serializer, options))
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
+
attr_accessor :object, :scope
|
18
19
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
def initialize(object, scope: {})
|
21
|
+
@object = object
|
22
|
+
@scope = scope
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
# Loops over all attributes and skips if a condition is defined and falsey
|
26
|
+
def to_h
|
27
|
+
self.class.attributes.each_with_object({}) do |attribute, obj|
|
28
|
+
next if attribute.condition && !public_send(attribute.condition)
|
28
29
|
|
29
|
-
|
30
|
+
obj[attribute.key] = ValueFetcher.fetch(attribute, object, self)
|
31
|
+
end
|
30
32
|
end
|
31
|
-
end
|
32
33
|
|
33
|
-
|
34
|
-
|
34
|
+
def to_json(*)
|
35
|
+
Oj.dump(to_h, mode: :json)
|
36
|
+
end
|
35
37
|
end
|
36
38
|
end
|
@@ -1,19 +1,21 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
module Seri
|
2
|
+
class GroupSerializer
|
3
|
+
def initialize(objects, serializer: nil, scope: {})
|
4
|
+
raise ArgumentError, 'serializer needs to be specified' if serializer.nil?
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
@objects = objects
|
7
|
+
@serializer = serializer
|
8
|
+
@scope = scope
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def to_json(*)
|
12
|
+
Oj.dump(to_h, mode: :json)
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
15
|
+
def to_h
|
16
|
+
@objects
|
17
|
+
.map { |object| @serializer.new(object, scope: @scope) }
|
18
|
+
.map(&:to_h)
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
data/lib/serializer/value.rb
CHANGED
@@ -1,58 +1,62 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
1
|
+
module Seri
|
2
|
+
class Serializer
|
3
|
+
class Value
|
4
|
+
def initialize(attribute, scope = nil)
|
5
|
+
@attribute = attribute
|
6
|
+
@scope = scope
|
7
|
+
end
|
8
|
+
|
9
|
+
def extraction_key
|
10
|
+
@attribute.from || @attribute.key
|
11
|
+
end
|
12
|
+
|
13
|
+
def precondition?
|
14
|
+
raise NotImplementedError, 'needs a method called precondition?'
|
15
|
+
end
|
16
|
+
|
17
|
+
def value
|
18
|
+
raise NotImplementedError, 'needs a method called value'
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class StaticValue < Value
|
23
|
+
def precondition?
|
24
|
+
@attribute.options.key?(:static_value)
|
25
|
+
end
|
26
|
+
|
27
|
+
def value
|
28
|
+
@attribute.options.fetch(:static_value)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
class SerializedValue < Value
|
33
|
+
def precondition?
|
34
|
+
@scope.respond_to?(extraction_key)
|
35
|
+
end
|
36
|
+
|
37
|
+
def value
|
38
|
+
@scope.public_send(extraction_key)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
class HashValue < Value
|
43
|
+
def precondition?
|
44
|
+
@scope.is_a?(Hash)
|
45
|
+
end
|
46
|
+
|
47
|
+
def value
|
48
|
+
@scope[extraction_key]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
class ObjectValue < Value
|
53
|
+
def precondition?
|
54
|
+
@scope.respond_to?(extraction_key)
|
55
|
+
end
|
56
|
+
|
57
|
+
def value
|
58
|
+
@scope.public_send(extraction_key)
|
59
|
+
end
|
60
|
+
end
|
57
61
|
end
|
58
62
|
end
|
@@ -1,59 +1,53 @@
|
|
1
|
-
|
2
|
-
class
|
1
|
+
module Seri
|
2
|
+
class Serializer
|
3
|
+
class ValueFetcher
|
4
|
+
class SerializerError < StandardError; end
|
3
5
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
ActiveRecord_Associations_CollectionProxy
|
8
|
-
].freeze
|
9
|
-
|
10
|
-
def self.fetch(attribute, object, serializer)
|
11
|
-
new(attribute, object, serializer).fetch
|
12
|
-
end
|
6
|
+
def self.fetch(attribute, object, serializer)
|
7
|
+
new(attribute, object, serializer).fetch
|
8
|
+
end
|
13
9
|
|
14
|
-
|
10
|
+
private_class_method :new
|
15
11
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
12
|
+
def initialize(attribute, object, serializer)
|
13
|
+
@attribute = attribute
|
14
|
+
@values = [
|
15
|
+
StaticValue.new(attribute),
|
16
|
+
SerializedValue.new(attribute, serializer),
|
17
|
+
HashValue.new(attribute, object),
|
18
|
+
ObjectValue.new(attribute, object)
|
19
|
+
]
|
20
|
+
end
|
25
21
|
|
26
|
-
|
27
|
-
|
22
|
+
def fetch
|
23
|
+
serializer = @attribute.serializer
|
28
24
|
|
29
|
-
|
25
|
+
return value unless serializer
|
30
26
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
|
38
|
-
# Fetches a value from an attribute by checking if there's a ..
|
39
|
-
# .. static value set, or a ..
|
40
|
-
# .. method defined in the serializer, or a ..
|
41
|
-
# .. method/attribute defined in the object or ..
|
42
|
-
# .. it raises an error
|
43
|
-
def value
|
44
|
-
@value ||= begin
|
45
|
-
extracted_value = @values.detect(&:precondition?)
|
46
|
-
|
47
|
-
if extracted_value.nil?
|
48
|
-
raise SerializerError,
|
49
|
-
"unknown attribute '#{@values[0].extraction_key}'"
|
27
|
+
if value.is_a?(Enumerable) && !value.is_a?(Hash)
|
28
|
+
value.map { |item| serializer.new(item).to_h }
|
29
|
+
else
|
30
|
+
serializer.new(value).to_h
|
31
|
+
end
|
50
32
|
end
|
51
33
|
|
52
|
-
|
34
|
+
# Fetches a value from an attribute by checking if there's a ..
|
35
|
+
# .. static value set, or a ..
|
36
|
+
# .. method defined in the serializer, or a ..
|
37
|
+
# .. method/attribute defined in the object or ..
|
38
|
+
# .. it raises an error
|
39
|
+
def value
|
40
|
+
@value ||= begin
|
41
|
+
extracted_value = @values.detect(&:precondition?)
|
42
|
+
|
43
|
+
if extracted_value.nil?
|
44
|
+
raise SerializerError,
|
45
|
+
"unknown attribute '#{@values[0].extraction_key}'"
|
46
|
+
end
|
47
|
+
|
48
|
+
extracted_value.value
|
49
|
+
end
|
50
|
+
end
|
53
51
|
end
|
54
52
|
end
|
55
|
-
|
56
|
-
def array?
|
57
|
-
ARRAYS.any? { |match| value.class.to_s.end_with?(match) }
|
58
|
-
end
|
59
53
|
end
|
data/lib/serializer/version.rb
CHANGED
data/seri.gemspec
CHANGED
@@ -4,7 +4,7 @@ require 'serializer/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = 'seri'
|
7
|
-
spec.version = Serializer::VERSION
|
7
|
+
spec.version = Seri::Serializer::VERSION
|
8
8
|
spec.authors = ['grdw']
|
9
9
|
spec.email = ['gerard@wetransfer.com']
|
10
10
|
|
@@ -27,7 +27,8 @@ Gem::Specification.new do |spec|
|
|
27
27
|
spec.add_dependency 'oj', '~> 3.7'
|
28
28
|
|
29
29
|
spec.add_development_dependency 'bundler', '~> 1.16'
|
30
|
+
spec.add_development_dependency 'pry', '~> 0.13'
|
30
31
|
spec.add_development_dependency 'rake', '~> 13.0'
|
31
32
|
spec.add_development_dependency 'rspec', '~> 3.0'
|
32
|
-
spec.add_development_dependency 'rubocop', '~> 0.
|
33
|
+
spec.add_development_dependency 'rubocop', '~> 0.82'
|
33
34
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: seri
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- grdw
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-10-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -38,6 +38,20 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.16'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: pry
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0.13'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0.13'
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: rake
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -72,14 +86,14 @@ dependencies:
|
|
72
86
|
requirements:
|
73
87
|
- - "~>"
|
74
88
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
89
|
+
version: '0.82'
|
76
90
|
type: :development
|
77
91
|
prerelease: false
|
78
92
|
version_requirements: !ruby/object:Gem::Requirement
|
79
93
|
requirements:
|
80
94
|
- - "~>"
|
81
95
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
96
|
+
version: '0.82'
|
83
97
|
description: A basic serializer
|
84
98
|
email:
|
85
99
|
- gerard@wetransfer.com
|
@@ -98,6 +112,7 @@ files:
|
|
98
112
|
- LICENSE.txt
|
99
113
|
- README.md
|
100
114
|
- Rakefile
|
115
|
+
- lib/seri.rb
|
101
116
|
- lib/serializer.rb
|
102
117
|
- lib/serializer/group_serializer.rb
|
103
118
|
- lib/serializer/value.rb
|
@@ -108,7 +123,7 @@ homepage: https://github.com/grdw/seri
|
|
108
123
|
licenses:
|
109
124
|
- MIT
|
110
125
|
metadata: {}
|
111
|
-
post_install_message:
|
126
|
+
post_install_message:
|
112
127
|
rdoc_options: []
|
113
128
|
require_paths:
|
114
129
|
- lib
|
@@ -124,7 +139,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
139
|
version: '0'
|
125
140
|
requirements: []
|
126
141
|
rubygems_version: 3.1.2
|
127
|
-
signing_key:
|
142
|
+
signing_key:
|
128
143
|
specification_version: 4
|
129
144
|
summary: A basic serializer
|
130
145
|
test_files: []
|