restpack_serializer 0.4.9 → 0.4.10
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/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
|