panko_serializer 0.5.10 → 0.6.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 +4 -4
- data/.travis.yml +3 -3
- data/Gemfile +7 -1
- data/Rakefile +1 -0
- data/benchmarks/bm_object_writer.rb +64 -0
- data/benchmarks/bm_to_object.rb +93 -0
- data/docs/attributes.md +1 -1
- data/ext/panko_serializer/attributes_writer/active_record.c +6 -10
- data/ext/panko_serializer/common.h +3 -0
- data/ext/panko_serializer/serialization_descriptor/attribute.c +1 -1
- data/lib/panko/array_serializer.rb +16 -12
- data/lib/panko/attribute.rb +1 -0
- data/lib/panko/object_writer.rb +56 -0
- data/lib/panko/serializer.rb +9 -4
- data/lib/panko/version.rb +1 -1
- data/lib/panko_serializer.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c49d12e1be46851f1fdb226b37d1c09673a586d053edb8b084f6345bf74b1637
|
4
|
+
data.tar.gz: e9895a4a74b16c83904ee77961c70259cb84a1d739b46d7203f7bdf2a06d3392
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 063cf79e3a6580a71a8b4e6f098cdb1514e7997cd22130a5189c4db7030b39ebada570f721cbfc36e4024141b30da7a40ed6c6d364c39465101f25e5a91baf61
|
7
|
+
data.tar.gz: 73987f5d252b7c2a4f0d901c941901f748536b7e16e017aede986899d1a1471246f7541b6c0aa35a1958b3c18e41bfdcb1795dfa7752296729991d5b0d1455ea
|
data/.travis.yml
CHANGED
@@ -2,9 +2,9 @@ sudo: false
|
|
2
2
|
cache: bundler
|
3
3
|
language: ruby
|
4
4
|
rvm:
|
5
|
-
- 2.3.8
|
6
5
|
- 2.5.5
|
7
6
|
- 2.6.3
|
7
|
+
- 2.7.0-preview1
|
8
8
|
|
9
9
|
env:
|
10
10
|
global:
|
@@ -26,8 +26,8 @@ env:
|
|
26
26
|
matrix:
|
27
27
|
- "RAILS_VERSION=4.2.0"
|
28
28
|
- "RAILS_VERSION=5.2.0"
|
29
|
-
- "RAILS_VERSION=6.0.0.
|
29
|
+
- "RAILS_VERSION=6.0.0.rc1"
|
30
30
|
|
31
31
|
matrix:
|
32
32
|
allow_failures:
|
33
|
-
- "RAILS_VERSION=6.0.0.
|
33
|
+
- "RAILS_VERSION=6.0.0.rc1"
|
data/Gemfile
CHANGED
@@ -10,8 +10,13 @@ gem "activesupport", rails_version
|
|
10
10
|
gem "activemodel", rails_version
|
11
11
|
gem "activerecord", rails_version, group: :test
|
12
12
|
|
13
|
+
|
13
14
|
group :benchmarks do
|
14
|
-
|
15
|
+
if raw_rails_version.include? "4.2"
|
16
|
+
gem 'sqlite3', '~> 1.3.6'
|
17
|
+
else
|
18
|
+
gem "sqlite3", "~> 1.4"
|
19
|
+
end
|
15
20
|
|
16
21
|
if raw_rails_version.include? "4.2"
|
17
22
|
gem "pg", "~> 0.15"
|
@@ -37,4 +42,5 @@ group :development do
|
|
37
42
|
gem "rake"
|
38
43
|
gem "rspec", "~> 3.0"
|
39
44
|
gem "rake-compiler"
|
45
|
+
gem "rubocop"
|
40
46
|
end
|
data/Rakefile
CHANGED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "./benchmarking_support"
|
3
|
+
require_relative "./app"
|
4
|
+
|
5
|
+
Benchmark.run("ObjectWriter_OneProperty_PushValue") do
|
6
|
+
writer = Panko::ObjectWriter.new
|
7
|
+
|
8
|
+
writer.push_object
|
9
|
+
writer.push_value "value1", "key1"
|
10
|
+
writer.pop
|
11
|
+
|
12
|
+
writer.output
|
13
|
+
end
|
14
|
+
|
15
|
+
Benchmark.run("ObjectWriter_TwoProperty_PushValue") do
|
16
|
+
writer = Panko::ObjectWriter.new
|
17
|
+
|
18
|
+
writer.push_object
|
19
|
+
writer.push_value "value1", "key1"
|
20
|
+
writer.push_value "value2", "key2"
|
21
|
+
writer.pop
|
22
|
+
|
23
|
+
writer.output
|
24
|
+
end
|
25
|
+
|
26
|
+
Benchmark.run("ObjectWriter_OneProperty_PushValuePushKey") do
|
27
|
+
writer = Panko::ObjectWriter.new
|
28
|
+
|
29
|
+
writer.push_object
|
30
|
+
writer.push_key "key1"
|
31
|
+
writer.push_value "value1"
|
32
|
+
writer.pop
|
33
|
+
|
34
|
+
writer.output
|
35
|
+
end
|
36
|
+
|
37
|
+
Benchmark.run("ObjectWriter_TwoProperty_PushValuePushKey") do
|
38
|
+
writer = Panko::ObjectWriter.new
|
39
|
+
|
40
|
+
writer.push_object
|
41
|
+
writer.push_key "key1"
|
42
|
+
writer.push_value "value1"
|
43
|
+
|
44
|
+
writer.push_key "key2"
|
45
|
+
writer.push_value "value2"
|
46
|
+
writer.pop
|
47
|
+
|
48
|
+
writer.output
|
49
|
+
end
|
50
|
+
|
51
|
+
Benchmark.run("ObjectWriter_NestedObject") do
|
52
|
+
writer = Panko::ObjectWriter.new
|
53
|
+
|
54
|
+
writer.push_object
|
55
|
+
writer.push_value "value1", "key1"
|
56
|
+
|
57
|
+
writer.push_object "key2"
|
58
|
+
writer.push_value "value2", "key2"
|
59
|
+
writer.pop
|
60
|
+
|
61
|
+
writer.pop
|
62
|
+
|
63
|
+
writer.output
|
64
|
+
end
|
@@ -0,0 +1,93 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require_relative "./benchmarking_support"
|
3
|
+
require_relative "./app"
|
4
|
+
require_relative "./setup"
|
5
|
+
|
6
|
+
class PostWithAliasModel < ActiveRecord::Base
|
7
|
+
self.table_name = 'posts'
|
8
|
+
|
9
|
+
alias_attribute :new_id, :id
|
10
|
+
alias_attribute :new_body, :body
|
11
|
+
alias_attribute :new_title, :title
|
12
|
+
alias_attribute :new_author_id, :author_id
|
13
|
+
alias_attribute :new_created_at, :created_at
|
14
|
+
end
|
15
|
+
|
16
|
+
class PostWithAliasFastSerializer < Panko::Serializer
|
17
|
+
attributes :new_id, :new_body, :new_title, :new_author_id, :new_created_at
|
18
|
+
end
|
19
|
+
|
20
|
+
def benchmark_aliased(prefix, serializer, options = {})
|
21
|
+
posts = PostWithAliasModel.all.to_a
|
22
|
+
posts_50 = posts.first(50).to_a
|
23
|
+
data = { all: posts, small: posts_50 }
|
24
|
+
|
25
|
+
merged_options = options.merge(each_serializer: serializer)
|
26
|
+
|
27
|
+
Benchmark.run("Panko_#{prefix}_PostWithAliasModels_#{posts.count}") do
|
28
|
+
Panko::ArraySerializer.new(posts, merged_options).to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
posts = PostWithAliasModel.all.to_a
|
32
|
+
posts_50 = posts.first(50).to_a
|
33
|
+
data = { all: posts, small: posts_50 }
|
34
|
+
|
35
|
+
Benchmark.run("Panko_#{prefix}_Posts_50") do
|
36
|
+
Panko::ArraySerializer.new(posts_50, merged_options).to_json
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class AuthorFastSerializer < Panko::Serializer
|
41
|
+
attributes :id, :name
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
class PostFastSerializer < Panko::Serializer
|
46
|
+
attributes :id, :body, :title, :author_id, :created_at
|
47
|
+
end
|
48
|
+
|
49
|
+
class PostFastWithMethodCallSerializer < Panko::Serializer
|
50
|
+
attributes :id, :body, :title, :author_id, :created_at, :method_call
|
51
|
+
|
52
|
+
def method_call
|
53
|
+
object.id
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class PostWithHasOneFastSerializer < Panko::Serializer
|
58
|
+
attributes :id, :body, :title, :author_id, :created_at
|
59
|
+
|
60
|
+
has_one :author, serializer: AuthorFastSerializer
|
61
|
+
end
|
62
|
+
|
63
|
+
class AuthorWithHasManyFastSerializer < Panko::Serializer
|
64
|
+
attributes :id, :name
|
65
|
+
|
66
|
+
has_many :posts, serializer: PostFastSerializer
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
def benchmark(prefix, serializer, options = {})
|
71
|
+
data = Benchmark.data
|
72
|
+
posts = data[:all]
|
73
|
+
posts_50 = data[:small]
|
74
|
+
|
75
|
+
merged_options = options.merge(each_serializer: serializer)
|
76
|
+
|
77
|
+
Benchmark.run("Panko_#{prefix}_Posts_#{posts.count}") do
|
78
|
+
Panko::ArraySerializer.new(posts, merged_options).to_a
|
79
|
+
end
|
80
|
+
|
81
|
+
data = Benchmark.data
|
82
|
+
posts = data[:all]
|
83
|
+
posts_50 = data[:small]
|
84
|
+
|
85
|
+
Benchmark.run("Panko_#{prefix}_Posts_50") do
|
86
|
+
Panko::ArraySerializer.new(posts_50, merged_options).to_a
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
|
92
|
+
benchmark "Simple", PostFastSerializer
|
93
|
+
benchmark "HasOne", PostWithHasOneFastSerializer
|
data/docs/attributes.md
CHANGED
@@ -86,7 +86,7 @@ Sometimes you find yourself have the same filtering logic in actions in order to
|
|
86
86
|
class UserSerializer < Panko::Serializer
|
87
87
|
attributes :id, :name, :email
|
88
88
|
|
89
|
-
def self.filters_for(context)
|
89
|
+
def self.filters_for(context, scope)
|
90
90
|
{
|
91
91
|
only: [:name]
|
92
92
|
}
|
@@ -29,7 +29,6 @@ struct attributes {
|
|
29
29
|
VALUE values;
|
30
30
|
|
31
31
|
// heuristicts
|
32
|
-
bool shouldReadFromHash;
|
33
32
|
bool tryToReadFromAdditionalTypes;
|
34
33
|
};
|
35
34
|
|
@@ -40,21 +39,18 @@ struct attributes init_context(VALUE obj) {
|
|
40
39
|
attributes_ctx.types = Qnil;
|
41
40
|
attributes_ctx.additional_types = Qnil;
|
42
41
|
|
43
|
-
attributes_ctx.shouldReadFromHash = false;
|
44
42
|
attributes_ctx.tryToReadFromAdditionalTypes = false;
|
45
43
|
|
46
44
|
volatile VALUE lazy_attributes_hash = panko_read_lazy_attributes_hash(obj);
|
47
45
|
|
48
46
|
if (RB_TYPE_P(lazy_attributes_hash, T_HASH)) {
|
49
47
|
attributes_ctx.attributes_hash = lazy_attributes_hash;
|
50
|
-
attributes_ctx.shouldReadFromHash = true;
|
51
48
|
} else {
|
52
49
|
volatile VALUE delegate_hash =
|
53
50
|
rb_ivar_get(lazy_attributes_hash, delegate_hash_id);
|
54
51
|
|
55
52
|
if (PANKO_EMPTY_HASH(delegate_hash) == false) {
|
56
53
|
attributes_ctx.attributes_hash = delegate_hash;
|
57
|
-
attributes_ctx.shouldReadFromHash = true;
|
58
54
|
}
|
59
55
|
|
60
56
|
attributes_ctx.types = rb_ivar_get(lazy_attributes_hash, types_id);
|
@@ -73,11 +69,13 @@ VALUE read_attribute(struct attributes attributes_ctx, Attribute attribute) {
|
|
73
69
|
volatile VALUE member, value;
|
74
70
|
|
75
71
|
member = attribute->name_str;
|
76
|
-
value =
|
72
|
+
value = Qnil;
|
77
73
|
|
78
|
-
|
74
|
+
|
75
|
+
if (!NIL_P(attributes_ctx.attributes_hash)) {
|
79
76
|
volatile VALUE attribute_metadata =
|
80
77
|
rb_hash_aref(attributes_ctx.attributes_hash, member);
|
78
|
+
|
81
79
|
if (attribute_metadata != Qnil) {
|
82
80
|
value = rb_ivar_get(attribute_metadata, value_before_type_cast_id);
|
83
81
|
|
@@ -87,13 +85,11 @@ VALUE read_attribute(struct attributes attributes_ctx, Attribute attribute) {
|
|
87
85
|
}
|
88
86
|
}
|
89
87
|
|
90
|
-
if (value
|
88
|
+
if (NIL_P(value) && !NIL_P(attributes_ctx.values)) {
|
91
89
|
value = rb_hash_aref(attributes_ctx.values, member);
|
92
|
-
if (NIL_P(value)) {
|
93
|
-
value = Qundef;
|
94
|
-
}
|
95
90
|
}
|
96
91
|
|
92
|
+
|
97
93
|
if (NIL_P(attribute->type) && !NIL_P(value)) {
|
98
94
|
if (attributes_ctx.tryToReadFromAdditionalTypes == true) {
|
99
95
|
attribute->type = rb_hash_aref(attributes_ctx.additional_types, member);
|
@@ -48,7 +48,7 @@ Attribute attribute_read(VALUE attribute) {
|
|
48
48
|
}
|
49
49
|
|
50
50
|
void attribute_try_invalidate(Attribute attribute, VALUE new_record_class) {
|
51
|
-
if (
|
51
|
+
if (attribute->record_class != new_record_class) {
|
52
52
|
attribute->type = Qnil;
|
53
53
|
attribute->record_class = new_record_class;
|
54
54
|
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
module Panko
|
4
4
|
class ArraySerializer
|
5
|
-
attr_accessor :
|
5
|
+
attr_accessor :subjects
|
6
6
|
|
7
|
-
def initialize(
|
8
|
-
@
|
7
|
+
def initialize(subjects, options = {})
|
8
|
+
@subjects = subjects
|
9
9
|
@each_serializer = options[:each_serializer]
|
10
10
|
|
11
11
|
if @each_serializer.nil?
|
@@ -27,22 +27,26 @@ Please pass valid each_serializer to ArraySerializer, for example:
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def to_json
|
30
|
-
serialize_to_json @
|
30
|
+
serialize_to_json @subjects
|
31
31
|
end
|
32
32
|
|
33
|
-
def serialize(
|
34
|
-
|
33
|
+
def serialize(subjects)
|
34
|
+
serialize_with_writer(subjects, Panko::ObjectWriter.new).output
|
35
35
|
end
|
36
36
|
|
37
37
|
def to_a
|
38
|
-
|
38
|
+
serialize_with_writer(@subjects, Panko::ObjectWriter.new).output
|
39
39
|
end
|
40
40
|
|
41
|
-
def serialize_to_json(
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
def serialize_to_json(subjects)
|
42
|
+
serialize_with_writer(subjects, Oj::StringWriter.new(mode: :rails)).to_s
|
43
|
+
end
|
44
|
+
|
45
|
+
private
|
46
|
+
|
47
|
+
def serialize_with_writer(subjects, writer)
|
48
|
+
Panko.serialize_objects(subjects.to_a, writer, @descriptor)
|
49
|
+
writer
|
46
50
|
end
|
47
51
|
end
|
48
52
|
end
|
data/lib/panko/attribute.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Panko::ObjectWriter
|
4
|
+
def initialize
|
5
|
+
@values = []
|
6
|
+
@keys = []
|
7
|
+
|
8
|
+
@next_key = nil
|
9
|
+
@output = nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def push_object(key = nil)
|
13
|
+
@values << {}
|
14
|
+
@keys << key
|
15
|
+
end
|
16
|
+
|
17
|
+
def push_array(key = nil)
|
18
|
+
@values << []
|
19
|
+
@keys << key
|
20
|
+
end
|
21
|
+
|
22
|
+
def push_key(key)
|
23
|
+
@next_key = key
|
24
|
+
end
|
25
|
+
|
26
|
+
def push_value(value, key = nil)
|
27
|
+
unless @next_key.nil?
|
28
|
+
raise "push_value is called with key after push_key is called" unless key.nil?
|
29
|
+
key = @next_key
|
30
|
+
@next_key = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
@values.last[key] = value.as_json
|
34
|
+
end
|
35
|
+
|
36
|
+
def pop
|
37
|
+
result = @values.pop
|
38
|
+
|
39
|
+
if @values.empty?
|
40
|
+
@output = result
|
41
|
+
return
|
42
|
+
end
|
43
|
+
|
44
|
+
scope_key = @keys.pop
|
45
|
+
if scope_key.nil?
|
46
|
+
@values.last << result
|
47
|
+
else
|
48
|
+
@values.last[scope_key] = result
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def output
|
53
|
+
raise "Output is called before poping all" unless @values.empty?
|
54
|
+
@output
|
55
|
+
end
|
56
|
+
end
|
data/lib/panko/serializer.rb
CHANGED
@@ -64,6 +64,7 @@ module Panko
|
|
64
64
|
|
65
65
|
def method_added(method)
|
66
66
|
return if @_descriptor.nil?
|
67
|
+
|
67
68
|
deleted_attr = @_descriptor.attributes.delete(method)
|
68
69
|
@_descriptor.method_fields << Attribute.create(method) unless deleted_attr.nil?
|
69
70
|
end
|
@@ -115,14 +116,18 @@ module Panko
|
|
115
116
|
attr_reader :object
|
116
117
|
|
117
118
|
def serialize(object)
|
118
|
-
|
119
|
+
serialize_with_writer(object, Panko::ObjectWriter.new).output
|
119
120
|
end
|
120
121
|
|
121
122
|
def serialize_to_json(object)
|
122
|
-
|
123
|
+
serialize_with_writer(object, Oj::StringWriter.new(mode: :rails)).to_s
|
124
|
+
end
|
125
|
+
|
126
|
+
private
|
127
|
+
|
128
|
+
def serialize_with_writer(object, writer)
|
123
129
|
Panko.serialize_object(object, writer, @descriptor)
|
124
|
-
|
125
|
-
writer.to_s
|
130
|
+
writer
|
126
131
|
end
|
127
132
|
end
|
128
133
|
end
|
data/lib/panko/version.rb
CHANGED
data/lib/panko_serializer.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: panko_serializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yosi Attias
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-06-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|
@@ -46,11 +46,13 @@ files:
|
|
46
46
|
- benchmarks/app.rb
|
47
47
|
- benchmarks/benchmarking_support.rb
|
48
48
|
- benchmarks/bm_ams_0_10.rb
|
49
|
+
- benchmarks/bm_object_writer.rb
|
49
50
|
- benchmarks/bm_panko_json.rb
|
50
51
|
- benchmarks/bm_panko_object.rb
|
51
52
|
- benchmarks/bm_plain_object.rb
|
52
53
|
- benchmarks/bm_serialization_descriptor.rb
|
53
54
|
- benchmarks/bm_serializer_resolver.rb
|
55
|
+
- benchmarks/bm_to_object.rb
|
54
56
|
- benchmarks/profile.rb
|
55
57
|
- benchmarks/sanity.rb
|
56
58
|
- benchmarks/setup.rb
|
@@ -90,6 +92,7 @@ files:
|
|
90
92
|
- lib/panko/array_serializer.rb
|
91
93
|
- lib/panko/association.rb
|
92
94
|
- lib/panko/attribute.rb
|
95
|
+
- lib/panko/object_writer.rb
|
93
96
|
- lib/panko/response.rb
|
94
97
|
- lib/panko/serialization_descriptor.rb
|
95
98
|
- lib/panko/serializer.rb
|