panko_serializer 0.2.2 → 0.3.2

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 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