panko_serializer 0.1.8 → 0.1.9

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: 390a6c3440b79ab3748f8a6f904de26f615bdfc7
4
- data.tar.gz: 2c402a39f74eff6b0ae928c7fe31840c9c82ea66
3
+ metadata.gz: 9c6bed38967e51bd9b7902aa9b98378c47ed947e
4
+ data.tar.gz: a538bbe197fabf3220485e05c886a47d6cf22713
5
5
  SHA512:
6
- metadata.gz: bb29ceacf15b3cf3d5dbcead7ca1c61ab758d3342e1af98323f1cee69cbc53e89375bc744cefdc77c5cf909f70b18ea2fe5523cd87ec4f8c02929a2a31d53cd6
7
- data.tar.gz: f85fe9e539ce2c3e051c07139f01a3318f075102bb745cf809e31e0b75874e5af920f403dd834ad5eab0c8bc22cde77b39051bf85a0993546bd641f5c1062db2
6
+ metadata.gz: 16fb0300a61dfd66e5b364640846dd1bdb7944a707e44e904f043b332b0ab700d878de100f5828577fdc1acc1b7e0247411b99a770ca9f3aa0b7e90b6acd79d5
7
+ data.tar.gz: ec5ac08ac0c6b8f20c714d3cd2079667ef45bd0f332df9d3a2eb527221c0e147e8cc183ae972d9b7b8bff2518b6a384ed8df08e8874535e4f35b2db23f2f9c53
data/README.md CHANGED
@@ -2,13 +2,103 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/yosiat/panko_serializer.svg?branch=master)](https://travis-ci.org/yosiat/panko_serializer)
4
4
 
5
- Panko is high performance library for serializing ActiveRecord objects.
5
+ Panko is library which is inspired by ActiveModelSerializers 0.9 for serializing ActiveRecord objects to JSON strings, fast.
6
6
 
7
- ## Status
7
+ To achieve it's performance:
8
8
 
9
- Panko is not ready for official release (it's missing documentation, tests, configuration options to remove assumptions).
9
+ * Oj - Panko relies Oj since it's fast and allow to to serialize incrementally using `Oj::StringWriter`
10
+ * Serialization Descriptor - Panko computes most of the metadata ahead of time, to save time later in serialization.
11
+ * Type casting — Panko does type casting by it's self, instead of relying ActiveRecord.
10
12
 
13
+ To dig deeper about the performance choices, read [Design Choices](https://github.com/yosiat/panko_serializer/wiki/Design-Choices).
11
14
 
15
+ ### Status
16
+
17
+ Panko is not ready for official release - it's missing documentation, tests which all be done incrementally.
18
+ If you want to start using Panko to see if it helps you, you are welcome! but check it well before deploying to Production.
19
+
20
+
21
+ ## Installation
22
+
23
+ To install Panko, all you need is to add it to your Gemfile:
24
+
25
+ ```ruby
26
+ gem "panko_serializer"
27
+ ```
28
+
29
+ Then, install it on the command line:
30
+
31
+ ```
32
+ > bundle install
33
+ ```
34
+
35
+ > Since the Gem name and namespace differ, you need to require "panko" explicitly. This will be fixed before official release.
36
+
37
+
38
+
39
+ ## Usage
40
+
41
+ ### Getting Started
42
+
43
+ Let's create serializer and use it inside Rails controller.
44
+
45
+ ```ruby
46
+ class PostSerializer < Panko::Serializer
47
+ attributes :title
48
+ end
49
+
50
+ class UserSerializer < Panko::Serializer
51
+ attributes :id, :name, :age
52
+
53
+ has_many :posts, serializer: PostSerializer
54
+ end
55
+ ```
56
+
57
+ As you can see, defining serializers is simple and resembles ActiveModelSerializers 0.9,
58
+ To utilize the `UserSerializer` inside a Rails controller and serialize some users, all we need to do is:
59
+
60
+ ```ruby
61
+ class UsersController < ApplicationController
62
+ def index
63
+ users = User.includes(:posts).all
64
+ render json: Panko::ArraySerializer(users, each_serializer: UserSerializer).to_json
65
+ end
66
+ end
67
+ ```
68
+
69
+ And voila, we have endpoint which serializers user records using Panko!
70
+
71
+
72
+ ## Features
73
+
74
+ ### Attributes
75
+
76
+ Attributes allow you to specify which record attributes you want to serialize,
77
+ There are two types of attributes:
78
+
79
+ * Field - simple columns defined on the record it self.
80
+ * Virtual/Method - this allows to include properties beyond simple fields.
81
+
82
+ Example:
83
+
84
+ ```ruby
85
+ class UserSerializer < Panko::Serializer
86
+ attributes :full_name
87
+
88
+ def full_name
89
+ "#{object.first_name} #{object.last_name}"
90
+ end
91
+ end
92
+ ```
93
+
94
+ As you can see, in order to access the serialized record, you need to access `object`.
95
+ If you want to pass data to the serializer, beyond the serialized record, you can pass `context` to the serializer (both in single and array serializer).
96
+
97
+ #### TODO:
98
+ Finished feature, will add documentation sson:
99
+ - Realtionships - `has_one`, `has_many`
100
+ - Filters & Nested Filters
101
+ - Reponse bag
12
102
 
13
103
  ## License
14
104
  The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,85 @@
1
+ # frozen_string_literal: true
2
+ require_relative "./benchmarking_support"
3
+ require "rails"
4
+ require "active_model"
5
+ require "active_support"
6
+ require "active_support/json"
7
+ require "action_controller"
8
+ require "action_controller/railtie"
9
+
10
+
11
+ require "memory_profiler"
12
+ require "ruby-prof"
13
+ require "ruby-prof-flamegraph"
14
+ require "panko_serializer"
15
+
16
+ def generate_attributes(count)
17
+ (1..count).map { |i| "attr_#{i}".to_sym }
18
+ end
19
+
20
+ class LeafASerializer < Panko::Serializer
21
+ attributes *generate_attributes(5)
22
+ end
23
+
24
+ class LeafBSerializer < Panko::Serializer
25
+ attributes *generate_attributes(6)
26
+ end
27
+
28
+ class ChildrenSerializer < Panko::Serializer
29
+ attributes *generate_attributes(28)
30
+
31
+ has_one :leaf_a, serializer: LeafASerializer
32
+ has_one :leaf_b, serializer: LeafBSerializer
33
+
34
+ def attr_1
35
+ end
36
+
37
+ def attr_2
38
+ end
39
+
40
+ def attr_3
41
+ end
42
+
43
+ def attr_4
44
+ end
45
+
46
+ def attr_5
47
+ end
48
+ end
49
+
50
+ class ParentSerializer < Panko::Serializer
51
+ attributes *generate_attributes(46)
52
+
53
+ has_many :children, serializer: ChildrenSerializer
54
+
55
+
56
+ def attr_1
57
+ end
58
+
59
+ def attr_2
60
+ end
61
+
62
+ def attr_3
63
+ end
64
+
65
+ def attr_4
66
+ end
67
+ end
68
+
69
+ attrs = generate_attributes(21)
70
+ attrs << :children
71
+ filters = {
72
+ instance: attrs,
73
+ children: generate_attributes(11)
74
+ }
75
+ Benchmark.run("NoFilters") do
76
+ Panko::SerializationDescriptor.build(ParentSerializer)
77
+ end
78
+
79
+ Benchmark.run("Attribute") do
80
+ Panko::SerializationDescriptor.build(ParentSerializer, only: [:children])
81
+ end
82
+
83
+ Benchmark.run("AssociationFilters") do
84
+ Panko::SerializationDescriptor.build(ParentSerializer, only: filters)
85
+ end
@@ -62,7 +62,7 @@ void serialize_fields(VALUE subject,
62
62
  serialize_method_fields(subject, str_writer, descriptor, context);
63
63
  }
64
64
 
65
- void serialize_has_one_associatoins(VALUE subject,
65
+ void serialize_has_one_associations(VALUE subject,
66
66
  VALUE str_writer,
67
67
  VALUE context,
68
68
  SerializationDescriptor descriptor,
@@ -84,7 +84,7 @@ void serialize_has_one_associatoins(VALUE subject,
84
84
  }
85
85
  }
86
86
 
87
- void serialize_has_many_associatoins(VALUE subject,
87
+ void serialize_has_many_associations(VALUE subject,
88
88
  VALUE str_writer,
89
89
  VALUE context,
90
90
  SerializationDescriptor descriptor,
@@ -116,12 +116,12 @@ VALUE serialize_subject(VALUE key,
116
116
  serialize_fields(subject, str_writer, descriptor, context);
117
117
 
118
118
  if (RARRAY_LEN(descriptor->has_one_associations) >= 0) {
119
- serialize_has_one_associatoins(subject, str_writer, context, descriptor,
119
+ serialize_has_one_associations(subject, str_writer, context, descriptor,
120
120
  descriptor->has_one_associations);
121
121
  }
122
122
 
123
123
  if (RARRAY_LEN(descriptor->has_many_associations) >= 0) {
124
- serialize_has_many_associatoins(subject, str_writer, context, descriptor,
124
+ serialize_has_many_associations(subject, str_writer, context, descriptor,
125
125
  descriptor->has_many_associations);
126
126
  }
127
127
 
@@ -35,6 +35,8 @@ module Panko
35
35
  # Applies attributes and association filters
36
36
  #
37
37
  def apply_filters(options)
38
+ return unless options.key?(:only) || options.key?(:except)
39
+
38
40
  attributes_only_filters, associations_only_filters = resolve_filters(options, :only)
39
41
  attributes_except_filters, associations_except_filters = resolve_filters(options, :except)
40
42
 
@@ -50,36 +52,57 @@ module Panko
50
52
  attributes_except_filters
51
53
  )
52
54
 
53
- self.has_many_associations = apply_association_filters(
54
- self.has_many_associations,
55
- { attributes: attributes_only_filters, associations: associations_only_filters },
56
- { attributes: attributes_except_filters, associations: associations_except_filters }
57
- )
55
+ unless self.has_many_associations.empty?
56
+ self.has_many_associations = apply_association_filters(
57
+ self.has_many_associations,
58
+ { attributes: attributes_only_filters, associations: associations_only_filters },
59
+ { attributes: attributes_except_filters, associations: associations_except_filters }
60
+ )
61
+ end
58
62
 
59
- self.has_one_associations = apply_association_filters(
60
- self.has_one_associations,
61
- { attributes: attributes_only_filters, associations: associations_only_filters },
62
- { attributes: attributes_except_filters, associations: associations_except_filters }
63
- )
63
+ unless self.has_one_associations.empty?
64
+ self.has_one_associations = apply_association_filters(
65
+ self.has_one_associations,
66
+ { attributes: attributes_only_filters, associations: associations_only_filters },
67
+ { attributes: attributes_except_filters, associations: associations_except_filters }
68
+ )
69
+ end
64
70
  end
65
71
 
66
72
  def apply_association_filters(associations, only_filters, except_filters)
67
- attributes_only_filters = only_filters[:attributes]
68
- attributes_only_filters = associations.map(&:first) if attributes_only_filters.empty?
73
+ attributes_only_filters = only_filters[:attributes] || []
74
+ unless attributes_only_filters.empty?
75
+ associations.select! do |association|
76
+ attributes_only_filters.include?(association.first)
77
+ end
78
+ end
79
+
69
80
  attributes_except_filters = except_filters[:attributes] || []
81
+ unless attributes_except_filters.empty?
82
+ associations.reject! do |association|
83
+ attributes_except_filters.include?(association.first)
84
+ end
85
+ end
86
+
87
+ associations_only_filters = only_filters[:associations]
88
+ associations_except_filters = except_filters[:associations]
70
89
 
90
+ if associations_only_filters.empty? && associations_except_filters.empty?
91
+ return associations
92
+ end
71
93
 
72
94
  associations.map do |association|
73
95
  name = association.first
74
- next if attributes_except_filters.include? name
75
- next unless attributes_only_filters.include? name
76
-
77
96
  descriptor = association.last
78
97
 
79
- descriptor.apply_filters({
80
- only: only_filters[:associations].fetch(name, []),
81
- except: except_filters[:associations].fetch(name, [])
82
- })
98
+ only_filter = associations_only_filters[name]
99
+ except_filter = associations_except_filters[name]
100
+
101
+ filters = {}
102
+ filters[:only] = only_filter unless only_filter.nil?
103
+ filters[:except] = except_filter unless except_filter.nil?
104
+
105
+ descriptor.apply_filters(filters) unless filters.empty?
83
106
 
84
107
  association
85
108
  end.compact
data/lib/panko/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Panko
3
- VERSION = "0.1.8"
3
+ VERSION = "0.1.9"
4
4
  end
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.8
4
+ version: 0.1.9
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-09-29 00:00:00.000000000 Z
11
+ date: 2017-10-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -105,6 +105,7 @@ files:
105
105
  - benchmarks/bm_controller.rb
106
106
  - benchmarks/bm_panko_json.rb
107
107
  - benchmarks/bm_panko_object.rb
108
+ - benchmarks/bm_serialization_descriptor.rb
108
109
  - benchmarks/profile.rb
109
110
  - benchmarks/sanity.rb
110
111
  - benchmarks/setup.rb