panko_serializer 0.1.4 → 0.1.5
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/README.md +7 -0
- data/benchmarks/type_casts/bm_panko.rb +0 -5
- data/ext/panko_serializer/attributes_iterator.c +19 -15
- data/ext/panko_serializer/panko_serializer.c +30 -25
- data/ext/panko_serializer/serialization_descriptor.c +13 -6
- data/ext/panko_serializer/time_conversion.c +42 -26
- data/ext/panko_serializer/type_cast.c +21 -14
- data/lib/panko/array_serializer.rb +1 -2
- data/lib/panko/serialization_descriptor.rb +38 -38
- data/lib/panko/serializer.rb +27 -13
- data/lib/panko/version.rb +1 -1
- data/panko_serializer.gemspec +0 -1
- metadata +3 -18
- data/lib/panko/cache.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73b05629bbbeb18415188b8c70e316f678f604ba
|
4
|
+
data.tar.gz: 95922dc138d747c5fa0ca282ff6b9eda4e004d55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1b6489dc3d9532d01766a38cbb6d0652275883d8ea8ad7b8dc6b82494f1d5035f5c95a925b2b0908bdcaf3a6807ec7afaca3c5982a1a894e102ac9aa7ae35243
|
7
|
+
data.tar.gz: 83c2b331d7acb26d4bbf6e851b5f30250b7074195c2f8a722bea053db867aa34af23a05dc015a0ceec098cfbc747b9f892516f9a8d534c50f5189180bcd5cf82
|
data/README.md
CHANGED
@@ -2,6 +2,13 @@
|
|
2
2
|
|
3
3
|
[](https://travis-ci.org/yosiat/panko_serializer)
|
4
4
|
|
5
|
+
Panko is high performance library for serializing ActiveRecord objects.
|
6
|
+
|
7
|
+
## Status
|
8
|
+
|
9
|
+
Panko is not ready for official release (it's missing documentation, tests, configuration options to remove assumptions).
|
10
|
+
|
11
|
+
|
5
12
|
|
6
13
|
## License
|
7
14
|
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
@@ -45,11 +45,6 @@ def db_panko_time
|
|
45
45
|
end
|
46
46
|
end
|
47
47
|
|
48
|
-
db_panko_time
|
49
|
-
utc_panko_time
|
50
|
-
|
51
|
-
exit
|
52
|
-
|
53
48
|
panko_type_convert ActiveRecord::Type::String, 1, "1"
|
54
49
|
panko_type_convert ActiveRecord::Type::Text, 1, "1"
|
55
50
|
panko_type_convert ActiveRecord::Type::Integer, "1", 1
|
@@ -1,24 +1,26 @@
|
|
1
1
|
#include "attributes_iterator.h"
|
2
2
|
|
3
|
-
static ID attributes_id
|
4
|
-
static ID types_id
|
5
|
-
static ID values_id
|
6
|
-
static ID delegate_hash_id
|
3
|
+
static ID attributes_id;
|
4
|
+
static ID types_id;
|
5
|
+
static ID values_id;
|
6
|
+
static ID delegate_hash_id;
|
7
7
|
|
8
|
-
static ID value_before_type_cast_id
|
9
|
-
static ID type_id
|
8
|
+
static ID value_before_type_cast_id;
|
9
|
+
static ID type_id;
|
10
10
|
|
11
11
|
VALUE read_attributes(VALUE obj) {
|
12
12
|
return rb_ivar_get(obj, attributes_id);
|
13
13
|
}
|
14
14
|
|
15
15
|
VALUE panko_read_lazy_attributes_hash(VALUE object) {
|
16
|
-
VALUE attributes_set
|
16
|
+
volatile VALUE attributes_set, attributes_hash;
|
17
|
+
|
18
|
+
attributes_set = read_attributes(object);
|
17
19
|
if (attributes_set == Qnil) {
|
18
20
|
return Qnil;
|
19
21
|
}
|
20
22
|
|
21
|
-
|
23
|
+
attributes_hash = read_attributes(attributes_set);
|
22
24
|
if (attributes_hash == Qnil) {
|
23
25
|
return Qnil;
|
24
26
|
}
|
@@ -37,29 +39,31 @@ VALUE panko_each_attribute(VALUE obj,
|
|
37
39
|
VALUE attributes,
|
38
40
|
EachAttributeFunc func,
|
39
41
|
VALUE context) {
|
40
|
-
VALUE attributes_hash
|
42
|
+
volatile VALUE attributes_hash, delegate_hash;
|
43
|
+
int i;
|
44
|
+
|
45
|
+
attributes_hash = panko_read_lazy_attributes_hash(obj);
|
41
46
|
if (attributes_hash == Qnil) {
|
42
47
|
return Qnil;
|
43
48
|
}
|
44
49
|
|
45
|
-
|
50
|
+
delegate_hash = rb_ivar_get(attributes_hash, delegate_hash_id);
|
46
51
|
bool tryToReadFromDelegateHash = RHASH_SIZE(delegate_hash) > 0;
|
47
52
|
|
48
53
|
VALUE types, values;
|
49
54
|
panko_read_types_and_value(attributes_hash, &types, &values);
|
50
55
|
|
51
|
-
int i;
|
52
56
|
for (i = 0; i < RARRAY_LEN(attributes); i++) {
|
53
|
-
VALUE member = RARRAY_AREF(attributes, i);
|
57
|
+
volatile VALUE member = rb_sym2str(RARRAY_AREF(attributes, i));
|
54
58
|
|
55
|
-
VALUE value = Qundef;
|
56
|
-
VALUE type_metadata = Qnil;
|
59
|
+
volatile VALUE value = Qundef;
|
60
|
+
volatile VALUE type_metadata = Qnil;
|
57
61
|
|
58
62
|
// First try to read from delegate hash,
|
59
63
|
// If the object was create in memory `User.new(name: "Yosi")`
|
60
64
|
// it won't exist in types/values
|
61
65
|
if (tryToReadFromDelegateHash) {
|
62
|
-
VALUE attribute_metadata = rb_hash_aref(delegate_hash, member);
|
66
|
+
volatile VALUE attribute_metadata = rb_hash_aref(delegate_hash, member);
|
63
67
|
if (attribute_metadata != Qnil) {
|
64
68
|
value = rb_ivar_get(attribute_metadata, value_before_type_cast_id);
|
65
69
|
type_metadata = rb_ivar_get(attribute_metadata, type_id);
|
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
#include "panko_serializer.h"
|
4
4
|
|
5
|
-
static ID push_value_id
|
6
|
-
static ID push_array_id
|
7
|
-
static ID push_object_id
|
8
|
-
static ID pop_id
|
5
|
+
static ID push_value_id;
|
6
|
+
static ID push_array_id;
|
7
|
+
static ID push_object_id;
|
8
|
+
static ID pop_id;
|
9
9
|
|
10
|
-
static ID to_a_id
|
10
|
+
static ID to_a_id;
|
11
11
|
|
12
12
|
void write_value(VALUE str_writer,
|
13
13
|
VALUE key,
|
@@ -24,18 +24,21 @@ void serialize_method_fields(VALUE subject,
|
|
24
24
|
VALUE str_writer,
|
25
25
|
SerializationDescriptor descriptor,
|
26
26
|
VALUE context) {
|
27
|
-
VALUE method_fields
|
27
|
+
VALUE method_fields, serializer;
|
28
|
+
long i;
|
29
|
+
|
30
|
+
method_fields = descriptor->method_fields;
|
28
31
|
if (RARRAY_LEN(method_fields) == 0) {
|
29
32
|
return;
|
30
33
|
}
|
31
34
|
|
32
|
-
|
35
|
+
serializer = sd_build_serializer(descriptor);
|
33
36
|
sd_apply_serializer_config(serializer, subject, context);
|
34
37
|
|
35
|
-
long i;
|
36
38
|
for (i = 0; i < RARRAY_LEN(method_fields); i++) {
|
37
39
|
VALUE attribute_name = RARRAY_AREF(method_fields, i);
|
38
|
-
VALUE result =
|
40
|
+
volatile VALUE result =
|
41
|
+
rb_funcall(serializer, rb_sym2id(attribute_name), 0);
|
39
42
|
|
40
43
|
write_value(str_writer, rb_sym2str(attribute_name), result, Qnil);
|
41
44
|
}
|
@@ -53,7 +56,8 @@ void serialize_fields(VALUE subject,
|
|
53
56
|
VALUE str_writer,
|
54
57
|
SerializationDescriptor descriptor,
|
55
58
|
VALUE context) {
|
56
|
-
panko_each_attribute(subject, descriptor->fields, panko_attributes_iter,
|
59
|
+
panko_each_attribute(subject, descriptor->fields, panko_attributes_iter,
|
60
|
+
str_writer);
|
57
61
|
|
58
62
|
serialize_method_fields(subject, str_writer, descriptor, context);
|
59
63
|
}
|
@@ -65,11 +69,11 @@ void serialize_has_one_associatoins(VALUE subject,
|
|
65
69
|
VALUE associations) {
|
66
70
|
long i;
|
67
71
|
for (i = 0; i < RARRAY_LEN(associations); i++) {
|
68
|
-
VALUE association = RARRAY_AREF(associations, i);
|
72
|
+
volatile VALUE association = RARRAY_AREF(associations, i);
|
69
73
|
|
70
|
-
VALUE name = RARRAY_AREF(association, 0);
|
71
|
-
VALUE association_descriptor = RARRAY_AREF(association, 1);
|
72
|
-
VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
|
74
|
+
volatile VALUE name = RARRAY_AREF(association, 0);
|
75
|
+
volatile VALUE association_descriptor = RARRAY_AREF(association, 1);
|
76
|
+
volatile VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
|
73
77
|
|
74
78
|
if (value == Qnil) {
|
75
79
|
write_value(str_writer, rb_sym2str(name), value, Qnil);
|
@@ -87,11 +91,11 @@ void serialize_has_many_associatoins(VALUE subject,
|
|
87
91
|
VALUE associations) {
|
88
92
|
long i;
|
89
93
|
for (i = 0; i < RARRAY_LEN(associations); i++) {
|
90
|
-
VALUE association = RARRAY_AREF(associations, i);
|
94
|
+
volatile VALUE association = RARRAY_AREF(associations, i);
|
91
95
|
|
92
|
-
VALUE name = RARRAY_AREF(association, 0);
|
93
|
-
VALUE association_descriptor = RARRAY_AREF(association, 1);
|
94
|
-
VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
|
96
|
+
volatile VALUE name = RARRAY_AREF(association, 0);
|
97
|
+
volatile VALUE association_descriptor = RARRAY_AREF(association, 1);
|
98
|
+
volatile VALUE value = rb_funcall(subject, rb_sym2id(name), 0);
|
95
99
|
|
96
100
|
if (value == Qnil) {
|
97
101
|
write_value(str_writer, rb_sym2str(name), value, Qnil);
|
@@ -131,15 +135,16 @@ VALUE serialize_subjects(VALUE key,
|
|
131
135
|
VALUE str_writer,
|
132
136
|
SerializationDescriptor descriptor,
|
133
137
|
VALUE context) {
|
138
|
+
long i;
|
139
|
+
|
134
140
|
rb_funcall(str_writer, push_array_id, 1, key);
|
135
141
|
|
136
142
|
if (!RB_TYPE_P(subjects, T_ARRAY)) {
|
137
143
|
subjects = rb_funcall(subjects, to_a_id, 0);
|
138
144
|
}
|
139
145
|
|
140
|
-
long i;
|
141
146
|
for (i = 0; i < RARRAY_LEN(subjects); i++) {
|
142
|
-
VALUE subject = RARRAY_AREF(subjects, i);
|
147
|
+
volatile VALUE subject = RARRAY_AREF(subjects, i);
|
143
148
|
serialize_subject(Qnil, subject, str_writer, descriptor, context);
|
144
149
|
}
|
145
150
|
|
@@ -168,11 +173,11 @@ VALUE serialize_subjects_api(VALUE klass,
|
|
168
173
|
}
|
169
174
|
|
170
175
|
void Init_panko_serializer() {
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
+
push_value_id = rb_intern("push_value");
|
177
|
+
push_array_id = rb_intern("push_array");
|
178
|
+
push_object_id = rb_intern("push_object");
|
179
|
+
pop_id = rb_intern("pop");
|
180
|
+
to_a_id = rb_intern("to_a");
|
176
181
|
|
177
182
|
VALUE mPanko = rb_define_module("Panko");
|
178
183
|
|
@@ -2,15 +2,16 @@
|
|
2
2
|
|
3
3
|
VALUE cSerializationDescriptor;
|
4
4
|
|
5
|
-
static ID context_id
|
6
|
-
static ID object_id
|
5
|
+
static ID context_id;
|
6
|
+
static ID object_id;
|
7
7
|
|
8
8
|
static void serialization_descriptor_free(void* ptr) {
|
9
|
+
SerializationDescriptor sd;
|
9
10
|
if (ptr == 0) {
|
10
11
|
return;
|
11
12
|
}
|
12
13
|
|
13
|
-
|
14
|
+
sd = (SerializationDescriptor)ptr;
|
14
15
|
sd->serializer_type = Qnil;
|
15
16
|
sd->serializer = Qnil;
|
16
17
|
sd->fields = Qnil;
|
@@ -64,7 +65,6 @@ void sd_apply_serializer_config(VALUE serializer, VALUE object, VALUE context) {
|
|
64
65
|
rb_ivar_set(serializer, context_id, context);
|
65
66
|
}
|
66
67
|
|
67
|
-
|
68
68
|
VALUE serialization_descriptor_fields_set(VALUE self, VALUE fields) {
|
69
69
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
70
70
|
|
@@ -121,6 +121,11 @@ VALUE serialization_descriptor_type_set(VALUE self, VALUE type) {
|
|
121
121
|
return Qnil;
|
122
122
|
}
|
123
123
|
|
124
|
+
VALUE serialization_descriptor_type_aref(VALUE self, VALUE type) {
|
125
|
+
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
126
|
+
return sd->serializer_type;
|
127
|
+
}
|
128
|
+
|
124
129
|
// Exposing this for testing
|
125
130
|
VALUE serialization_descriptor_build_serializer(VALUE self) {
|
126
131
|
SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
|
@@ -128,8 +133,8 @@ VALUE serialization_descriptor_build_serializer(VALUE self) {
|
|
128
133
|
}
|
129
134
|
|
130
135
|
void panko_init_serialization_descriptor(VALUE mPanko) {
|
131
|
-
|
132
|
-
|
136
|
+
object_id = rb_intern("@object");
|
137
|
+
context_id = rb_intern("@context");
|
133
138
|
|
134
139
|
cSerializationDescriptor =
|
135
140
|
rb_define_class_under(mPanko, "SerializationDescriptor", rb_cObject);
|
@@ -160,6 +165,8 @@ void panko_init_serialization_descriptor(VALUE mPanko) {
|
|
160
165
|
|
161
166
|
rb_define_method(cSerializationDescriptor,
|
162
167
|
"type=", serialization_descriptor_type_set, 1);
|
168
|
+
rb_define_method(cSerializationDescriptor,
|
169
|
+
"type", serialization_descriptor_type_aref, 0);
|
163
170
|
|
164
171
|
rb_define_method(cSerializationDescriptor, "build_serializer",
|
165
172
|
serialization_descriptor_build_serializer, 0);
|
@@ -1,65 +1,79 @@
|
|
1
1
|
#include "time_conversion.h"
|
2
2
|
|
3
|
+
const int YEAR_REGION = 1;
|
4
|
+
const int MONTH_REGION = 2;
|
5
|
+
const int DAY_REGION = 3;
|
6
|
+
const int HOUR_REGION = 4;
|
7
|
+
const int MINUTE_REGION = 5;
|
8
|
+
const int SECOND_REGION = 6;
|
9
|
+
|
3
10
|
static regex_t* iso8601_time_regex;
|
4
11
|
static regex_t* ar_iso_datetime_regex;
|
5
12
|
|
6
13
|
VALUE is_iso8601_time_string(const char* value) {
|
7
14
|
const UChar *start, *range, *end;
|
15
|
+
OnigPosition r;
|
8
16
|
|
9
17
|
const UChar* str = (const UChar*)(value);
|
10
18
|
|
11
19
|
end = str + strlen(value);
|
12
20
|
start = str;
|
13
21
|
range = end;
|
14
|
-
|
15
|
-
|
22
|
+
r = onig_search(iso8601_time_regex, str, end, start, range, NULL,
|
23
|
+
ONIG_OPTION_NONE);
|
16
24
|
|
17
25
|
return r >= 0 ? Qtrue : Qfalse;
|
18
26
|
}
|
19
27
|
|
20
|
-
void
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
long
|
25
|
-
|
28
|
+
void append_region(const char* source,
|
29
|
+
char** to,
|
30
|
+
const OnigRegion* region,
|
31
|
+
int region_number) {
|
32
|
+
long iter = 0;
|
33
|
+
long regionEnd = region->end[region_number];
|
34
|
+
for (iter = region->beg[region_number]; iter < regionEnd; iter++) {
|
35
|
+
*(*to)++ = source[iter];
|
36
|
+
}
|
26
37
|
}
|
27
38
|
|
28
39
|
VALUE iso_ar_iso_datetime_string(const char* value) {
|
29
40
|
const UChar *start, *range, *end;
|
41
|
+
OnigPosition r;
|
30
42
|
OnigRegion* region = onig_region_new();
|
43
|
+
volatile VALUE output;
|
31
44
|
|
32
45
|
const UChar* str = (const UChar*)(value);
|
33
46
|
|
34
47
|
end = str + strlen(value);
|
35
48
|
start = str;
|
36
49
|
range = end;
|
37
|
-
|
38
|
-
|
50
|
+
r = onig_search(ar_iso_datetime_regex, str, end, start, range, region,
|
51
|
+
ONIG_OPTION_NONE);
|
39
52
|
|
40
|
-
|
53
|
+
output = Qnil;
|
41
54
|
if (r >= 0) {
|
42
55
|
char buf[21] = "";
|
56
|
+
char* cur = buf;
|
43
57
|
|
44
|
-
|
45
|
-
|
58
|
+
append_region(value, &cur, region, YEAR_REGION);
|
59
|
+
*cur++ = '-';
|
46
60
|
|
47
|
-
|
48
|
-
|
61
|
+
append_region(value, &cur, region, MONTH_REGION);
|
62
|
+
*cur++ = '-';
|
49
63
|
|
50
|
-
|
51
|
-
|
64
|
+
append_region(value, &cur, region, DAY_REGION);
|
65
|
+
*cur++ = 'T';
|
52
66
|
|
53
|
-
|
54
|
-
|
67
|
+
append_region(value, &cur, region, HOUR_REGION);
|
68
|
+
*cur++ = ':';
|
55
69
|
|
56
|
-
|
57
|
-
|
70
|
+
append_region(value, &cur, region, MINUTE_REGION);
|
71
|
+
*cur++ = ':';
|
58
72
|
|
59
|
-
|
60
|
-
|
73
|
+
append_region(value, &cur, region, SECOND_REGION);
|
74
|
+
*cur++ = 'Z';
|
61
75
|
|
62
|
-
output = rb_str_new(buf,
|
76
|
+
output = rb_str_new(buf, cur - buf);
|
63
77
|
}
|
64
78
|
|
65
79
|
onig_region_free(region, 1);
|
@@ -81,12 +95,14 @@ void build_regex(OnigRegex* reg, const UChar* pattern) {
|
|
81
95
|
}
|
82
96
|
|
83
97
|
void panko_init_time(VALUE mPanko) {
|
84
|
-
const UChar*
|
98
|
+
const UChar *ISO8601_PATTERN, *AR_ISO_DATETIME_PATTERN;
|
99
|
+
|
100
|
+
ISO8601_PATTERN =
|
85
101
|
(UChar*)"^([\\+-]?\\d{4}(?!\\d{2}\\b))((-?)((0[1-9]|1[0-2])(\\3([12]\\d|0[1-9]|3[01]))?|W([0-4]\\d|5[0-2])(-?[1-7])?|(00[1-9]|0[1-9]\\d|[12]\\d{2}|3([0-5]\\d|6[1-6])))([T\\s]((([01]\\d|2[0-3])((:?)[0-5]\\d)?|24\\:?00)([\\.,]\\d+(?!:))?)?(\\17[0-5]\\d([\\.,]\\d+)?)?([zZ]|([\\+-])([01]\\d|2[0-3]):?([0-5]\\d)?)?)?)?$";
|
86
102
|
|
87
103
|
build_regex(&iso8601_time_regex, ISO8601_PATTERN);
|
88
104
|
|
89
|
-
|
105
|
+
AR_ISO_DATETIME_PATTERN =
|
90
106
|
(UChar*)"\\A(?<year>\\d{4})-(?<month>\\d\\d)-(?<mday>\\d\\d) (?<hour>\\d\\d):(?<min>\\d\\d):(?<sec>\\d\\d)(\\.(?<microsec>\\d+))?\\z";
|
91
107
|
|
92
108
|
build_regex(&ar_iso_datetime_regex, AR_ISO_DATETIME_PATTERN);
|
@@ -1,9 +1,9 @@
|
|
1
1
|
#include "type_cast.h"
|
2
2
|
#include "time_conversion.h"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
ID type_cast_from_database_id = 0;
|
5
|
+
ID to_s_id = 0;
|
6
|
+
ID to_i_id = 0;
|
7
7
|
|
8
8
|
// Caching ActiveRecord Types
|
9
9
|
static VALUE ar_string_type = Qundef;
|
@@ -23,19 +23,20 @@ static VALUE ar_pg_date_time_type = Qundef;
|
|
23
23
|
static int initiailized = 0;
|
24
24
|
|
25
25
|
VALUE cache_postgres_type_lookup(VALUE ar) {
|
26
|
-
VALUE ar_connection_adapters
|
27
|
-
|
26
|
+
VALUE ar_connection_adapters, ar_postgresql, ar_oid;
|
27
|
+
|
28
|
+
ar_connection_adapters = rb_const_get_at(ar, rb_intern("ConnectionAdapters"));
|
28
29
|
if (ar_connection_adapters == Qundef) {
|
29
30
|
return Qfalse;
|
30
31
|
}
|
31
32
|
|
32
|
-
|
33
|
+
ar_postgresql =
|
33
34
|
rb_const_get_at(ar_connection_adapters, rb_intern("PostgreSQL"));
|
34
35
|
if (ar_postgresql == Qundef) {
|
35
36
|
return Qfalse;
|
36
37
|
}
|
37
38
|
|
38
|
-
|
39
|
+
ar_oid = rb_const_get_at(ar_postgresql, rb_intern("OID"));
|
39
40
|
if (ar_oid == Qundef) {
|
40
41
|
return Qfalse;
|
41
42
|
}
|
@@ -50,14 +51,16 @@ VALUE cache_postgres_type_lookup(VALUE ar) {
|
|
50
51
|
}
|
51
52
|
|
52
53
|
VALUE cache_time_zone_type_lookup(VALUE ar) {
|
54
|
+
VALUE ar_attr_methods, ar_time_zone_conversion;
|
55
|
+
|
53
56
|
// ActiveRecord::AttributeMethods
|
54
|
-
|
57
|
+
ar_attr_methods = rb_const_get_at(ar, rb_intern("AttributeMethods"));
|
55
58
|
if (ar_attr_methods == Qundef) {
|
56
59
|
return Qfalse;
|
57
60
|
}
|
58
61
|
|
59
62
|
// ActiveRecord::AttributeMethods::TimeZoneConversion
|
60
|
-
|
63
|
+
ar_time_zone_conversion =
|
61
64
|
rb_const_get_at(ar_attr_methods, rb_intern("TimeZoneConversion"));
|
62
65
|
if (ar_time_zone_conversion == Qundef) {
|
63
66
|
return Qfalse;
|
@@ -76,10 +79,12 @@ void cache_type_lookup() {
|
|
76
79
|
|
77
80
|
initiailized = 1;
|
78
81
|
|
79
|
-
VALUE ar
|
82
|
+
VALUE ar, ar_type;
|
83
|
+
|
84
|
+
ar = rb_const_get_at(rb_cObject, rb_intern("ActiveRecord"));
|
80
85
|
|
81
86
|
// ActiveRecord::Type
|
82
|
-
|
87
|
+
ar_type = rb_const_get_at(ar, rb_intern("Type"));
|
83
88
|
|
84
89
|
ar_string_type = rb_const_get_at(ar_type, rb_intern("String"));
|
85
90
|
ar_text_type = rb_const_get_at(ar_type, rb_intern("Text"));
|
@@ -226,7 +231,7 @@ VALUE cast_date_time_type(VALUE value) {
|
|
226
231
|
return value;
|
227
232
|
}
|
228
233
|
|
229
|
-
VALUE iso8601_string = iso_ar_iso_datetime_string(val);
|
234
|
+
volatile VALUE iso8601_string = iso_ar_iso_datetime_string(val);
|
230
235
|
if (iso8601_string != Qnil) {
|
231
236
|
return iso8601_string;
|
232
237
|
}
|
@@ -238,8 +243,10 @@ VALUE cast_date_time_type(VALUE value) {
|
|
238
243
|
VALUE type_cast(VALUE type_metadata, VALUE value) {
|
239
244
|
cache_type_lookup();
|
240
245
|
|
241
|
-
VALUE type_klass
|
242
|
-
|
246
|
+
VALUE type_klass, typeCastedValue;
|
247
|
+
|
248
|
+
type_klass = CLASS_OF(type_metadata);
|
249
|
+
typeCastedValue = Qundef;
|
243
250
|
|
244
251
|
TypeCast typeCast;
|
245
252
|
for (typeCast = type_casts; typeCast->canCast != NULL; typeCast++) {
|
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require_relative "cache"
|
3
2
|
|
4
3
|
module Panko
|
5
4
|
class ArraySerializer
|
@@ -15,7 +14,7 @@ module Panko
|
|
15
14
|
except: options.fetch(:except, [])
|
16
15
|
}
|
17
16
|
|
18
|
-
@descriptor =
|
17
|
+
@descriptor = SerializationDescriptorBuilder.build(@each_serializer, serializer_options)
|
19
18
|
@context = options.fetch(:context, nil)
|
20
19
|
end
|
21
20
|
|
@@ -1,32 +1,25 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module Panko
|
3
3
|
module SerializationDescriptorBuilder
|
4
|
-
def self.
|
5
|
-
backend = Panko::SerializationDescriptor.new
|
6
|
-
|
4
|
+
def self.apply_filters(backend, options)
|
7
5
|
serializer_only_filters, attributes_only_filters = resolve_filters(options, :only)
|
8
6
|
serializer_except_filters, attributes_except_filters = resolve_filters(options, :except)
|
9
7
|
|
10
|
-
fields, method_fields = fields_of(serializer)
|
11
|
-
|
12
|
-
backend.type = serializer
|
13
|
-
|
14
8
|
backend.fields = apply_fields_filters(
|
15
|
-
fields,
|
9
|
+
backend.fields,
|
16
10
|
serializer_only_filters,
|
17
11
|
serializer_except_filters
|
18
12
|
)
|
19
|
-
backend.fields = backend.fields.map &:to_s
|
20
13
|
|
21
14
|
backend.method_fields = apply_fields_filters(
|
22
|
-
method_fields,
|
15
|
+
backend.method_fields,
|
23
16
|
serializer_only_filters,
|
24
17
|
serializer_except_filters
|
25
18
|
)
|
26
19
|
|
27
20
|
backend.has_many_associations = build_associations(
|
28
21
|
apply_association_filters(
|
29
|
-
|
22
|
+
backend.has_many_associations,
|
30
23
|
serializer_only_filters,
|
31
24
|
serializer_except_filters
|
32
25
|
),
|
@@ -36,44 +29,49 @@ module Panko
|
|
36
29
|
|
37
30
|
backend.has_one_associations = build_associations(
|
38
31
|
apply_association_filters(
|
39
|
-
|
32
|
+
backend.has_one_associations,
|
40
33
|
serializer_only_filters,
|
41
34
|
serializer_except_filters
|
42
35
|
),
|
43
36
|
attributes_only_filters,
|
44
37
|
attributes_except_filters
|
45
38
|
)
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.duplicate(descriptor)
|
42
|
+
backend = Panko::SerializationDescriptor.new
|
43
|
+
|
44
|
+
backend.type = descriptor.type
|
45
|
+
|
46
|
+
backend.fields = descriptor.fields
|
47
|
+
backend.method_fields = descriptor.method_fields
|
48
|
+
|
49
|
+
backend.has_many_associations = descriptor.has_many_associations
|
50
|
+
backend.has_one_associations = descriptor.has_one_associations
|
46
51
|
|
47
52
|
backend
|
48
53
|
end
|
49
54
|
|
50
|
-
def self.
|
51
|
-
|
52
|
-
method_fields = []
|
55
|
+
def self.build(serializer, options={})
|
56
|
+
backend = duplicate(serializer._descriptor)
|
53
57
|
|
54
|
-
|
55
|
-
if serializer.method_defined? attribute
|
56
|
-
method_fields << attribute
|
57
|
-
else
|
58
|
-
fields << attribute
|
59
|
-
end
|
60
|
-
end
|
58
|
+
apply_filters(backend, options)
|
61
59
|
|
62
|
-
|
60
|
+
backend
|
63
61
|
end
|
64
62
|
|
65
63
|
def self.build_associations(associations, attributes_only_filters, attributes_except_filters)
|
66
|
-
associations.
|
67
|
-
|
68
|
-
|
64
|
+
associations.each do |association|
|
65
|
+
name = association.first
|
66
|
+
descriptor = association.last
|
69
67
|
|
70
|
-
options[:only] = options.fetch(:only, []) + attributes_only_filters.fetch(association[:name], [])
|
71
|
-
options[:except] = options.fetch(:except, []) + attributes_except_filters.fetch(association[:name], [])
|
72
68
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
69
|
+
options = {
|
70
|
+
only: attributes_only_filters.fetch(name, []),
|
71
|
+
except: attributes_except_filters.fetch(name, [])
|
72
|
+
}
|
73
|
+
|
74
|
+
apply_filters(descriptor, options)
|
77
75
|
end
|
78
76
|
end
|
79
77
|
|
@@ -88,6 +86,8 @@ module Panko
|
|
88
86
|
# which mean, for the current instance use `[:a]` as filter
|
89
87
|
# and for association named `foo` use `[:b]`
|
90
88
|
|
89
|
+
return [], {} if filters.empty?
|
90
|
+
|
91
91
|
serializer_filters = filters.fetch(:instance, [])
|
92
92
|
association_filters = filters.except(:instance)
|
93
93
|
|
@@ -95,19 +95,19 @@ module Panko
|
|
95
95
|
end
|
96
96
|
|
97
97
|
def self.apply_fields_filters(fields, only, except)
|
98
|
-
return fields & only
|
99
|
-
return fields - except
|
98
|
+
return fields & only unless only.empty?
|
99
|
+
return fields - except unless except.empty?
|
100
100
|
|
101
101
|
fields
|
102
102
|
end
|
103
103
|
|
104
104
|
def self.apply_association_filters(associations, only, except)
|
105
|
-
|
106
|
-
return associations.select { |assoc| only.include?(assoc
|
105
|
+
unless only.empty?
|
106
|
+
return associations.select { |assoc| only.include?(assoc.first) }
|
107
107
|
end
|
108
108
|
|
109
|
-
|
110
|
-
return associations.reject { |assoc| except.include?(assoc
|
109
|
+
unless except.empty?
|
110
|
+
return associations.reject { |assoc| except.include?(assoc.first) }
|
111
111
|
end
|
112
112
|
|
113
113
|
associations
|
data/lib/panko/serializer.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require_relative "cache"
|
3
2
|
require_relative "serialization_descriptor"
|
4
3
|
require "oj"
|
5
4
|
|
@@ -7,33 +6,48 @@ module Panko
|
|
7
6
|
class Serializer
|
8
7
|
class << self
|
9
8
|
def inherited(base)
|
10
|
-
base.
|
11
|
-
base.
|
12
|
-
base._has_many_associations = (_has_many_associations || []).dup
|
9
|
+
base._descriptor = Panko::SerializationDescriptor.new
|
10
|
+
base._descriptor.type = base
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
base._descriptor.fields = []
|
13
|
+
base._descriptor.method_fields = []
|
14
|
+
base._descriptor.has_many_associations = []
|
15
|
+
base._descriptor.has_one_associations = []
|
17
16
|
end
|
18
17
|
|
19
|
-
attr_accessor :
|
18
|
+
attr_accessor :_descriptor
|
20
19
|
|
21
20
|
def attributes(*attrs)
|
22
|
-
@
|
21
|
+
@_descriptor.fields.push(*attrs).uniq!
|
22
|
+
end
|
23
|
+
|
24
|
+
def method_added(method)
|
25
|
+
return if @_descriptor.nil?
|
26
|
+
@_descriptor.fields.delete(method)
|
27
|
+
@_descriptor.method_fields << method
|
23
28
|
end
|
24
29
|
|
25
30
|
def has_one(name, options)
|
26
|
-
|
31
|
+
serializer_const = SerializationDescriptorBuilder.resolve_serializer(options[:serializer])
|
32
|
+
|
33
|
+
@_descriptor.has_one_associations << [
|
34
|
+
name,
|
35
|
+
SerializationDescriptorBuilder.build(serializer_const, options)
|
36
|
+
]
|
27
37
|
end
|
28
38
|
|
29
39
|
def has_many(name, options)
|
30
|
-
|
40
|
+
serializer_const = SerializationDescriptorBuilder.resolve_serializer(options[:serializer])
|
41
|
+
|
42
|
+
@_descriptor.has_many_associations << [
|
43
|
+
name,
|
44
|
+
SerializationDescriptorBuilder.build(serializer_const, options)
|
45
|
+
]
|
31
46
|
end
|
32
47
|
end
|
33
48
|
|
34
49
|
def initialize(options = {})
|
35
|
-
@descriptor =
|
36
|
-
|
50
|
+
@descriptor = SerializationDescriptorBuilder.build(self.class, options)
|
37
51
|
@context = options[:context]
|
38
52
|
end
|
39
53
|
|
data/lib/panko/version.rb
CHANGED
data/panko_serializer.gemspec
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.1.
|
4
|
+
version: 0.1.5
|
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-09-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -80,20 +80,6 @@ dependencies:
|
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: 3.2.0
|
83
|
-
- !ruby/object:Gem::Dependency
|
84
|
-
name: concurrent-ruby
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
86
|
-
requirements:
|
87
|
-
- - ">="
|
88
|
-
- !ruby/object:Gem::Version
|
89
|
-
version: '0'
|
90
|
-
type: :runtime
|
91
|
-
prerelease: false
|
92
|
-
version_requirements: !ruby/object:Gem::Requirement
|
93
|
-
requirements:
|
94
|
-
- - ">="
|
95
|
-
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
97
83
|
description:
|
98
84
|
email:
|
99
85
|
- yosy101@gmail.com
|
@@ -139,7 +125,6 @@ files:
|
|
139
125
|
- ext/panko_serializer/type_cast.h
|
140
126
|
- lib/panko.rb
|
141
127
|
- lib/panko/array_serializer.rb
|
142
|
-
- lib/panko/cache.rb
|
143
128
|
- lib/panko/response.rb
|
144
129
|
- lib/panko/serialization_descriptor.rb
|
145
130
|
- lib/panko/serializer.rb
|
@@ -165,7 +150,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
165
150
|
version: '0'
|
166
151
|
requirements: []
|
167
152
|
rubyforge_project:
|
168
|
-
rubygems_version: 2.6.
|
153
|
+
rubygems_version: 2.6.13
|
169
154
|
signing_key:
|
170
155
|
specification_version: 4
|
171
156
|
summary: Fast serialization for ActiveModel
|
data/lib/panko/cache.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
require "concurrent"
|
3
|
-
|
4
|
-
|
5
|
-
module Panko
|
6
|
-
# Serialer Descriptor Cache
|
7
|
-
class Cache
|
8
|
-
def initialize
|
9
|
-
@_cache = Concurrent::Map.new
|
10
|
-
end
|
11
|
-
|
12
|
-
def fetch(serializer_const, options)
|
13
|
-
serializer_key = build_key(serializer_const, options[:only], options[:except])
|
14
|
-
serializer = @_cache.compute_if_absent(serializer_key) {
|
15
|
-
SerializationDescriptorBuilder.build(serializer_const,
|
16
|
-
only: options.fetch(:only, []),
|
17
|
-
except: options.fetch(:except, [])
|
18
|
-
)
|
19
|
-
}
|
20
|
-
|
21
|
-
serializer
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
25
|
-
|
26
|
-
#
|
27
|
-
# Create key based on what we define unique serializer
|
28
|
-
#
|
29
|
-
def build_key(serializer_const, only, except)
|
30
|
-
[serializer_const, only, except].hash
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
CACHE = Panko::Cache.new
|
35
|
-
end
|