fast_serializer 1.0.0

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.
@@ -0,0 +1,28 @@
1
+ require 'spec_helper'
2
+
3
+ describe FastSerializer do
4
+
5
+ it "should be able to set and get a global cache" do
6
+ expect(FastSerializer.cache).to eq nil
7
+ begin
8
+ FastSerializer.cache = :mock
9
+ expect(FastSerializer.cache).to eq :mock
10
+ ensure
11
+ FastSerializer.cache = nil
12
+ end
13
+ expect(FastSerializer.cache).to eq nil
14
+ end
15
+
16
+ it "should set the cache to Rails.cache with the value :rails" do
17
+ begin
18
+ rails = double(:cache => :rails_cache)
19
+ stub_const("Rails", rails)
20
+ FastSerializer.cache = :rails
21
+ expect(FastSerializer.cache).to be_a FastSerializer::Cache::ActiveSupportCache
22
+ expect(FastSerializer.cache.cache).to eq :rails_cache
23
+ ensure
24
+ FastSerializer.cache = nil
25
+ end
26
+ end
27
+
28
+ end
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe FastSerializer::SerializationContext do
4
+
5
+ it "should get a single context only within a block" do
6
+ expect(FastSerializer::SerializationContext.current).to eq nil
7
+ FastSerializer::SerializationContext.use do
8
+ context = FastSerializer::SerializationContext.current
9
+ expect(FastSerializer::SerializationContext.current).to_not eq nil
10
+ FastSerializer::SerializationContext.use do
11
+ expect(FastSerializer::SerializationContext.current).to eq context
12
+ end
13
+ expect(FastSerializer::SerializationContext.current).to eq context
14
+ end
15
+ expect(FastSerializer::SerializationContext.current).to eq nil
16
+ end
17
+
18
+ it "should create serializers and reload them from cache with the same object and options" do
19
+ context = FastSerializer::SerializationContext.new
20
+ object = SimpleModel.new(:id => 1, :name => "foo")
21
+
22
+ serializer = context.load(SimpleSerializer, object, :count => 1)
23
+ expect(serializer).to be_a SimpleSerializer
24
+ expect(serializer.object).to eq object
25
+ expect(serializer.options).to eq(:count => 1)
26
+
27
+ expect(context.load(SimpleSerializer, object, :count => 1).object_id).to eq serializer.object_id
28
+ expect(context.load(SimpleSerializer, SimpleModel.new(:id => 2, :name => "bar"), :count => 1).object_id).to_not eq serializer.object_id
29
+ expect(context.load(SimpleSerializer, object, :count => 2).object_id).to_not eq serializer.object_id
30
+ end
31
+
32
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ describe FastSerializer::SerializedField do
4
+
5
+ let(:field){ FastSerializer::SerializedField.new(:test) }
6
+ let(:model){ SimpleModel.new(:id => 1, :name => "foo") }
7
+
8
+ it "should integers" do
9
+ expect(field.serialize(1)).to eq 1
10
+ end
11
+
12
+ it "should serialize floats" do
13
+ expect(field.serialize(1.5)).to eq 1.5
14
+ end
15
+
16
+ it "should serialize strings" do
17
+ expect(field.serialize("foo")).to eq "foo"
18
+ end
19
+
20
+ it "should serialize symbols" do
21
+ expect(field.serialize(:foo)).to eq :foo
22
+ end
23
+
24
+ it "should serialize nil" do
25
+ expect(field.serialize(nil)).to eq nil
26
+ end
27
+
28
+ it "should serialize booleans" do
29
+ expect(field.serialize(true)).to eq true
30
+ expect(field.serialize(false)).to eq false
31
+ end
32
+
33
+ it "should serialize times" do
34
+ time = Time.now
35
+ expect(field.serialize(time)).to eq time
36
+ end
37
+
38
+ it "should serialize dates" do
39
+ date = Date.today
40
+ expect(field.serialize(date)).to eq date
41
+ end
42
+
43
+ it "should serialize a field using a specified serializer" do
44
+ field = FastSerializer::SerializedField.new(:test, serializer: SimpleSerializer)
45
+ expect(field.serialize(model)).to eq({:id => 1, :name => "foo", :validated => false})
46
+ end
47
+
48
+ it "should serialize an enumerable field using a specified serializer" do
49
+ field = FastSerializer::SerializedField.new(:test, serializer: SimpleSerializer, enumerable: true)
50
+ expect(field.serialize(model)).to eq([{:id => 1, :name => "foo", :validated => false}])
51
+ end
52
+
53
+ it "should serialize a field value by calling as_json on the field" do
54
+ expect(field.serialize(model)).to eq({:id => 1, :name => "foo", :description => nil, :number => nil})
55
+ end
56
+
57
+ it "should serialize a hash of objects" do
58
+ expect(field.serialize(:name => "Test", :object => model)).to eq({
59
+ :name => "Test",
60
+ :object => {:id => 1, :name => "foo", :description => nil, :number => nil}
61
+ })
62
+ end
63
+
64
+ it "should serialize an array of objects" do
65
+ expect(field.serialize([model, model])).to eq([
66
+ {:id => 1, :name => "foo", :description => nil, :number => nil},
67
+ {:id => 1, :name => "foo", :description => nil, :number => nil}
68
+ ])
69
+ end
70
+
71
+ end
@@ -0,0 +1,146 @@
1
+ require 'spec_helper'
2
+
3
+ describe FastSerializer::Serializer do
4
+
5
+ let(:model){ SimpleModel.new(:id => 1, :name => "foo", :description => "foobar") }
6
+
7
+ it "should serialize object to JSON compatible format" do
8
+ serializer = SimpleSerializer.new(model)
9
+ expect(serializer.as_json).to eq({:id => 1, :name => "foo", :validated => false})
10
+ expect(serializer.to_hash).to eq({:id => 1, :name => "foo", :validated => false})
11
+ expect(serializer.to_h).to eq({:id => 1, :name => "foo", :validated => false})
12
+ end
13
+
14
+ it "should serialize nil as nil" do
15
+ expect(SimpleSerializer.new(nil).as_json).to eq nil
16
+ end
17
+
18
+ it "should include optional fields only if included in the options" do
19
+ expect(SimpleSerializer.new(model).as_json).to eq({:id => 1, :name => "foo", :validated => false})
20
+ expect(SimpleSerializer.new(model, :include => :nothing).as_json).to eq({:id => 1, :name => "foo", :validated => false})
21
+ expect(SimpleSerializer.new(model, :include => :description).as_json).to eq({:id => 1, :name => "foo", :validated => false, :description => "foobar"})
22
+ expect(SimpleSerializer.new(model, :include => ["description"]).as_json).to eq({:id => 1, :name => "foo", :validated => false, :description => "foobar"})
23
+ end
24
+
25
+ it "should exclude specified fields" do
26
+ expect(SimpleSerializer.new(model, :exclude => :name).as_json).to eq({:id => 1, :validated => false})
27
+ expect(SimpleSerializer.new(model, :exclude => ["id", "validated"]).as_json).to eq({:name => "foo"})
28
+ end
29
+
30
+ it "should allow aliasing fields" do
31
+ number_model = SimpleModel.new(:number => 50.5)
32
+ expect(SimpleSerializer.new(number_model, :include => :amount).as_json).to eq({:id => nil, :name => nil, :validated => false, :amount => 50.5})
33
+ end
34
+
35
+ it "should pull cached serializers from a cache" do
36
+ serializer = SimpleSerializer.new(model)
37
+ cached_serializer = CachedSerializer.new(model)
38
+
39
+ expect(serializer.cacheable?).to eq false
40
+ expect(cached_serializer.cacheable?).to eq true
41
+
42
+ expect(serializer.cache_ttl).to eq nil
43
+ expect(cached_serializer.cache_ttl).to eq 2
44
+
45
+ expect(cached_serializer.as_json).to eq serializer.as_json
46
+ expect(cached_serializer.as_json.object_id).to eq cached_serializer.as_json.object_id
47
+ end
48
+
49
+ it "should allow setting cache and ttl on parent serializers" do
50
+ class SubCacheSerializer1 < CachedSerializer
51
+ self.cache_ttl = 5
52
+ self.cache = :mock
53
+ end
54
+
55
+ class SubCacheSerializer2 < CachedSerializer
56
+ end
57
+
58
+ expect(SubCacheSerializer1.cacheable?).to eq true
59
+ expect(SubCacheSerializer2.cacheable?).to eq true
60
+
61
+ expect(SubCacheSerializer1.cache).to eq :mock
62
+ expect(SubCacheSerializer2.cache).to eq CachedSerializer.cache
63
+
64
+ expect(SubCacheSerializer1.cache_ttl).to eq 5
65
+ expect(SubCacheSerializer2.cache_ttl).to eq 2
66
+ end
67
+
68
+ it "should allow setting cache and ttl on instances" do
69
+ serializer = SimpleSerializer.new(model, :cacheable => true, :cache => :mock, :cache_ttl => 10)
70
+ expect(serializer.cacheable?).to eq true
71
+ expect(serializer.cache).to eq :mock
72
+ expect(serializer.cache_ttl).to eq 10
73
+ end
74
+
75
+ it "should get the cache from the global setting by default" do
76
+ class SubCacheSerializerGlobalInheritTest
77
+ include FastSerializer::Serializer
78
+ self.cacheable
79
+ end
80
+
81
+ expect(SubCacheSerializerGlobalInheritTest.cache).to eq nil
82
+ allow(FastSerializer).to receive_messages(:cache => :mock)
83
+ expect(SubCacheSerializerGlobalInheritTest.cache).to eq :mock
84
+ end
85
+
86
+ it "should not break on cached serializers if no cache is set" do
87
+ serializer = CachedSerializer.new(model, :cache => nil)
88
+ expect(serializer.as_json).to eq({:id => 1, :name => "foo", :validated => false})
89
+ end
90
+
91
+ it "should serialize complex objects" do
92
+ other_model = SimpleModel.new(:id => 3, :name => "other")
93
+ complex = SimpleModel.new(:id => 2, :name => :complex, :parent => model, :associations => [model, other_model])
94
+ serializer = ComplexSerializer.new(complex, :serial_number => 15)
95
+ expect(serializer.as_json).to eq({
96
+ :id => 2, :name => :complex, :validated => false, :serial_number => 15,
97
+ :associations => [
98
+ {:id => 1, :name => "foo", :validated => false},
99
+ {:id => 3, :name => "other", :validated => false}
100
+ ],
101
+ :parent => {:id => 1, :name => "foo", :validated => false}
102
+ })
103
+ end
104
+
105
+ it "should return identical serialized values for serializers on the same object and options inside the same context" do
106
+ other_model = SimpleModel.new(:id => 3, :name => "other")
107
+ complex = SimpleModel.new(:id => 2, :name => "complex", :associations => [model, other_model, model])
108
+ serializer = ComplexSerializer.new(complex)
109
+ json = serializer.as_json
110
+ expect(json[:associations][0].object_id).to_not eq json[:associations][1].object_id
111
+ expect(json[:associations][0].object_id).to eq json[:associations][2].object_id
112
+ end
113
+
114
+ it "should dump the object to JSON" do
115
+ complex = SimpleModel.new(:id => 2, :name => "complex", :parent => model, :associations => [model])
116
+ serializer = ComplexSerializer.new(complex)
117
+ expect(JSON.load(serializer.to_json)).to eq({
118
+ "id" => 2,
119
+ "name" => "complex",
120
+ "validated" => false,
121
+ "serial_number" => nil,
122
+ "associations" => [
123
+ {"id" => 1, "name" => "foo", "validated" => false}
124
+ ],
125
+ "parent" => {"id" => 1, "name" => "foo", "validated" => false}
126
+ })
127
+ end
128
+
129
+ it "should expose options from the options hash by name" do
130
+ serializer = CachedSerializer.new(model, :foo => "bar")
131
+ expect(serializer.option(:foo)).to eq "bar"
132
+ expect(serializer.option(:other)).to eq nil
133
+ end
134
+
135
+ it "should return nil value for options if none are set" do
136
+ serializer = CachedSerializer.new(model, nil)
137
+ expect(serializer.option(:foo)).to eq nil
138
+ end
139
+
140
+ it "should not get into infinite loops" do
141
+ model = SimpleModel.new(:id => 1)
142
+ model.parent = model
143
+ serializer = CircularSerializer.new(model)
144
+ expect{ serializer.as_json }.to raise_error(FastSerializer::CircularReferenceError)
145
+ end
146
+ end
@@ -0,0 +1,16 @@
1
+ require 'rspec'
2
+ require_relative "../lib/fast_serializer"
3
+ require_relative "support/test_models"
4
+
5
+ RSpec.configure do |config|
6
+ config.run_all_when_everything_filtered = true
7
+ config.filter_run :focus
8
+
9
+ # Run specs in random order to surface order dependencies. If you find an
10
+ # order dependency and want to debug it, you can fix the order by providing
11
+ # the seed, which is printed after each run.
12
+ # --seed 1234
13
+ config.order = 'random'
14
+
15
+ config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
16
+ end
@@ -0,0 +1,64 @@
1
+ class SimpleModel
2
+ attr_reader :id, :name, :description, :associations, :number
3
+ attr_accessor :parent
4
+
5
+ def initialize(attributes = {})
6
+ @id = attributes[:id]
7
+ @name = attributes[:name]
8
+ @description = attributes[:description]
9
+ @validated = attributes[:validated]
10
+ @associations = attributes[:associations]
11
+ @parent = attributes[:parent]
12
+ @number = attributes[:number]
13
+ end
14
+
15
+ def validated?
16
+ !!@validated
17
+ end
18
+
19
+ def as_json(*args)
20
+ {:id => @id, :name => @name, :description => @description, :number => @number}
21
+ end
22
+ end
23
+
24
+ class TestCache < FastSerializer::Cache
25
+ def initialize
26
+ @cache = {}
27
+ end
28
+
29
+ def fetch(serializer, ttl)
30
+ val = @cache[serializer.cache_key]
31
+ unless val
32
+ val = yield
33
+ @cache[serializer.cache_key] = val
34
+ end
35
+ val
36
+ end
37
+ end
38
+
39
+ class SimpleSerializer
40
+ include FastSerializer::Serializer
41
+
42
+ serialize :id, :name, :validated?
43
+ serialize :description, optional: true
44
+ serialize :number, as: :amount, optional: true
45
+ end
46
+
47
+ class CachedSerializer < SimpleSerializer
48
+ cacheable ttl: 2, cache: TestCache.new
49
+ end
50
+
51
+ class ComplexSerializer < SimpleSerializer
52
+ serialize :serial_number, delegate: false
53
+ serialize :associations, delegate: true, serializer: CachedSerializer, enumerable: true
54
+ serialize :parent, delegate: true, serializer: SimpleSerializer
55
+
56
+ def serial_number
57
+ option(:serial_number)
58
+ end
59
+ end
60
+
61
+ class CircularSerializer < SimpleSerializer
62
+ remove :name, :validated
63
+ serialize :parent, serializer: self
64
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fast_serializer
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - We Heart It
8
+ - Brian Durand
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-03-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: bundler
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - "~>"
19
+ - !ruby/object:Gem::Version
20
+ version: '1.3'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - "~>"
26
+ - !ruby/object:Gem::Version
27
+ version: '1.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: rspec
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - "~>"
47
+ - !ruby/object:Gem::Version
48
+ version: '3.0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - "~>"
54
+ - !ruby/object:Gem::Version
55
+ version: '3.0'
56
+ description: Super fast object serialization for API's combining a simple DSL with
57
+ many optimizations under the hood.
58
+ email:
59
+ - dev@weheartit.com
60
+ - bbdurand@gmail.com
61
+ executables: []
62
+ extensions: []
63
+ extra_rdoc_files: []
64
+ files:
65
+ - ".gitignore"
66
+ - HISTORY.txt
67
+ - MIT_LICENSE
68
+ - README.md
69
+ - Rakefile
70
+ - VERSION
71
+ - fast_serializer.gemspec
72
+ - lib/fast_serializer.rb
73
+ - lib/fast_serializer/array_serializer.rb
74
+ - lib/fast_serializer/cache.rb
75
+ - lib/fast_serializer/cache/active_support_cache.rb
76
+ - lib/fast_serializer/serialization_context.rb
77
+ - lib/fast_serializer/serialized_field.rb
78
+ - lib/fast_serializer/serializer.rb
79
+ - spec/array_serializer_spec.rb
80
+ - spec/fast_serializer_spec.rb
81
+ - spec/serialization_context_spec.rb
82
+ - spec/serialized_field_spec.rb
83
+ - spec/serializer_spec.rb
84
+ - spec/spec_helper.rb
85
+ - spec/support/test_models.rb
86
+ homepage: https://github.com/weheartit/fast_serializer
87
+ licenses:
88
+ - MIT
89
+ metadata: {}
90
+ post_install_message:
91
+ rdoc_options: []
92
+ require_paths:
93
+ - lib
94
+ required_ruby_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ">="
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ requirements: []
105
+ rubyforge_project:
106
+ rubygems_version: 2.4.5
107
+ signing_key:
108
+ specification_version: 4
109
+ summary: Super fast object serialization for API's.
110
+ test_files:
111
+ - spec/array_serializer_spec.rb
112
+ - spec/fast_serializer_spec.rb
113
+ - spec/serialization_context_spec.rb
114
+ - spec/serialized_field_spec.rb
115
+ - spec/serializer_spec.rb
116
+ - spec/spec_helper.rb
117
+ - spec/support/test_models.rb