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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 438e40448a2abf780b5369b43e9c93546d2bfc0e
4
- data.tar.gz: ffe908bf3ebad77bb9d068d5bd0fdb0f504cb343
3
+ metadata.gz: e9e1120b6231ae836d11ca59c17443518f5ccb80
4
+ data.tar.gz: 2b38dd527027204628714825d38d5f8c83b0d4a9
5
5
  SHA512:
6
- metadata.gz: 73657995f001cf88eba9fdc698e233d75d34fd6b2ca26651b782f700fe1a055c5627f77b2146d115fe94d2a130cbcb363107767de69289ceb934d8b6e77f0783
7
- data.tar.gz: e222d962f5003c2af279b43c3c1a5b8a8817a998a10b2b917f394b5bbe50edece41ced1f8b1dff8dc72e7ba2c96c9aaa843d7c60b8719b0091f0f6088976074e
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 serializers user records using Panko!
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
@@ -4,6 +4,7 @@ require "active_record/connection_adapters/postgresql_adapter"
4
4
  require "active_model"
5
5
  require "active_support/all"
6
6
  require "pg"
7
+ require "oj"
7
8
 
8
9
 
9
10
  require_relative "../benchmarking_support"
@@ -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
- *type = rb_ivar_get(attribute_metadata, type_id);
52
+
53
+ if (*type == Qnil) {
54
+ *type = rb_ivar_get(attribute_metadata, type_id);
55
+ }
53
56
  }
54
57
  }
55
58
 
56
- VALUE panko_each_attribute(VALUE obj,
57
- VALUE attributes,
58
- VALUE aliases,
59
- EachAttributeFunc func,
60
- VALUE context) {
61
- volatile VALUE lazy_attribute_hash, delegate_hash;
62
- VALUE values = Qundef;
63
- VALUE types = Qundef;
64
- VALUE additional_types = Qundef;
65
- int i;
66
-
67
- lazy_attribute_hash = panko_read_lazy_attributes_hash(obj);
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
- return Qnil;
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
- delegate_hash = lazy_attribute_hash;
79
- tryToReadFromDelegateHash = true;
88
+ attributes_ctx.attributes_hash = lazy_attribute_hash;
89
+ attributes_ctx.shouldReadFromHash = true;
80
90
  } else {
81
- delegate_hash = rb_ivar_get(lazy_attribute_hash, delegate_hash_id);
82
- tryToReadFromDelegateHash = !panko_is_empty_hash(delegate_hash);
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, &additional_types,
85
- &values);
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 = !panko_is_empty_hash(additional_types);
102
+ attributes_ctx.tryToReadFromAdditionalTypes =
103
+ !panko_is_empty_hash(attributes_ctx.additional_types);
88
104
  }
89
105
 
90
- bool tryToReadFromAliases = !panko_is_empty_hash(aliases);
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
- volatile VALUE value = Qundef;
97
- volatile VALUE type_metadata = Qnil;
109
+ VALUE read_attribute(struct attributes attributes_ctx, Attribute attribute) {
110
+ VALUE member = attribute->name_str;
111
+ volatile VALUE value = Qundef;
98
112
 
99
- // First try to read from delegate hash,
100
- // If the object was create in memory `User.new(name: "Yosi")`
101
- // it won't exist in types/values
102
- if (tryToReadFromDelegateHash) {
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
- if (values != Qundef && value == Qundef) {
107
- value = rb_hash_aref(values, member);
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
- if (tryToReadFromAdditionalTypes) {
110
- type_metadata = rb_hash_aref(additional_types, member);
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
- if (tryToReadFromAliases) {
118
- volatile VALUE alias_name = rb_hash_aref(aliases, member_raw);
119
- if (alias_name != Qnil) {
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
- func(obj, member, value, type_metadata, context);
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 object,
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, Qnil);
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->fields, descriptor->aliases,
60
- panko_attributes_iter, str_writer);
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 association = RARRAY_AREF(associations, i);
57
+ volatile VALUE association_el = RARRAY_AREF(associations, i);
58
+ Association association = association_read(association_el);
73
59
 
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);
60
+ volatile VALUE value = rb_funcall(subject, association->name_id, 0);
77
61
 
78
62
  if (value == Qnil) {
79
- write_value(str_writer, rb_sym2str(name), value, Qnil);
63
+ write_value(str_writer, association->name_str, value);
80
64
  } else {
81
- serialize_subject(rb_sym2str(name), value, str_writer,
82
- sd_read(association_descriptor), context);
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 association = RARRAY_AREF(associations, i);
78
+ volatile VALUE association_el = RARRAY_AREF(associations, i);
79
+ Association association = association_read(association_el);
95
80
 
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);
81
+ volatile VALUE value = rb_funcall(subject, association->name_id, 0);
99
82
 
100
83
  if (value == Qnil) {
101
- write_value(str_writer, rb_sym2str(name), value, Qnil);
84
+ write_value(str_writer, association->name_str, value);
102
85
  } else {
103
- serialize_subjects(rb_sym2str(name), value, str_writer,
104
- sd_read(association_descriptor), context);
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
  }
@@ -1,7 +1,9 @@
1
1
  #include <ruby.h>
2
2
 
3
- #include "serialization_descriptor.h"
3
+ #include "association.h"
4
+ #include "attribute.h"
4
5
  #include "attributes_iterator.h"
6
+ #include "serialization_descriptor.h"
5
7
  #include "type_cast.h"
6
8
 
7
9
  VALUE serialize_subject(VALUE key,
@@ -5,46 +5,44 @@ VALUE cSerializationDescriptor;
5
5
  static ID context_id;
6
6
  static ID object_id;
7
7
 
8
- static void serialization_descriptor_free(void* ptr) {
9
- SerializationDescriptor sd;
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->fields = Qnil;
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 serialization_descriptor_mark(SerializationDescriptor data) {
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->fields);
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 serialization_descriptor_new(int argc, VALUE* argv, VALUE self) {
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->fields = Qnil;
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->fields = fields;
83
+ sd->attributes = attributes;
74
84
  return Qnil;
75
85
  }
76
86
 
77
- VALUE serialization_descriptor_fields_ref(VALUE self) {
87
+ VALUE sd_attributes_ref(VALUE self) {
78
88
  SerializationDescriptor sd = (SerializationDescriptor)DATA_PTR(self);
79
- return sd->fields;
89
+ return sd->attributes;
80
90
  }
81
91
 
82
- VALUE serialization_descriptor_method_fields_set(VALUE self,
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 serialization_descriptor_method_fields_ref(VALUE self) {
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 serialization_descriptor_has_one_associations_set(
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 serialization_descriptor_has_one_associations_ref(VALUE self) {
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 serialization_descriptor_has_many_associations_set(
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 serialization_descriptor_has_many_associations_ref(VALUE self) {
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 serialization_descriptor_type_set(VALUE self, VALUE type) {
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 serialization_descriptor_type_aref(VALUE self, VALUE type) {
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 serialization_descriptor_aliases_set(VALUE self, VALUE aliases) {
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 serialization_descriptor_aliases_aref(VALUE self, VALUE aliases) {
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 serialization_descriptor_build_serializer(VALUE self) {
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
- "fields=", serialization_descriptor_fields_set, 1);
160
- rb_define_method(cSerializationDescriptor, "fields",
161
- serialization_descriptor_fields_ref, 0);
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
- serialization_descriptor_method_fields_ref, 0);
175
+ sd_method_fields_ref, 0);
168
176
 
169
- rb_define_method(cSerializationDescriptor, "has_one_associations=",
170
- serialization_descriptor_has_one_associations_set, 1);
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
- serialization_descriptor_has_one_associations_ref, 0);
180
+ sd_has_one_associations_ref, 0);
173
181
 
174
- rb_define_method(cSerializationDescriptor, "has_many_associations=",
175
- serialization_descriptor_has_many_associations_set, 1);
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
- serialization_descriptor_has_many_associations_ref, 0);
185
+ sd_has_many_associations_ref, 0);
178
186
 
179
- rb_define_method(cSerializationDescriptor,
180
- "type=", serialization_descriptor_type_set, 1);
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
- "aliases=", serialization_descriptor_aliases_set, 1);
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
- serialization_descriptor_build_serializer, 0);
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 fields;
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
- ar_pg_integer_type = rb_const_get_at(ar_oid, rb_intern("Integer"));
45
- ar_pg_float_type = rb_const_get_at(ar_oid, rb_intern("Float"));
46
- ar_pg_uuid_type = rb_const_get_at(ar_oid, rb_intern("Uuid"));
47
- ar_pg_json_type = rb_const_get_at(ar_oid, rb_intern("Json"));
48
- ar_pg_date_time_type = rb_const_get_at(ar_oid, rb_intern("DateTime"));
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
- // TODO: instead of parsing the json, let's signal to "write_value"
196
- // to use "push_json" instead of "push_value"
197
- return Qundef;
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
@@ -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.fields = descriptor.fields.dup
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
- backend.has_many_associations = descriptor.has_many_associations.dup
27
- backend.has_one_associations = descriptor.has_one_associations.dup
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.aliases = descriptor.aliases.dup
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
- apply_aliases_filters(
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.first)
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.first)
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.first
102
- descriptor = association.last
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 apply_aliases_filters(aliases, only, except)
144
- return if self.aliases.nil? || self.aliases.empty?
145
-
155
+ def apply_attribute_filters!(only, except)
146
156
  unless only.empty?
147
- only.map! do |field_name|
148
- alias_name = self.aliases.key(field_name)
149
- next field_name if alias_name.nil?
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
- alias_name
161
+ only.include?(name_to_check.to_sym)
152
162
  end
153
163
  end
154
164
 
155
165
  unless except.empty?
156
- except.map! do |field_name|
157
- alias_name = self.aliases.key(field_name)
158
- next field_name if alias_name.nil?
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
- alias_name
170
+ except.include?(name_to_check.to_sym)
161
171
  end
162
172
  end
163
173
  end
@@ -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
- base._descriptor.fields = []
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.fields.push(*attrs).uniq!
24
+ @_descriptor.attributes.push(*attrs.map { |attr| Attribute.create(attr) }).uniq!
23
25
  end
24
26
 
25
27
  def aliases(aliases = {})
26
- @_descriptor.aliases = aliases
27
- attributes(*aliases.keys)
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.fields.delete(method)
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
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Panko
3
- VERSION = "0.2.2"
3
+ VERSION = "0.3.2"
4
4
  end
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
  require "panko/version"
3
+ require "panko/attribute"
3
4
  require "panko/serializer"
4
5
  require "panko/array_serializer"
5
6
  require "panko/response"
6
7
 
7
8
 
8
9
  # C Extension
10
+ require "oj"
9
11
  require "panko/panko_serializer"
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.2.2
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-10-26 00:00:00.000000000 Z
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.13
159
+ rubygems_version: 2.6.14
154
160
  signing_key:
155
161
  specification_version: 4
156
162
  summary: Fast serialization for ActiveModel