panko_serializer 0.1.8 → 0.1.9

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