fast_serializer 1.1.1 → 1.1.3
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 +4 -4
- data/CHANGELOG.md +46 -0
- data/MIT_LICENSE +1 -1
- data/README.md +31 -1
- data/VERSION +1 -1
- data/fast_serializer.gemspec +29 -19
- data/lib/fast_serializer/array_serializer.rb +13 -5
- data/lib/fast_serializer/cache/active_support_cache.rb +8 -6
- data/lib/fast_serializer/cache.rb +14 -0
- data/lib/fast_serializer/serialization_context.rb +17 -2
- data/lib/fast_serializer/serialized_field.rb +32 -11
- data/lib/fast_serializer/serializer.rb +56 -29
- data/lib/fast_serializer.rb +14 -12
- metadata +18 -67
- data/.gitignore +0 -17
- data/HISTORY.md +0 -25
- data/Rakefile +0 -18
- data/spec/array_serializer_spec.rb +0 -67
- data/spec/cache/active_support_cache_spec.rb +0 -24
- data/spec/fast_serializer_spec.rb +0 -40
- data/spec/serialization_context_spec.rb +0 -32
- data/spec/serialized_field_spec.rb +0 -71
- data/spec/serializer_spec.rb +0 -177
- data/spec/spec_helper.rb +0 -18
- data/spec/support/test_models.rb +0 -74
@@ -1,71 +0,0 @@
|
|
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
|
data/spec/serializer_spec.rb
DELETED
@@ -1,177 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe FastSerializer::Serializer do
|
4
|
-
|
5
|
-
let(:model){ SimpleModel.new(:id => 1, :name => "foo", :description => "foobar", :number => 12) }
|
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 pass include and exclude options to child serializers" do
|
106
|
-
other_model = SimpleModel.new(:id => 3, :name => "other")
|
107
|
-
complex = SimpleModel.new(:id => 2, :name => :complex, :parent => model, :associations => [model, other_model])
|
108
|
-
serializer = ComplexSerializer.new(complex, :serial_number => 15, :exclude => {:associations => [:validated]}, :include => {:parent => :amount})
|
109
|
-
expect(serializer.as_json).to eq({
|
110
|
-
:id => 2, :name => :complex, :validated => false, :serial_number => 15,
|
111
|
-
:associations => [
|
112
|
-
{:id => 1, :name => "foo"},
|
113
|
-
{:id => 3, :name => "other"}
|
114
|
-
],
|
115
|
-
:parent => {:id => 1, :name => "foo", :validated => false, :amount => 12}
|
116
|
-
})
|
117
|
-
end
|
118
|
-
|
119
|
-
it "should have a scope option" do
|
120
|
-
serializer = CachedSerializer.new(model, :scope => :foo)
|
121
|
-
expect(serializer.scope).to eq :foo
|
122
|
-
end
|
123
|
-
|
124
|
-
it "should return identical serialized values for serializers on the same object and options inside the same context" do
|
125
|
-
other_model = SimpleModel.new(:id => 3, :name => "other")
|
126
|
-
complex = SimpleModel.new(:id => 2, :name => "complex", :associations => [model, other_model, model])
|
127
|
-
serializer = ComplexSerializer.new(complex)
|
128
|
-
json = serializer.as_json
|
129
|
-
expect(json[:associations][0].object_id).to_not eq json[:associations][1].object_id
|
130
|
-
expect(json[:associations][0].object_id).to eq json[:associations][2].object_id
|
131
|
-
end
|
132
|
-
|
133
|
-
it "should dump the object to JSON" do
|
134
|
-
complex = SimpleModel.new(:id => 2, :name => "complex", :parent => model, :associations => [model])
|
135
|
-
serializer = ComplexSerializer.new(complex)
|
136
|
-
expect(JSON.load(serializer.to_json)).to eq({
|
137
|
-
"id" => 2,
|
138
|
-
"name" => "complex",
|
139
|
-
"validated" => false,
|
140
|
-
"serial_number" => nil,
|
141
|
-
"associations" => [
|
142
|
-
{"id" => 1, "name" => "foo", "validated" => false}
|
143
|
-
],
|
144
|
-
"parent" => {"id" => 1, "name" => "foo", "validated" => false, "description"=>"foobar"}
|
145
|
-
})
|
146
|
-
end
|
147
|
-
|
148
|
-
it "should allow passing options for JSON dumping" do
|
149
|
-
complex = SimpleModel.new(:id => 2, :name => "complex", :parent => model, :associations => [model])
|
150
|
-
serializer = ComplexSerializer.new(complex)
|
151
|
-
expect(serializer.to_json(:pretty => true)).to be_a(String)
|
152
|
-
end
|
153
|
-
|
154
|
-
it "should expose options from the options hash by name" do
|
155
|
-
serializer = CachedSerializer.new(model, :foo => "bar")
|
156
|
-
expect(serializer.option(:foo)).to eq "bar"
|
157
|
-
expect(serializer.option(:other)).to eq nil
|
158
|
-
end
|
159
|
-
|
160
|
-
it "should return nil value for options if none are set" do
|
161
|
-
serializer = CachedSerializer.new(model, nil)
|
162
|
-
expect(serializer.option(:foo)).to eq nil
|
163
|
-
end
|
164
|
-
|
165
|
-
it "should not get into infinite loops" do
|
166
|
-
model = SimpleModel.new(:id => 1)
|
167
|
-
model.parent = model
|
168
|
-
serializer = CircularSerializer.new(model)
|
169
|
-
expect{ serializer.as_json }.to raise_error(FastSerializer::CircularReferenceError)
|
170
|
-
end
|
171
|
-
|
172
|
-
it "should allow conditionals on serialized fields" do
|
173
|
-
expect(ConditionalSerializer.new(model).as_json).to eq({:id => 1})
|
174
|
-
expect(ConditionalSerializer.new(model, :scope => :description).as_json).to eq({:id => 1, :description => "foobar"})
|
175
|
-
expect(ConditionalSerializer.new(model, :scope => :name).as_json).to eq({:id => 1, :name => "foo"})
|
176
|
-
end
|
177
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rspec'
|
2
|
-
require 'active_support/cache'
|
3
|
-
require 'active_support/cache/memory_store'
|
4
|
-
require_relative "../lib/fast_serializer"
|
5
|
-
require_relative "support/test_models"
|
6
|
-
|
7
|
-
RSpec.configure do |config|
|
8
|
-
config.run_all_when_everything_filtered = true
|
9
|
-
config.filter_run :focus
|
10
|
-
|
11
|
-
# Run specs in random order to surface order dependencies. If you find an
|
12
|
-
# order dependency and want to debug it, you can fix the order by providing
|
13
|
-
# the seed, which is printed after each run.
|
14
|
-
# --seed 1234
|
15
|
-
config.order = 'random'
|
16
|
-
|
17
|
-
config.expect_with(:rspec) { |c| c.syntax = [:should, :expect] }
|
18
|
-
end
|
data/spec/support/test_models.rb
DELETED
@@ -1,74 +0,0 @@
|
|
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, serializer_options: {include: :description}
|
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
|
65
|
-
|
66
|
-
class ConditionalSerializer < SimpleSerializer
|
67
|
-
remove :validated
|
68
|
-
serialize :description, if: -> { scope == :description }
|
69
|
-
serialize :name, if: :show_name?
|
70
|
-
|
71
|
-
def show_name?
|
72
|
-
scope == :name
|
73
|
-
end
|
74
|
-
end
|