restpack_serializer 0.4.9 → 0.4.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +15 -15
- data/lib/restpack_serializer.rb +1 -0
- data/lib/restpack_serializer/result.rb +53 -0
- data/lib/restpack_serializer/serializable/paging.rb +8 -38
- data/lib/restpack_serializer/version.rb +1 -1
- data/spec/result_spec.rb +51 -0
- data/spec/serializable/paging_spec.rb +4 -4
- data/spec/serializable/resource_spec.rb +2 -2
- data/spec/serializable/side_loading/side_loading_spec.rb +1 -1
- metadata +6 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2dfadef3b0cdb67cc4f5a4b659448218f230bcba
|
4
|
+
data.tar.gz: 5f83c011e2b01d6c539250e289661fde606d1d55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b13cf34cf4f9e0a4cda766e356d6fc69e249eb9944de45f3ad5e489e9fda2f9506b377540f9a798782aa5cf230ecdaa5f966df884040b98b62afe5790689266d
|
7
|
+
data.tar.gz: 0d6c339987850df7d6a3e8dfe2a3e683eb2df3277878c0e98eaf613a0677f1da91eff1007bce939e9d8092d5ca976d9694143676209fd94f2406a682edc28492
|
data/README.md
CHANGED
@@ -64,8 +64,8 @@ end
|
|
64
64
|
|
65
65
|
These endpoint will live at URLs such as `/albums` and `/albums/142857`:
|
66
66
|
|
67
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json
|
68
|
-
* http://restpack-serializer-sample.herokuapp.com/albums/4.json
|
67
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json
|
68
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums/4.json
|
69
69
|
|
70
70
|
Both `page` and `resource` methods take an optional scope argument allowing us to enforce arbitrary constraints:
|
71
71
|
|
@@ -77,12 +77,12 @@ AlbumSerializer.page(params, Albums.where("year < 1950"))
|
|
77
77
|
|
78
78
|
Collections are paged by default. `page` and `page_size` parameters are available:
|
79
79
|
|
80
|
-
* http://restpack-serializer-sample.herokuapp.com/songs.json?page=2
|
81
|
-
* http://restpack-serializer-sample.herokuapp.com/songs.json?page=2&page_size=3
|
80
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?page=2
|
81
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?page=2&page_size=3
|
82
82
|
|
83
83
|
Paging details are included in a `meta` attribute:
|
84
84
|
|
85
|
-
http://restpack-serializer-sample.herokuapp.com/songs.json?page=2&page_size=3 yields:
|
85
|
+
http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?page=2&page_size=3 yields:
|
86
86
|
|
87
87
|
```javascript
|
88
88
|
{
|
@@ -163,11 +163,11 @@ In this example, we are allowing related `songs` and `artists` to be included in
|
|
163
163
|
|
164
164
|
#### No side-loads
|
165
165
|
|
166
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json
|
166
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json
|
167
167
|
|
168
168
|
#### Side-load related Artists
|
169
169
|
|
170
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?include=artists
|
170
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?include=artists
|
171
171
|
|
172
172
|
which yields:
|
173
173
|
|
@@ -269,15 +269,15 @@ which yields:
|
|
269
269
|
|
270
270
|
#### Side-load related Songs
|
271
271
|
|
272
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?include=songs
|
272
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?include=songs
|
273
273
|
|
274
274
|
An album `:has_many` songs, so the side-loaded songs are paged. The `meta.songs` includes `previous_href` and `next_href` which point to the previous and next page of this side-loaded data. These URLs take the form:
|
275
275
|
|
276
|
-
* http://restpack-serializer-sample.herokuapp.com/songs.json?album_ids=1,2,3,4&page=2
|
276
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/songs.json?album_ids=1,2,3,4&page=2
|
277
277
|
|
278
278
|
#### Side-load related Artists and Songs
|
279
279
|
|
280
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?include=artists,songs
|
280
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?include=artists,songs
|
281
281
|
|
282
282
|
## Filtering
|
283
283
|
|
@@ -285,13 +285,13 @@ Simple filtering based on primary and foreign keys is supported by default:
|
|
285
285
|
|
286
286
|
#### By primary key:
|
287
287
|
|
288
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?id=1
|
289
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?ids=1,2,4
|
288
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?id=1
|
289
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?ids=1,2,4
|
290
290
|
|
291
291
|
#### By foreign key:
|
292
292
|
|
293
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?artist_id=1
|
294
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?artist_ids=2,3
|
293
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?artist_id=1
|
294
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?artist_ids=2,3
|
295
295
|
|
296
296
|
#### Custom filters:
|
297
297
|
|
@@ -308,4 +308,4 @@ end
|
|
308
308
|
|
309
309
|
Side-loading is available when filtering:
|
310
310
|
|
311
|
-
* http://restpack-serializer-sample.herokuapp.com/albums.json?artist_ids=2,3&include=artists,songs
|
311
|
+
* http://restpack-serializer-sample.herokuapp.com/api/v1/albums.json?artist_ids=2,3&include=artists,songs
|
data/lib/restpack_serializer.rb
CHANGED
@@ -0,0 +1,53 @@
|
|
1
|
+
module RestPack::Serializer
|
2
|
+
class Result
|
3
|
+
attr_accessor :resources, :meta, :links
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@resources = {}
|
7
|
+
@meta = {}
|
8
|
+
@links = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def serialize
|
12
|
+
result = {}
|
13
|
+
|
14
|
+
result[:meta] = @meta unless @meta.empty?
|
15
|
+
result[:links] = @links unless @links.empty?
|
16
|
+
|
17
|
+
unless @resources.empty?
|
18
|
+
inject_to_many_links!
|
19
|
+
result[@resources.keys.first] = @resources.values.first
|
20
|
+
|
21
|
+
linked = @resources.except(@resources.keys.first)
|
22
|
+
result[:linked] = linked unless linked.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
result
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def inject_to_many_links! #find and inject to_many links from related @resources
|
31
|
+
@resources.keys.each do |key|
|
32
|
+
@resources[key].each do |item|
|
33
|
+
if item[:links]
|
34
|
+
item[:links].each do |link_key, link_value|
|
35
|
+
unless link_value.is_a? Array
|
36
|
+
plural_linked_key = "#{link_key}s".to_sym
|
37
|
+
|
38
|
+
if @resources[plural_linked_key]
|
39
|
+
linked_resource = @resources[plural_linked_key].find { |i| i[:id] == link_value }
|
40
|
+
if linked_resource
|
41
|
+
linked_resource[:links] ||= {}
|
42
|
+
linked_resource[:links][key] ||= []
|
43
|
+
linked_resource[:links][key] << item[:id]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -12,24 +12,21 @@ module RestPack::Serializer::Paging
|
|
12
12
|
per_page: options.page_size
|
13
13
|
)
|
14
14
|
|
15
|
-
result =
|
16
|
-
|
17
|
-
|
18
|
-
self.key => serialize_meta(page, options)
|
19
|
-
}
|
20
|
-
}
|
15
|
+
result = RestPack::Serializer::Result.new
|
16
|
+
result.resources[self.key] = serialize_page(page)
|
17
|
+
result.meta[self.key] = serialize_meta(page, options)
|
21
18
|
|
22
19
|
if options.include_links
|
23
|
-
result
|
20
|
+
result.links = self.links
|
24
21
|
Array(RestPack::Serializer::Factory.create(*options.include)).each do |serializer|
|
25
|
-
result
|
22
|
+
result.links.merge! serializer.class.links
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
26
|
side_load_data = side_loads(page, options)
|
30
|
-
result
|
31
|
-
result
|
32
|
-
|
27
|
+
result.meta.merge!(side_load_data[:meta] || {})
|
28
|
+
result.resources.merge! side_load_data.except(:meta)
|
29
|
+
result.serialize
|
33
30
|
end
|
34
31
|
|
35
32
|
private
|
@@ -69,32 +66,5 @@ module RestPack::Serializer::Paging
|
|
69
66
|
url += '?' + params.join('&') if params.any?
|
70
67
|
url
|
71
68
|
end
|
72
|
-
|
73
|
-
def inject_to_many_links(result) #TODO: GJ: extract this into a result class and refactor
|
74
|
-
keys = result.keys - [:meta, :links]
|
75
|
-
|
76
|
-
keys.each do |key|
|
77
|
-
result[key].each do |item|
|
78
|
-
if item[:links]
|
79
|
-
item[:links].each do |link_key, link_value|
|
80
|
-
unless link_value.is_a? Array
|
81
|
-
plural_linked_key = "#{link_key}s".to_sym
|
82
|
-
|
83
|
-
if result[plural_linked_key]
|
84
|
-
linked_resource = result[plural_linked_key].find { |i| i[:id] == link_value }
|
85
|
-
if linked_resource
|
86
|
-
linked_resource[:links] ||= {}
|
87
|
-
linked_resource[:links][key] ||= []
|
88
|
-
linked_resource[:links][key] << item[:id]
|
89
|
-
end
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
result
|
98
|
-
end
|
99
69
|
end
|
100
70
|
end
|
data/spec/result_spec.rb
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RestPack::Serializer::Result do
|
4
|
+
context 'a new instance' do
|
5
|
+
it 'has defaults' do
|
6
|
+
subject.resources.should == {}
|
7
|
+
subject.meta.should == {}
|
8
|
+
subject.links.should == {}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
context 'when serializing' do
|
13
|
+
let(:result) { subject.serialize }
|
14
|
+
context 'in jsonapi.org format' do
|
15
|
+
context 'an empty result' do
|
16
|
+
it 'returns an empty result' do
|
17
|
+
result.should == {}
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'a simple list of resources' do
|
22
|
+
before do
|
23
|
+
subject.resources[:albums] = [{ name: 'Album 1' }, { name: 'Album 2'}]
|
24
|
+
subject.meta[:albums] = { count: 2 }
|
25
|
+
subject.links['albums.songs'] = { href: 'songs.json', type: 'songs' }
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'returns correct jsonapi.org format' do
|
29
|
+
result[:albums].should == subject.resources[:albums]
|
30
|
+
result[:meta].should == subject.meta
|
31
|
+
result[:links].should == subject.links
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context 'a list with side-loaded resources' do
|
36
|
+
before do
|
37
|
+
subject.resources[:albums] = [{ id: '1', name: 'AMOK'}]
|
38
|
+
subject.resources[:songs] = [{ id: '91', name: 'Before Your Very Eyes...', links: { album: '1' }}]
|
39
|
+
subject.links['albums.songs'] = { type: 'songs', href: '/api/v1/songs?album_id={albums.id}' }
|
40
|
+
subject.links['songs.album'] = { type: 'albums', href: '/api/v1/albums/{songs.album}' }
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns correct jsonapi.org format, including injected to_many links' do
|
44
|
+
result[:albums].should == [{ id: '1', name: 'AMOK', links: { songs: ['91'] } }]
|
45
|
+
result[:links].should == subject.links
|
46
|
+
result[:linked][:songs].should == subject.resources[:songs]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -101,7 +101,7 @@ describe RestPack::Serializer::Paging do
|
|
101
101
|
let(:params) { { include: 'albums' } }
|
102
102
|
|
103
103
|
it "includes side-loaded models" do
|
104
|
-
page[:albums].should_not == nil
|
104
|
+
page[:linked][:albums].should_not == nil
|
105
105
|
end
|
106
106
|
|
107
107
|
it "includes the side-loads in the main meta data" do
|
@@ -118,7 +118,7 @@ describe RestPack::Serializer::Paging do
|
|
118
118
|
song[:links][:album].should == song_model.album_id.to_s
|
119
119
|
song[:links][:artist].should == song_model.artist_id.to_s
|
120
120
|
|
121
|
-
album = page[:albums].first
|
121
|
+
album = page[:linked][:albums].first
|
122
122
|
album_model = MyApp::Album.find(album[:id])
|
123
123
|
|
124
124
|
album[:links][:artist].should == album_model.artist_id.to_s
|
@@ -128,8 +128,8 @@ describe RestPack::Serializer::Paging do
|
|
128
128
|
context "with includes as comma delimited string" do
|
129
129
|
let(:params) { { include: "albums,artists" } }
|
130
130
|
it "includes side-loaded models" do
|
131
|
-
page[:albums].should_not == nil
|
132
|
-
page[:artists].should_not == nil
|
131
|
+
page[:linked][:albums].should_not == nil
|
132
|
+
page[:linked][:artists].should_not == nil
|
133
133
|
end
|
134
134
|
|
135
135
|
it "includes the side-loads in page hrefs" do
|
@@ -18,8 +18,8 @@ describe RestPack::Serializer::Resource do
|
|
18
18
|
let(:params) { { id: @song.id, include: 'albums' } }
|
19
19
|
|
20
20
|
it "includes side-loaded models" do
|
21
|
-
resource[:albums].count.should == 1
|
22
|
-
resource[:albums].first[:id].should == @song.album.id.to_s
|
21
|
+
resource[:linked][:albums].count.should == 1
|
22
|
+
resource[:linked][:albums].first[:id].should == @song.album.id.to_s
|
23
23
|
end
|
24
24
|
|
25
25
|
it "includes the side-loads in the main meta data" do
|
@@ -75,7 +75,7 @@ describe RestPack::Serializer::SideLoading do
|
|
75
75
|
MyApp::ArtistSerializer.filterable_by.should == [:id]
|
76
76
|
end
|
77
77
|
end
|
78
|
-
context "a model with a single :
|
78
|
+
context "a model with a single :belongs_to relations" do
|
79
79
|
it "is filterable by primary key and foreign keys" do
|
80
80
|
MyApp::AlbumSerializer.filterable_by.should =~ [:id, :artist_id, :year]
|
81
81
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restpack_serializer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gavin Joyce
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -225,6 +225,7 @@ files:
|
|
225
225
|
- lib/restpack_serializer/configuration.rb
|
226
226
|
- lib/restpack_serializer/factory.rb
|
227
227
|
- lib/restpack_serializer/options.rb
|
228
|
+
- lib/restpack_serializer/result.rb
|
228
229
|
- lib/restpack_serializer/serializable.rb
|
229
230
|
- lib/restpack_serializer/serializable/attributes.rb
|
230
231
|
- lib/restpack_serializer/serializable/filterable.rb
|
@@ -237,6 +238,7 @@ files:
|
|
237
238
|
- spec/fixtures/db.rb
|
238
239
|
- spec/fixtures/serializers.rb
|
239
240
|
- spec/restpack_serializer_spec.rb
|
241
|
+
- spec/result_spec.rb
|
240
242
|
- spec/serializable/attributes_spec.rb
|
241
243
|
- spec/serializable/filterable_spec.rb
|
242
244
|
- spec/serializable/options_spec.rb
|
@@ -267,7 +269,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
269
|
version: '0'
|
268
270
|
requirements: []
|
269
271
|
rubyforge_project:
|
270
|
-
rubygems_version: 2.0.
|
272
|
+
rubygems_version: 2.0.5
|
271
273
|
signing_key:
|
272
274
|
specification_version: 4
|
273
275
|
summary: Model serialization, paging, side-loading and filtering
|
@@ -276,6 +278,7 @@ test_files:
|
|
276
278
|
- spec/fixtures/db.rb
|
277
279
|
- spec/fixtures/serializers.rb
|
278
280
|
- spec/restpack_serializer_spec.rb
|
281
|
+
- spec/result_spec.rb
|
279
282
|
- spec/serializable/attributes_spec.rb
|
280
283
|
- spec/serializable/filterable_spec.rb
|
281
284
|
- spec/serializable/options_spec.rb
|