panko_serializer 0.2.2 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -3
- data/_config.yml +1 -0
- data/benchmarks/bm_serialization_descriptor.rb +0 -8
- data/benchmarks/type_casts/bm_panko.rb +3 -3
- data/benchmarks/type_casts/support.rb +1 -0
- data/ext/panko_serializer/association.c +81 -0
- data/ext/panko_serializer/association.h +20 -0
- data/ext/panko_serializer/attribute.c +73 -0
- data/ext/panko_serializer/attribute.h +23 -0
- data/ext/panko_serializer/attributes_iterator.c +89 -52
- data/ext/panko_serializer/attributes_iterator.h +3 -6
- data/ext/panko_serializer/panko_serializer.c +19 -34
- data/ext/panko_serializer/panko_serializer.h +3 -1
- data/ext/panko_serializer/serialization_descriptor.c +62 -58
- data/ext/panko_serializer/serialization_descriptor.h +5 -7
- data/ext/panko_serializer/type_cast.c +38 -8
- data/ext/panko_serializer/type_cast.h +5 -0
- data/lib/panko/attribute.rb +30 -0
- data/lib/panko/response.rb +8 -0
- data/lib/panko/serialization_descriptor.rb +38 -28
- data/lib/panko/serializer.rb +21 -9
- data/lib/panko/version.rb +1 -1
- data/lib/panko_serializer.rb +2 -0
- metadata +9 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9e1120b6231ae836d11ca59c17443518f5ccb80
|
4
|
+
data.tar.gz: 2b38dd527027204628714825d38d5f8c83b0d4a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9642ae4e418b15a0051d2bb08b352bb035afabfb3f0eb115ded715fb6edc5db91a3a17a4dbd76793607b3c6db020eb2ea08625bf11e5b85311835cb8eebb428d
|
7
|
+
data.tar.gz: 9b0225b6e43c743425b8cbb0e105541ec646aa50a7fcaf634631ddc427ecc808cf1f96ac3a3ebe96bccdff292708f9a473f16be8481e4959917b79fc9b95d985
|
data/README.md
CHANGED
@@ -32,8 +32,6 @@ Then, install it on the command line:
|
|
32
32
|
> bundle install
|
33
33
|
```
|
34
34
|
|
35
|
-
> Since the Gem name and namespace differ, you need to require "panko" explicitly. This will be fixed before official release.
|
36
|
-
|
37
35
|
|
38
36
|
|
39
37
|
## Usage
|
@@ -66,7 +64,7 @@ class UsersController < ApplicationController
|
|
66
64
|
end
|
67
65
|
```
|
68
66
|
|
69
|
-
And voila, we have endpoint which
|
67
|
+
And voila, we have endpoint which serialize users using Panko!
|
70
68
|
|
71
69
|
|
72
70
|
## Features
|
data/_config.yml
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
theme: jekyll-theme-cayman
|
@@ -1,16 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require_relative "./benchmarking_support"
|
3
3
|
require "rails"
|
4
|
-
require "active_model"
|
5
4
|
require "active_support"
|
6
|
-
require "active_support/json"
|
7
|
-
require "action_controller"
|
8
|
-
require "action_controller/railtie"
|
9
5
|
|
10
|
-
|
11
|
-
require "memory_profiler"
|
12
|
-
require "ruby-prof"
|
13
|
-
require "ruby-prof-flamegraph"
|
14
6
|
require "panko_serializer"
|
15
7
|
|
16
8
|
def generate_attributes(count)
|
@@ -44,11 +44,11 @@ def db_panko_time
|
|
44
44
|
Panko::_type_cast(converter, from)
|
45
45
|
end
|
46
46
|
end
|
47
|
-
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Json, '{"a":1}', {a:1}
|
48
|
-
db_panko_time
|
49
|
-
utc_panko_time
|
50
47
|
|
51
48
|
panko_type_convert ActiveRecord::Type::String, 1, "1"
|
49
|
+
panko_type_convert ActiveRecord::ConnectionAdapters::PostgreSQL::OID::Json, '{"a":1}', {a:1}
|
50
|
+
exit
|
51
|
+
|
52
52
|
panko_type_convert ActiveRecord::Type::Text, 1, "1"
|
53
53
|
panko_type_convert ActiveRecord::Type::Integer, "1", 1
|
54
54
|
panko_type_convert ActiveRecord::Type::Float, "1.23", 1.23
|
@@ -0,0 +1,81 @@
|
|
1
|
+
#include "association.h"
|
2
|
+
|
3
|
+
VALUE cAssociation;
|
4
|
+
|
5
|
+
static void association_free(void* ptr) {
|
6
|
+
if (!ptr) {
|
7
|
+
return;
|
8
|
+
}
|
9
|
+
|
10
|
+
Association association = (Association)ptr;
|
11
|
+
association->name_str = Qnil;
|
12
|
+
association->name_id = 0;
|
13
|
+
association->name_sym = Qnil;
|
14
|
+
association->rb_descriptor = Qnil;
|
15
|
+
|
16
|
+
if (!association->descriptor || association->descriptor != NULL) {
|
17
|
+
association->descriptor = NULL;
|
18
|
+
}
|
19
|
+
|
20
|
+
xfree(association);
|
21
|
+
}
|
22
|
+
|
23
|
+
void association_mark(Association data) {
|
24
|
+
rb_gc_mark(data->name_str);
|
25
|
+
rb_gc_mark(data->name_sym);
|
26
|
+
rb_gc_mark(data->rb_descriptor);
|
27
|
+
|
28
|
+
if (data->descriptor != NULL) {
|
29
|
+
sd_mark(data->descriptor);
|
30
|
+
}
|
31
|
+
}
|
32
|
+
|
33
|
+
static VALUE association_new(int argc, VALUE* argv, VALUE self) {
|
34
|
+
Association association = ALLOC(struct _Association);
|
35
|
+
|
36
|
+
Check_Type(argv[0], T_SYMBOL);
|
37
|
+
Check_Type(argv[1], T_STRING);
|
38
|
+
|
39
|
+
association->name_sym = argv[0];
|
40
|
+
association->name_str = argv[1];
|
41
|
+
association->rb_descriptor = argv[2];
|
42
|
+
|
43
|
+
association->name_id = rb_intern_str(association->name_str);
|
44
|
+
association->descriptor = sd_read(association->rb_descriptor);
|
45
|
+
|
46
|
+
return Data_Wrap_Struct(cAssociation, association_mark, association_free,
|
47
|
+
association);
|
48
|
+
}
|
49
|
+
|
50
|
+
Association association_read(VALUE association) {
|
51
|
+
return (Association)DATA_PTR(association);
|
52
|
+
}
|
53
|
+
|
54
|
+
VALUE association_name_sym_ref(VALUE self) {
|
55
|
+
Association association = (Association)DATA_PTR(self);
|
56
|
+
return association->name_sym;
|
57
|
+
}
|
58
|
+
|
59
|
+
VALUE association_descriptor_ref(VALUE self) {
|
60
|
+
Association association = (Association)DATA_PTR(self);
|
61
|
+
return association->rb_descriptor;
|
62
|
+
}
|
63
|
+
|
64
|
+
VALUE association_decriptor_aset(VALUE self, VALUE descriptor) {
|
65
|
+
Association association = (Association)DATA_PTR(self);
|
66
|
+
|
67
|
+
association->rb_descriptor = descriptor;
|
68
|
+
association->descriptor = sd_read(descriptor);
|
69
|
+
|
70
|
+
return association->rb_descriptor;
|
71
|
+
}
|
72
|
+
|
73
|
+
void panko_init_association(VALUE mPanko) {
|
74
|
+
cAssociation = rb_define_class_under(mPanko, "Association", rb_cObject);
|
75
|
+
|
76
|
+
rb_define_module_function(cAssociation, "new", association_new, -1);
|
77
|
+
|
78
|
+
rb_define_method(cAssociation, "name_sym", association_name_sym_ref, 0);
|
79
|
+
rb_define_method(cAssociation, "descriptor", association_descriptor_ref, 0);
|
80
|
+
rb_define_method(cAssociation, "descriptor=", association_decriptor_aset, 1);
|
81
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#ifndef __ASSOCIATION_H__
|
4
|
+
#define __ASSOCIATION_H__
|
5
|
+
|
6
|
+
#include "serialization_descriptor.h"
|
7
|
+
|
8
|
+
typedef struct _Association {
|
9
|
+
ID name_id;
|
10
|
+
VALUE name_sym;
|
11
|
+
VALUE name_str;
|
12
|
+
|
13
|
+
VALUE rb_descriptor;
|
14
|
+
SerializationDescriptor descriptor;
|
15
|
+
} * Association;
|
16
|
+
|
17
|
+
Association association_read(VALUE association);
|
18
|
+
void panko_init_association(VALUE mPanko);
|
19
|
+
|
20
|
+
#endif
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#include "attribute.h"
|
2
|
+
|
3
|
+
VALUE cAttribute;
|
4
|
+
|
5
|
+
static void attribute_free(void* ptr) {
|
6
|
+
if (!ptr) {
|
7
|
+
return;
|
8
|
+
}
|
9
|
+
|
10
|
+
Attribute attribute = (Attribute)ptr;
|
11
|
+
attribute->name_str = Qnil;
|
12
|
+
attribute->name_id = 0;
|
13
|
+
attribute->alias_name = Qnil;
|
14
|
+
attribute->type = Qnil;
|
15
|
+
attribute->record_class = Qnil;
|
16
|
+
|
17
|
+
xfree(attribute);
|
18
|
+
}
|
19
|
+
|
20
|
+
void attribute_mark(Attribute data) {
|
21
|
+
rb_gc_mark(data->name_str);
|
22
|
+
rb_gc_mark(data->alias_name);
|
23
|
+
rb_gc_mark(data->type);
|
24
|
+
rb_gc_mark(data->record_class);
|
25
|
+
}
|
26
|
+
|
27
|
+
static VALUE attribute_new(int argc, VALUE* argv, VALUE self) {
|
28
|
+
Attribute attribute = ALLOC(struct _Attribute);
|
29
|
+
|
30
|
+
Check_Type(argv[0], T_STRING);
|
31
|
+
if (argv[1] != Qnil) {
|
32
|
+
Check_Type(argv[1], T_STRING);
|
33
|
+
}
|
34
|
+
|
35
|
+
attribute->name_str = argv[0];
|
36
|
+
attribute->name_id = rb_intern_str(attribute->name_str);
|
37
|
+
attribute->alias_name = argv[1];
|
38
|
+
attribute->type = Qnil;
|
39
|
+
attribute->record_class = Qnil;
|
40
|
+
|
41
|
+
return Data_Wrap_Struct(cAttribute, attribute_mark, attribute_free,
|
42
|
+
attribute);
|
43
|
+
}
|
44
|
+
|
45
|
+
Attribute attribute_read(VALUE attribute) {
|
46
|
+
return (Attribute)DATA_PTR(attribute);
|
47
|
+
}
|
48
|
+
|
49
|
+
void attribute_try_invalidate(Attribute attribute, VALUE new_record_class) {
|
50
|
+
if (rb_equal(attribute->record_class, new_record_class) == Qfalse) {
|
51
|
+
attribute->type = Qnil;
|
52
|
+
attribute->record_class = new_record_class;
|
53
|
+
}
|
54
|
+
}
|
55
|
+
|
56
|
+
VALUE attribute_name_ref(VALUE self) {
|
57
|
+
Attribute attribute = (Attribute)DATA_PTR(self);
|
58
|
+
return attribute->name_str;
|
59
|
+
}
|
60
|
+
|
61
|
+
VALUE attribute_alias_name_ref(VALUE self) {
|
62
|
+
Attribute attribute = (Attribute)DATA_PTR(self);
|
63
|
+
return attribute->alias_name;
|
64
|
+
}
|
65
|
+
|
66
|
+
void panko_init_attribute(VALUE mPanko) {
|
67
|
+
cAttribute = rb_define_class_under(mPanko, "Attribute", rb_cObject);
|
68
|
+
|
69
|
+
rb_define_module_function(cAttribute, "new", attribute_new, -1);
|
70
|
+
|
71
|
+
rb_define_method(cAttribute, "name", attribute_name_ref, 0);
|
72
|
+
rb_define_method(cAttribute, "alias_name", attribute_alias_name_ref, 0);
|
73
|
+
}
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#ifndef __ATTRIBUTE_H__
|
4
|
+
#define __ATTRIBUTE_H__
|
5
|
+
|
6
|
+
typedef struct _Attribute {
|
7
|
+
VALUE name_str;
|
8
|
+
ID name_id;
|
9
|
+
VALUE alias_name;
|
10
|
+
|
11
|
+
/*
|
12
|
+
* We will cache the activerecord type
|
13
|
+
* by the record_class
|
14
|
+
*/
|
15
|
+
VALUE type;
|
16
|
+
VALUE record_class;
|
17
|
+
} * Attribute;
|
18
|
+
|
19
|
+
Attribute attribute_read(VALUE attribute);
|
20
|
+
void attribute_try_invalidate(Attribute attribute, VALUE record);
|
21
|
+
void panko_init_attribute(VALUE mPanko);
|
22
|
+
|
23
|
+
#endif
|
@@ -49,79 +49,116 @@ void read_attribute_from_hash(VALUE attributes_hash,
|
|
49
49
|
volatile VALUE attribute_metadata = rb_hash_aref(attributes_hash, member);
|
50
50
|
if (attribute_metadata != Qnil) {
|
51
51
|
*value = rb_ivar_get(attribute_metadata, value_before_type_cast_id);
|
52
|
-
|
52
|
+
|
53
|
+
if (*type == Qnil) {
|
54
|
+
*type = rb_ivar_get(attribute_metadata, type_id);
|
55
|
+
}
|
53
56
|
}
|
54
57
|
}
|
55
58
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
struct attributes {
|
60
|
+
VALUE attributes_hash;
|
61
|
+
|
62
|
+
VALUE types;
|
63
|
+
VALUE additional_types;
|
64
|
+
VALUE values;
|
65
|
+
|
66
|
+
// heuristicts
|
67
|
+
bool shouldReadFromHash;
|
68
|
+
bool tryToReadFromAdditionalTypes;
|
69
|
+
};
|
70
|
+
|
71
|
+
struct attributes init_context(VALUE obj) {
|
72
|
+
struct attributes attributes_ctx;
|
73
|
+
attributes_ctx.attributes_hash = Qnil;
|
74
|
+
attributes_ctx.values = Qnil;
|
75
|
+
attributes_ctx.types = Qnil;
|
76
|
+
attributes_ctx.additional_types = Qnil;
|
77
|
+
|
78
|
+
attributes_ctx.shouldReadFromHash = false;
|
79
|
+
attributes_ctx.tryToReadFromAdditionalTypes = false;
|
80
|
+
|
81
|
+
volatile VALUE lazy_attribute_hash = panko_read_lazy_attributes_hash(obj);
|
82
|
+
|
68
83
|
if (lazy_attribute_hash == Qnil) {
|
69
|
-
|
84
|
+
// TODO: handle
|
70
85
|
}
|
71
86
|
|
72
|
-
bool tryToReadFromDelegateHash = false;
|
73
|
-
bool tryToReadFromAdditionalTypes = false;
|
74
|
-
|
75
|
-
// If lazy_attribute_hash is not ActiveRecord::LazyAttributeHash
|
76
|
-
// and it's actually hash, read from it
|
77
87
|
if (RB_TYPE_P(lazy_attribute_hash, T_HASH)) {
|
78
|
-
|
79
|
-
|
88
|
+
attributes_ctx.attributes_hash = lazy_attribute_hash;
|
89
|
+
attributes_ctx.shouldReadFromHash = true;
|
80
90
|
} else {
|
81
|
-
delegate_hash =
|
82
|
-
|
91
|
+
volatile VALUE delegate_hash =
|
92
|
+
rb_ivar_get(lazy_attribute_hash, delegate_hash_id);
|
93
|
+
if (!panko_is_empty_hash(delegate_hash)) {
|
94
|
+
attributes_ctx.attributes_hash = delegate_hash;
|
95
|
+
attributes_ctx.shouldReadFromHash = true;
|
96
|
+
}
|
83
97
|
|
84
|
-
panko_read_types_and_value(lazy_attribute_hash, &types,
|
85
|
-
&
|
98
|
+
panko_read_types_and_value(lazy_attribute_hash, &attributes_ctx.types,
|
99
|
+
&attributes_ctx.additional_types,
|
100
|
+
&attributes_ctx.values);
|
86
101
|
|
87
|
-
tryToReadFromAdditionalTypes =
|
102
|
+
attributes_ctx.tryToReadFromAdditionalTypes =
|
103
|
+
!panko_is_empty_hash(attributes_ctx.additional_types);
|
88
104
|
}
|
89
105
|
|
90
|
-
|
91
|
-
|
92
|
-
for (i = 0; i < RARRAY_LEN(attributes); i++) {
|
93
|
-
volatile VALUE member_raw = RARRAY_AREF(attributes, i);
|
94
|
-
volatile VALUE member = rb_sym2str(member_raw);
|
106
|
+
return attributes_ctx;
|
107
|
+
}
|
95
108
|
|
96
|
-
|
97
|
-
|
109
|
+
VALUE read_attribute(struct attributes attributes_ctx, Attribute attribute) {
|
110
|
+
VALUE member = attribute->name_str;
|
111
|
+
volatile VALUE value = Qundef;
|
98
112
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
read_attribute_from_hash(delegate_hash, member, &value, &type_metadata);
|
113
|
+
if (attributes_ctx.values != Qnil && value == Qundef) {
|
114
|
+
value = rb_hash_aref(attributes_ctx.values, member);
|
115
|
+
if (value == Qnil) {
|
116
|
+
value = Qundef;
|
104
117
|
}
|
118
|
+
}
|
119
|
+
|
120
|
+
if (value == Qundef && attributes_ctx.shouldReadFromHash) {
|
121
|
+
read_attribute_from_hash(attributes_ctx.attributes_hash, member, &value,
|
122
|
+
&attribute->type);
|
123
|
+
}
|
105
124
|
|
106
|
-
|
107
|
-
|
125
|
+
if (attribute->type == Qnil) {
|
126
|
+
if (attributes_ctx.tryToReadFromAdditionalTypes) {
|
127
|
+
attribute->type = rb_hash_aref(attributes_ctx.additional_types, member);
|
128
|
+
}
|
108
129
|
|
109
|
-
|
110
|
-
|
111
|
-
}
|
112
|
-
if (type_metadata == Qnil) {
|
113
|
-
type_metadata = rb_hash_aref(types, member);
|
114
|
-
}
|
130
|
+
if (attributes_ctx.types != Qnil && attribute->type == Qnil) {
|
131
|
+
attribute->type = rb_hash_aref(attributes_ctx.types, member);
|
115
132
|
}
|
133
|
+
}
|
134
|
+
|
135
|
+
if (attribute->type != Qnil && value != Qnil) {
|
136
|
+
return type_cast(attribute->type, value);
|
137
|
+
}
|
138
|
+
|
139
|
+
return value;
|
140
|
+
}
|
141
|
+
|
142
|
+
VALUE panko_each_attribute(VALUE obj,
|
143
|
+
VALUE attributes,
|
144
|
+
EachAttributeFunc func,
|
145
|
+
VALUE writer) {
|
146
|
+
long i;
|
147
|
+
struct attributes attributes_ctx = init_context(obj);
|
148
|
+
volatile VALUE record_class = CLASS_OF(obj);
|
149
|
+
|
150
|
+
for (i = 0; i < RARRAY_LEN(attributes); i++) {
|
151
|
+
volatile VALUE raw_attribute = RARRAY_AREF(attributes, i);
|
152
|
+
Attribute attribute = attribute_read(raw_attribute);
|
153
|
+
attribute_try_invalidate(attribute, record_class);
|
116
154
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
member = rb_sym2str(alias_name);
|
121
|
-
}
|
155
|
+
volatile VALUE name_str = attribute->name_str;
|
156
|
+
if (attribute->alias_name != Qnil) {
|
157
|
+
name_str = attribute->alias_name;
|
122
158
|
}
|
123
159
|
|
124
|
-
|
160
|
+
volatile VALUE value = read_attribute(attributes_ctx, attribute);
|
161
|
+
func(writer, name_str, value);
|
125
162
|
}
|
126
163
|
|
127
164
|
return Qnil;
|
@@ -1,17 +1,14 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <stdbool.h>
|
3
3
|
|
4
|
+
#include "attribute.h"
|
4
5
|
#include "serialization_descriptor.h"
|
6
|
+
#include "type_cast.h"
|
5
7
|
|
6
|
-
typedef void (*EachAttributeFunc)(VALUE
|
7
|
-
VALUE name,
|
8
|
-
VALUE value,
|
9
|
-
VALUE type_metadata,
|
10
|
-
VALUE context);
|
8
|
+
typedef void (*EachAttributeFunc)(VALUE writer, VALUE name, VALUE value);
|
11
9
|
|
12
10
|
extern VALUE panko_each_attribute(VALUE object,
|
13
11
|
VALUE attributes,
|
14
|
-
VALUE aliases,
|
15
12
|
EachAttributeFunc func,
|
16
13
|
VALUE context);
|
17
14
|
|
@@ -9,14 +9,7 @@ static ID pop_id;
|
|
9
9
|
|
10
10
|
static ID to_a_id;
|
11
11
|
|
12
|
-
void write_value(VALUE str_writer,
|
13
|
-
VALUE key,
|
14
|
-
VALUE value,
|
15
|
-
VALUE type_metadata) {
|
16
|
-
if (type_metadata != Qnil && value != Qnil) {
|
17
|
-
value = type_cast(type_metadata, value);
|
18
|
-
}
|
19
|
-
|
12
|
+
void write_value(VALUE str_writer, VALUE key, VALUE value) {
|
20
13
|
rb_funcall(str_writer, push_value_id, 2, value, key);
|
21
14
|
}
|
22
15
|
|
@@ -36,28 +29,20 @@ void serialize_method_fields(VALUE subject,
|
|
36
29
|
sd_apply_serializer_config(serializer, subject, context);
|
37
30
|
|
38
31
|
for (i = 0; i < RARRAY_LEN(method_fields); i++) {
|
39
|
-
VALUE attribute_name = RARRAY_AREF(method_fields, i);
|
32
|
+
volatile VALUE attribute_name = RARRAY_AREF(method_fields, i);
|
40
33
|
volatile VALUE result =
|
41
34
|
rb_funcall(serializer, rb_sym2id(attribute_name), 0);
|
42
35
|
|
43
|
-
write_value(str_writer, rb_sym2str(attribute_name), result
|
36
|
+
write_value(str_writer, rb_sym2str(attribute_name), result);
|
44
37
|
}
|
45
38
|
}
|
46
39
|
|
47
|
-
void panko_attributes_iter(VALUE object,
|
48
|
-
VALUE name,
|
49
|
-
VALUE value,
|
50
|
-
VALUE type_metadata,
|
51
|
-
VALUE str_writer) {
|
52
|
-
write_value(str_writer, name, value, type_metadata);
|
53
|
-
}
|
54
|
-
|
55
40
|
void serialize_fields(VALUE subject,
|
56
41
|
VALUE str_writer,
|
57
42
|
SerializationDescriptor descriptor,
|
58
43
|
VALUE context) {
|
59
|
-
panko_each_attribute(subject, descriptor->
|
60
|
-
|
44
|
+
panko_each_attribute(subject, descriptor->attributes, write_value,
|
45
|
+
str_writer);
|
61
46
|
|
62
47
|
serialize_method_fields(subject, str_writer, descriptor, context);
|
63
48
|
}
|
@@ -69,17 +54,16 @@ void serialize_has_one_associations(VALUE subject,
|
|
69
54
|
VALUE associations) {
|
70
55
|
long i;
|
71
56
|
for (i = 0; i < RARRAY_LEN(associations); i++) {
|
72
|
-
volatile VALUE
|
57
|
+
volatile VALUE association_el = RARRAY_AREF(associations, i);
|
58
|
+
Association association = association_read(association_el);
|
73
59
|
|
74
|
-
volatile VALUE
|
75
|
-
volatile VALUE association_descriptor = RARRAY_AREF(association, 1);
|
76
|
-
volatile VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
|
60
|
+
volatile VALUE value = rb_funcall(subject, association->name_id, 0);
|
77
61
|
|
78
62
|
if (value == Qnil) {
|
79
|
-
write_value(str_writer,
|
63
|
+
write_value(str_writer, association->name_str, value);
|
80
64
|
} else {
|
81
|
-
serialize_subject(
|
82
|
-
|
65
|
+
serialize_subject(association->name_str, value, str_writer,
|
66
|
+
association->descriptor, context);
|
83
67
|
}
|
84
68
|
}
|
85
69
|
}
|
@@ -91,17 +75,16 @@ void serialize_has_many_associations(VALUE subject,
|
|
91
75
|
VALUE associations) {
|
92
76
|
long i;
|
93
77
|
for (i = 0; i < RARRAY_LEN(associations); i++) {
|
94
|
-
volatile VALUE
|
78
|
+
volatile VALUE association_el = RARRAY_AREF(associations, i);
|
79
|
+
Association association = association_read(association_el);
|
95
80
|
|
96
|
-
volatile VALUE
|
97
|
-
volatile VALUE association_descriptor = RARRAY_AREF(association, 1);
|
98
|
-
volatile VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
|
81
|
+
volatile VALUE value = rb_funcall(subject, association->name_id, 0);
|
99
82
|
|
100
83
|
if (value == Qnil) {
|
101
|
-
write_value(str_writer,
|
84
|
+
write_value(str_writer, association->name_str, value);
|
102
85
|
} else {
|
103
|
-
serialize_subjects(
|
104
|
-
|
86
|
+
serialize_subjects(association->name_str, value, str_writer,
|
87
|
+
association->descriptor, context);
|
105
88
|
}
|
106
89
|
}
|
107
90
|
}
|
@@ -190,4 +173,6 @@ void Init_panko_serializer() {
|
|
190
173
|
panko_init_serialization_descriptor(mPanko);
|
191
174
|
panko_init_attributes_iterator(mPanko);
|
192
175
|
panko_init_type_cast(mPanko);
|
176
|
+
panko_init_attribute(mPanko);
|
177
|
+
panko_init_association(mPanko);
|
193
178
|
}
|
@@ -5,46 +5,44 @@ VALUE cSerializationDescriptor;
|
|
5
5
|
static ID context_id;
|
6
6
|
static ID object_id;
|
7
7
|
|
8
|
-
static void
|
9
|
-
|
10
|
-
if (ptr == 0) {
|
8
|
+
static void sd_free(SerializationDescriptor sd) {
|
9
|
+
if (!sd) {
|
11
10
|
return;
|
12
11
|
}
|
13
12
|
|
14
|
-
sd = (SerializationDescriptor)ptr;
|
15
13
|
sd->serializer_type = Qnil;
|
16
14
|
sd->serializer = Qnil;
|
17
|
-
sd->
|
15
|
+
sd->attributes = Qnil;
|
18
16
|
sd->method_fields = Qnil;
|
19
17
|
sd->has_one_associations = Qnil;
|
20
18
|
sd->has_many_associations = Qnil;
|
21
19
|
sd->aliases = Qnil;
|
20
|
+
|
21
|
+
xfree(sd);
|
22
22
|
}
|
23
23
|
|
24
|
-
void
|
24
|
+
void sd_mark(SerializationDescriptor data) {
|
25
25
|
rb_gc_mark(data->serializer_type);
|
26
26
|
rb_gc_mark(data->serializer);
|
27
|
-
rb_gc_mark(data->
|
27
|
+
rb_gc_mark(data->attributes);
|
28
28
|
rb_gc_mark(data->method_fields);
|
29
29
|
rb_gc_mark(data->has_one_associations);
|
30
30
|
rb_gc_mark(data->has_many_associations);
|
31
31
|
rb_gc_mark(data->aliases);
|
32
32
|
}
|
33
33
|
|
34
|
-
static VALUE
|
34
|
+
static VALUE sd_new(int argc, VALUE* argv, VALUE self) {
|
35
35
|
SerializationDescriptor sd = ALLOC(struct _SerializationDescriptor);
|
36
36
|
|
37
37
|
sd->serializer = Qnil;
|
38
38
|
sd->serializer_type = Qnil;
|
39
|
-
sd->
|
39
|
+
sd->attributes = Qnil;
|
40
40
|
sd->method_fields = Qnil;
|
41
41
|
sd->has_one_associations = Qnil;
|
42
42
|
sd->has_many_associations = Qnil;
|
43
43
|
sd->aliases = Qnil;
|
44
44
|
|
45
|
-
return Data_Wrap_Struct(cSerializationDescriptor,
|
46
|
-
serialization_descriptor_mark,
|
47
|
-
serialization_descriptor_free, sd);
|
45
|
+
return Data_Wrap_Struct(cSerializationDescriptor, sd_mark, sd_free, sd);
|
48
46
|
}
|
49
47
|
|
50
48
|
SerializationDescriptor sd_read(VALUE descriptor) {
|
@@ -60,87 +58,94 @@ VALUE sd_build_serializer(SerializationDescriptor sd) {
|
|
60
58
|
return sd->serializer;
|
61
59
|
}
|
62
60
|
|
61
|
+
VALUE sd_serializer_set(VALUE self, VALUE serializer) {
|
62
|
+
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
63
|
+
|
64
|
+
sd->serializer = serializer;
|
65
|
+
return Qnil;
|
66
|
+
}
|
67
|
+
|
68
|
+
VALUE sd_serializer_ref(VALUE self) {
|
69
|
+
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
70
|
+
|
71
|
+
return sd->serializer;
|
72
|
+
}
|
73
|
+
|
63
74
|
void sd_apply_serializer_config(VALUE serializer, VALUE object, VALUE context) {
|
64
75
|
rb_ivar_set(serializer, object_id, object);
|
65
|
-
if(context != Qnil && context != Qundef) {
|
76
|
+
if (context != Qnil && context != Qundef) {
|
66
77
|
rb_ivar_set(serializer, context_id, context);
|
67
78
|
}
|
68
79
|
}
|
69
|
-
|
70
|
-
VALUE serialization_descriptor_fields_set(VALUE self, VALUE fields) {
|
80
|
+
VALUE sd_attributes_set(VALUE self, VALUE attributes) {
|
71
81
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
72
82
|
|
73
|
-
sd->
|
83
|
+
sd->attributes = attributes;
|
74
84
|
return Qnil;
|
75
85
|
}
|
76
86
|
|
77
|
-
VALUE
|
87
|
+
VALUE sd_attributes_ref(VALUE self) {
|
78
88
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
79
|
-
return sd->
|
89
|
+
return sd->attributes;
|
80
90
|
}
|
81
91
|
|
82
|
-
VALUE
|
83
|
-
VALUE method_fields) {
|
92
|
+
VALUE sd_method_fields_set(VALUE self, VALUE method_fields) {
|
84
93
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
85
94
|
sd->method_fields = method_fields;
|
86
95
|
return Qnil;
|
87
96
|
}
|
88
97
|
|
89
|
-
VALUE
|
98
|
+
VALUE sd_method_fields_ref(VALUE self) {
|
90
99
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
91
100
|
return sd->method_fields;
|
92
101
|
}
|
93
102
|
|
94
|
-
VALUE
|
95
|
-
VALUE self,
|
96
|
-
VALUE has_one_associations) {
|
103
|
+
VALUE sd_has_one_associations_set(VALUE self, VALUE has_one_associations) {
|
97
104
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
98
105
|
sd->has_one_associations = has_one_associations;
|
99
106
|
return Qnil;
|
100
107
|
}
|
101
108
|
|
102
|
-
VALUE
|
109
|
+
VALUE sd_has_one_associations_ref(VALUE self) {
|
103
110
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
104
111
|
return sd->has_one_associations;
|
105
112
|
}
|
106
113
|
|
107
|
-
VALUE
|
108
|
-
VALUE self,
|
109
|
-
VALUE has_many_associations) {
|
114
|
+
VALUE sd_has_many_associations_set(VALUE self, VALUE has_many_associations) {
|
110
115
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
111
116
|
sd->has_many_associations = has_many_associations;
|
112
117
|
return Qnil;
|
113
118
|
}
|
114
119
|
|
115
|
-
VALUE
|
120
|
+
VALUE sd_has_many_associations_ref(VALUE self) {
|
116
121
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
117
122
|
return sd->has_many_associations;
|
118
123
|
}
|
119
124
|
|
120
|
-
VALUE
|
125
|
+
VALUE sd_type_set(VALUE self, VALUE type) {
|
121
126
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
122
127
|
sd->serializer_type = type;
|
123
128
|
return Qnil;
|
124
129
|
}
|
125
130
|
|
126
|
-
VALUE
|
131
|
+
VALUE sd_type_aref(VALUE self, VALUE type) {
|
127
132
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
128
133
|
return sd->serializer_type;
|
129
134
|
}
|
130
135
|
|
131
|
-
VALUE
|
136
|
+
VALUE sd_aliases_set(VALUE self, VALUE aliases) {
|
132
137
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
133
138
|
sd->aliases = aliases;
|
134
139
|
return Qnil;
|
135
140
|
}
|
136
141
|
|
137
|
-
VALUE
|
142
|
+
VALUE sd_aliases_aref(VALUE self, VALUE aliases) {
|
138
143
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
139
144
|
return sd->aliases;
|
140
145
|
}
|
141
146
|
|
142
147
|
// Exposing this for testing
|
143
|
-
VALUE
|
148
|
+
VALUE public_sd_build_serializer(VALUE self) {
|
144
149
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
145
150
|
return sd_build_serializer(sd);
|
146
151
|
}
|
@@ -152,40 +157,39 @@ void panko_init_serialization_descriptor(VALUE mPanko) {
|
|
152
157
|
cSerializationDescriptor =
|
153
158
|
rb_define_class_under(mPanko, "SerializationDescriptor", rb_cObject);
|
154
159
|
|
155
|
-
rb_define_module_function(cSerializationDescriptor, "new",
|
156
|
-
serialization_descriptor_new, -1);
|
160
|
+
rb_define_module_function(cSerializationDescriptor, "new", sd_new, -1);
|
157
161
|
|
158
|
-
rb_define_method(cSerializationDescriptor,
|
159
|
-
|
160
|
-
rb_define_method(cSerializationDescriptor, "
|
161
|
-
|
162
|
+
rb_define_method(cSerializationDescriptor, "serializer=", sd_serializer_set,
|
163
|
+
1);
|
164
|
+
rb_define_method(cSerializationDescriptor, "serializer", sd_serializer_ref,
|
165
|
+
0);
|
162
166
|
|
163
|
-
rb_define_method(cSerializationDescriptor,
|
164
|
-
"method_fields=", serialization_descriptor_method_fields_set,
|
167
|
+
rb_define_method(cSerializationDescriptor, "attributes=", sd_attributes_set,
|
165
168
|
1);
|
169
|
+
rb_define_method(cSerializationDescriptor, "attributes", sd_attributes_ref,
|
170
|
+
0);
|
171
|
+
|
172
|
+
rb_define_method(cSerializationDescriptor,
|
173
|
+
"method_fields=", sd_method_fields_set, 1);
|
166
174
|
rb_define_method(cSerializationDescriptor, "method_fields",
|
167
|
-
|
175
|
+
sd_method_fields_ref, 0);
|
168
176
|
|
169
|
-
rb_define_method(cSerializationDescriptor,
|
170
|
-
|
177
|
+
rb_define_method(cSerializationDescriptor,
|
178
|
+
"has_one_associations=", sd_has_one_associations_set, 1);
|
171
179
|
rb_define_method(cSerializationDescriptor, "has_one_associations",
|
172
|
-
|
180
|
+
sd_has_one_associations_ref, 0);
|
173
181
|
|
174
|
-
rb_define_method(cSerializationDescriptor,
|
175
|
-
|
182
|
+
rb_define_method(cSerializationDescriptor,
|
183
|
+
"has_many_associations=", sd_has_many_associations_set, 1);
|
176
184
|
rb_define_method(cSerializationDescriptor, "has_many_associations",
|
177
|
-
|
185
|
+
sd_has_many_associations_ref, 0);
|
178
186
|
|
179
|
-
rb_define_method(cSerializationDescriptor,
|
180
|
-
|
181
|
-
rb_define_method(cSerializationDescriptor, "type",
|
182
|
-
serialization_descriptor_type_aref, 0);
|
187
|
+
rb_define_method(cSerializationDescriptor, "type=", sd_type_set, 1);
|
188
|
+
rb_define_method(cSerializationDescriptor, "type", sd_type_aref, 0);
|
183
189
|
|
184
|
-
rb_define_method(cSerializationDescriptor,
|
185
|
-
|
186
|
-
rb_define_method(cSerializationDescriptor, "aliases",
|
187
|
-
serialization_descriptor_aliases_aref, 0);
|
190
|
+
rb_define_method(cSerializationDescriptor, "aliases=", sd_aliases_set, 1);
|
191
|
+
rb_define_method(cSerializationDescriptor, "aliases", sd_aliases_aref, 0);
|
188
192
|
|
189
193
|
rb_define_method(cSerializationDescriptor, "build_serializer",
|
190
|
-
|
194
|
+
public_sd_build_serializer, 0);
|
191
195
|
}
|
@@ -10,19 +10,17 @@ typedef struct _SerializationDescriptor {
|
|
10
10
|
VALUE serializer;
|
11
11
|
|
12
12
|
// Metadata
|
13
|
-
VALUE
|
14
|
-
VALUE method_fields;
|
13
|
+
VALUE attributes;
|
15
14
|
VALUE aliases;
|
15
|
+
VALUE method_fields;
|
16
16
|
VALUE has_one_associations;
|
17
17
|
VALUE has_many_associations;
|
18
18
|
} * SerializationDescriptor;
|
19
19
|
|
20
|
-
VALUE serialization_descriptor_fields_ref(VALUE descriptor);
|
21
|
-
VALUE serialization_descriptor_method_fields_ref(VALUE descriptor);
|
22
|
-
VALUE serialization_descriptor_has_one_associations_ref(VALUE descriptor);
|
23
|
-
VALUE serialization_descriptor_has_many_associations_ref(VALUE descriptor);
|
24
|
-
|
25
20
|
SerializationDescriptor sd_read(VALUE descriptor);
|
21
|
+
|
22
|
+
void sd_mark(SerializationDescriptor data);
|
23
|
+
|
26
24
|
VALUE sd_build_serializer(SerializationDescriptor descriptor);
|
27
25
|
void sd_apply_serializer_config(VALUE serializer, VALUE object, VALUE context);
|
28
26
|
|
@@ -5,6 +5,10 @@ ID deserialize_from_db_id = 0;
|
|
5
5
|
ID to_s_id = 0;
|
6
6
|
ID to_i_id = 0;
|
7
7
|
|
8
|
+
static VALUE oj_type = Qundef;
|
9
|
+
static VALUE oj_parseerror_type = Qundef;
|
10
|
+
ID load_id = 0;
|
11
|
+
|
8
12
|
// Caching ActiveRecord Types
|
9
13
|
static VALUE ar_string_type = Qundef;
|
10
14
|
static VALUE ar_text_type = Qundef;
|
@@ -41,11 +45,25 @@ VALUE cache_postgres_type_lookup(VALUE ar) {
|
|
41
45
|
return Qfalse;
|
42
46
|
}
|
43
47
|
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
48
|
+
if (rb_const_defined_at(ar_oid, rb_intern("Float")) == (int)Qtrue) {
|
49
|
+
ar_pg_float_type = rb_const_get_at(ar_oid, rb_intern("Float"));
|
50
|
+
}
|
51
|
+
|
52
|
+
if (rb_const_defined_at(ar_oid, rb_intern("Integer")) == (int)Qtrue) {
|
53
|
+
ar_pg_integer_type = rb_const_get_at(ar_oid, rb_intern("Integer"));
|
54
|
+
}
|
55
|
+
|
56
|
+
if (rb_const_defined_at(ar_oid, rb_intern("Uuid")) == (int)Qtrue) {
|
57
|
+
ar_pg_uuid_type = rb_const_get_at(ar_oid, rb_intern("Uuid"));
|
58
|
+
}
|
59
|
+
|
60
|
+
if (rb_const_defined_at(ar_oid, rb_intern("Json")) == (int)Qtrue) {
|
61
|
+
ar_pg_json_type = rb_const_get_at(ar_oid, rb_intern("Json"));
|
62
|
+
}
|
63
|
+
|
64
|
+
if (rb_const_defined_at(ar_oid, rb_intern("DateTime")) == (int)Qtrue) {
|
65
|
+
ar_pg_date_time_type = rb_const_get_at(ar_oid, rb_intern("DateTime"));
|
66
|
+
}
|
49
67
|
|
50
68
|
return Qtrue;
|
51
69
|
}
|
@@ -187,14 +205,22 @@ bool is_json_type(VALUE type_klass) {
|
|
187
205
|
return ar_pg_json_type != Qundef && type_klass == ar_pg_json_type;
|
188
206
|
}
|
189
207
|
|
208
|
+
VALUE rescue_func() {
|
209
|
+
return Qnil;
|
210
|
+
}
|
211
|
+
|
212
|
+
VALUE parse_json(VALUE value) {
|
213
|
+
return rb_funcall(oj_type, load_id, 1, value);
|
214
|
+
}
|
215
|
+
|
190
216
|
VALUE cast_json_type(VALUE value) {
|
191
217
|
if (!RB_TYPE_P(value, T_STRING)) {
|
192
218
|
return value;
|
193
219
|
}
|
194
220
|
|
195
|
-
|
196
|
-
|
197
|
-
return
|
221
|
+
volatile VALUE result =
|
222
|
+
rb_rescue2(parse_json, value, rescue_func, Qundef, oj_parseerror_type, 0);
|
223
|
+
return result;
|
198
224
|
}
|
199
225
|
|
200
226
|
bool is_boolean_type(VALUE type_klass) {
|
@@ -282,6 +308,10 @@ void panko_init_type_cast(VALUE mPanko) {
|
|
282
308
|
to_s_id = rb_intern_const("to_s");
|
283
309
|
to_i_id = rb_intern_const("to_i");
|
284
310
|
|
311
|
+
oj_type = rb_const_get_at(rb_cObject, rb_intern("Oj"));
|
312
|
+
oj_parseerror_type = rb_const_get_at(oj_type, rb_intern("ParseError"));
|
313
|
+
load_id = rb_intern_const("load");
|
314
|
+
|
285
315
|
rb_define_singleton_method(mPanko, "_type_cast", public_type_cast, 2);
|
286
316
|
|
287
317
|
panko_init_time(mPanko);
|
@@ -1,6 +1,9 @@
|
|
1
1
|
#include <ruby.h>
|
2
2
|
#include <stdbool.h>
|
3
3
|
|
4
|
+
#ifndef __PANKO_TYPE_CAST_H__
|
5
|
+
#define __PANKO_TYPE_CAST_H__
|
6
|
+
|
4
7
|
/*
|
5
8
|
* Type Casting
|
6
9
|
*
|
@@ -72,3 +75,5 @@ static struct _TypeCast type_casts[] = {
|
|
72
75
|
|
73
76
|
extern VALUE type_cast(VALUE type_metadata, VALUE value);
|
74
77
|
void panko_init_type_cast(VALUE mPanko);
|
78
|
+
|
79
|
+
#endif
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Panko
|
4
|
+
class Attribute
|
5
|
+
def self.create(name, alias_name: nil)
|
6
|
+
alias_name = alias_name.to_s unless alias_name.nil?
|
7
|
+
Attribute.new(name.to_s, alias_name)
|
8
|
+
end
|
9
|
+
|
10
|
+
def ==(attr)
|
11
|
+
return name.to_sym == attr if attr.is_a? Symbol
|
12
|
+
if attr.is_a? Panko::Attribute
|
13
|
+
return name == attr.name && alias_name == attr.alias_name
|
14
|
+
end
|
15
|
+
super
|
16
|
+
end
|
17
|
+
|
18
|
+
def hash
|
19
|
+
name.to_sym.hash
|
20
|
+
end
|
21
|
+
|
22
|
+
def eql?(attr)
|
23
|
+
self.==(attr)
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspect
|
27
|
+
"<Panko::Attribute name=#{name.inspect} alias_name=#{alias_name.inspect}>"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/panko/response.rb
CHANGED
@@ -2,6 +2,12 @@
|
|
2
2
|
require "oj"
|
3
3
|
|
4
4
|
module Panko
|
5
|
+
JsonValue = Struct.new(:value) do
|
6
|
+
def self.from(value)
|
7
|
+
JsonValue.new(value)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
5
11
|
class Response
|
6
12
|
def initialize(data)
|
7
13
|
@data = data
|
@@ -15,6 +21,8 @@ module Panko
|
|
15
21
|
@data.each do |key, value|
|
16
22
|
if value.is_a?(Panko::ArraySerializer) || value.is_a?(Panko::Serializer)
|
17
23
|
writer.push_json(value.to_json, key.to_s)
|
24
|
+
elsif value.is_a?(Panko::JsonValue)
|
25
|
+
writer.push_json(value.value, key.to_s)
|
18
26
|
else
|
19
27
|
writer.push_value(value, key.to_s)
|
20
28
|
end
|
@@ -20,13 +20,31 @@ module Panko
|
|
20
20
|
|
21
21
|
backend.type = descriptor.type
|
22
22
|
|
23
|
-
backend.
|
23
|
+
backend.attributes = descriptor.attributes.map do |attr|
|
24
|
+
Attribute.create(attr.name, alias_name: attr.alias_name)
|
25
|
+
end
|
26
|
+
|
24
27
|
backend.method_fields = descriptor.method_fields.dup
|
25
28
|
|
26
|
-
|
27
|
-
|
29
|
+
unless descriptor.serializer.nil?
|
30
|
+
backend.serializer = descriptor.serializer.reset
|
31
|
+
end
|
32
|
+
|
33
|
+
backend.has_many_associations = descriptor.has_many_associations.map do |assoc|
|
34
|
+
Panko::Association.new(
|
35
|
+
assoc.name_sym,
|
36
|
+
assoc.name_sym.to_s,
|
37
|
+
Panko::SerializationDescriptor.duplicate(assoc.descriptor)
|
38
|
+
)
|
39
|
+
end
|
28
40
|
|
29
|
-
backend.
|
41
|
+
backend.has_one_associations = descriptor.has_one_associations.map do |assoc|
|
42
|
+
Panko::Association.new(
|
43
|
+
assoc.name_sym,
|
44
|
+
assoc.name_sym.to_s,
|
45
|
+
Panko::SerializationDescriptor.duplicate(assoc.descriptor)
|
46
|
+
)
|
47
|
+
end
|
30
48
|
|
31
49
|
backend
|
32
50
|
end
|
@@ -40,14 +58,7 @@ module Panko
|
|
40
58
|
attributes_only_filters, associations_only_filters = resolve_filters(options, :only)
|
41
59
|
attributes_except_filters, associations_except_filters = resolve_filters(options, :except)
|
42
60
|
|
43
|
-
|
44
|
-
self.aliases,
|
45
|
-
attributes_only_filters,
|
46
|
-
attributes_except_filters
|
47
|
-
)
|
48
|
-
|
49
|
-
self.fields = apply_fields_filters(
|
50
|
-
self.fields,
|
61
|
+
apply_attribute_filters!(
|
51
62
|
attributes_only_filters,
|
52
63
|
attributes_except_filters
|
53
64
|
)
|
@@ -79,17 +90,19 @@ module Panko
|
|
79
90
|
attributes_only_filters = only_filters[:attributes] || []
|
80
91
|
unless attributes_only_filters.empty?
|
81
92
|
associations.select! do |association|
|
82
|
-
attributes_only_filters.include?(association.
|
93
|
+
attributes_only_filters.include?(association.name_sym)
|
83
94
|
end
|
84
95
|
end
|
85
96
|
|
97
|
+
|
86
98
|
attributes_except_filters = except_filters[:attributes] || []
|
87
99
|
unless attributes_except_filters.empty?
|
88
100
|
associations.reject! do |association|
|
89
|
-
attributes_except_filters.include?(association.
|
101
|
+
attributes_except_filters.include?(association.name_sym)
|
90
102
|
end
|
91
103
|
end
|
92
104
|
|
105
|
+
|
93
106
|
associations_only_filters = only_filters[:associations]
|
94
107
|
associations_except_filters = except_filters[:associations]
|
95
108
|
|
@@ -98,8 +111,8 @@ module Panko
|
|
98
111
|
end
|
99
112
|
|
100
113
|
associations.map do |association|
|
101
|
-
name = association.
|
102
|
-
descriptor = association.
|
114
|
+
name = association.name_sym
|
115
|
+
descriptor = association.descriptor
|
103
116
|
|
104
117
|
only_filter = associations_only_filters[name]
|
105
118
|
except_filter = associations_except_filters[name]
|
@@ -107,7 +120,6 @@ module Panko
|
|
107
120
|
filters = {}
|
108
121
|
filters[:only] = only_filter unless only_filter.nil?
|
109
122
|
filters[:except] = except_filter unless except_filter.nil?
|
110
|
-
|
111
123
|
descriptor.apply_filters(filters) unless filters.empty?
|
112
124
|
|
113
125
|
association
|
@@ -140,24 +152,22 @@ module Panko
|
|
140
152
|
fields
|
141
153
|
end
|
142
154
|
|
143
|
-
def
|
144
|
-
return if self.aliases.nil? || self.aliases.empty?
|
145
|
-
|
155
|
+
def apply_attribute_filters!(only, except)
|
146
156
|
unless only.empty?
|
147
|
-
|
148
|
-
|
149
|
-
|
157
|
+
self.attributes.select! do |attribute|
|
158
|
+
name_to_check = attribute.name
|
159
|
+
name_to_check = attribute.alias_name unless attribute.alias_name.nil?
|
150
160
|
|
151
|
-
|
161
|
+
only.include?(name_to_check.to_sym)
|
152
162
|
end
|
153
163
|
end
|
154
164
|
|
155
165
|
unless except.empty?
|
156
|
-
|
157
|
-
|
158
|
-
|
166
|
+
self.attributes.reject! do |attribute|
|
167
|
+
name_to_check = attribute.name
|
168
|
+
name_to_check = attribute.alias_name unless attribute.alias_name.nil?
|
159
169
|
|
160
|
-
|
170
|
+
except.include?(name_to_check.to_sym)
|
161
171
|
end
|
162
172
|
end
|
163
173
|
end
|
data/lib/panko/serializer.rb
CHANGED
@@ -9,9 +9,11 @@ module Panko
|
|
9
9
|
base._descriptor = Panko::SerializationDescriptor.new
|
10
10
|
base._descriptor.type = base
|
11
11
|
|
12
|
+
base._descriptor.attributes = []
|
12
13
|
base._descriptor.aliases = {}
|
13
|
-
|
14
|
+
|
14
15
|
base._descriptor.method_fields = []
|
16
|
+
|
15
17
|
base._descriptor.has_many_associations = []
|
16
18
|
base._descriptor.has_one_associations = []
|
17
19
|
end
|
@@ -19,36 +21,39 @@ module Panko
|
|
19
21
|
attr_accessor :_descriptor
|
20
22
|
|
21
23
|
def attributes(*attrs)
|
22
|
-
@_descriptor.
|
24
|
+
@_descriptor.attributes.push(*attrs.map { |attr| Attribute.create(attr) }).uniq!
|
23
25
|
end
|
24
26
|
|
25
27
|
def aliases(aliases = {})
|
26
|
-
|
27
|
-
|
28
|
+
aliases.each do |attr, alias_name|
|
29
|
+
@_descriptor.attributes << Attribute.create(attr, alias_name: alias_name)
|
30
|
+
end
|
28
31
|
end
|
29
32
|
|
30
33
|
def method_added(method)
|
31
34
|
return if @_descriptor.nil?
|
32
|
-
@_descriptor.
|
35
|
+
@_descriptor.attributes.delete(method)
|
33
36
|
@_descriptor.method_fields << method
|
34
37
|
end
|
35
38
|
|
36
39
|
def has_one(name, options)
|
37
40
|
serializer_const = options[:serializer]
|
38
41
|
|
39
|
-
@_descriptor.has_one_associations <<
|
42
|
+
@_descriptor.has_one_associations << Panko::Association.new(
|
40
43
|
name,
|
44
|
+
name.to_s,
|
41
45
|
Panko::SerializationDescriptor.build(serializer_const, options)
|
42
|
-
|
46
|
+
)
|
43
47
|
end
|
44
48
|
|
45
49
|
def has_many(name, options)
|
46
50
|
serializer_const = options[:serializer] || options[:each_serializer]
|
47
51
|
|
48
|
-
@_descriptor.has_many_associations <<
|
52
|
+
@_descriptor.has_many_associations << Panko::Association.new(
|
49
53
|
name,
|
54
|
+
name.to_s.freeze,
|
50
55
|
Panko::SerializationDescriptor.build(serializer_const, options)
|
51
|
-
|
56
|
+
)
|
52
57
|
end
|
53
58
|
end
|
54
59
|
|
@@ -68,5 +73,12 @@ module Panko
|
|
68
73
|
Panko::serialize_subject(object, writer, @descriptor, @context)
|
69
74
|
writer.to_s
|
70
75
|
end
|
76
|
+
|
77
|
+
def reset
|
78
|
+
@object = nil
|
79
|
+
@context = nil
|
80
|
+
|
81
|
+
self
|
82
|
+
end
|
71
83
|
end
|
72
84
|
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.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yosi Attias
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-12-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- LICENSE.txt
|
98
98
|
- README.md
|
99
99
|
- Rakefile
|
100
|
+
- _config.yml
|
100
101
|
- benchmarks/BENCHMARKS.md
|
101
102
|
- benchmarks/allocs.rb
|
102
103
|
- benchmarks/app.rb
|
@@ -112,6 +113,10 @@ files:
|
|
112
113
|
- benchmarks/type_casts/bm_active_record.rb
|
113
114
|
- benchmarks/type_casts/bm_panko.rb
|
114
115
|
- benchmarks/type_casts/support.rb
|
116
|
+
- ext/panko_serializer/association.c
|
117
|
+
- ext/panko_serializer/association.h
|
118
|
+
- ext/panko_serializer/attribute.c
|
119
|
+
- ext/panko_serializer/attribute.h
|
115
120
|
- ext/panko_serializer/attributes_iterator.c
|
116
121
|
- ext/panko_serializer/attributes_iterator.h
|
117
122
|
- ext/panko_serializer/extconf.rb
|
@@ -124,6 +129,7 @@ files:
|
|
124
129
|
- ext/panko_serializer/type_cast.c
|
125
130
|
- ext/panko_serializer/type_cast.h
|
126
131
|
- lib/panko/array_serializer.rb
|
132
|
+
- lib/panko/attribute.rb
|
127
133
|
- lib/panko/response.rb
|
128
134
|
- lib/panko/serialization_descriptor.rb
|
129
135
|
- lib/panko/serializer.rb
|
@@ -150,7 +156,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
150
156
|
version: '0'
|
151
157
|
requirements: []
|
152
158
|
rubyforge_project:
|
153
|
-
rubygems_version: 2.6.
|
159
|
+
rubygems_version: 2.6.14
|
154
160
|
signing_key:
|
155
161
|
specification_version: 4
|
156
162
|
summary: Fast serialization for ActiveModel
|