fast_serializer 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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