restpack_serializer 0.2.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.
@@ -0,0 +1,102 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe RestPack::Serializer do
4
+ let(:serializer) { PersonSerializer.new }
5
+ let(:person) { Person.new(id: 123, name: 'Gavin', age: 36) }
6
+ class Person
7
+ attr_accessor :id, :name, :age
8
+
9
+ def initialize(attributes = {})
10
+ @id = attributes[:id]
11
+ @name = attributes[:name]
12
+ @age = attributes[:age]
13
+ end
14
+
15
+ def self.table_name
16
+ "people"
17
+ end
18
+ end
19
+
20
+ context "bare bones serializer" do
21
+ class EmptySerializer
22
+ include RestPack::Serializer
23
+ end
24
+
25
+ it "serializes to an empty hash" do
26
+ EmptySerializer.as_json(person).should == { }
27
+ end
28
+ end
29
+
30
+ class PersonSerializer
31
+ include RestPack::Serializer
32
+ attributes :id, :name, :url, :admin_info
33
+
34
+ def url
35
+ "/api/v1/people/#{id}.json"
36
+ end
37
+
38
+ def admin_info
39
+ { key: "super_secret_sauce" }
40
+ end
41
+
42
+ def include_admin_info?
43
+ @options[:is_admin?]
44
+ end
45
+ end
46
+
47
+ describe ".as_json" do
48
+ it "serializes specified attributes" do
49
+ serializer.as_json(person).should == {
50
+ id: '123', name: 'Gavin', url: '/api/v1/people/123.json'
51
+ }
52
+ end
53
+
54
+ context "with options" do
55
+ it "excludes specified attributes" do
56
+ serializer.as_json(person, { include_url?: false }).should == {
57
+ id: '123', name: 'Gavin'
58
+ }
59
+ end
60
+
61
+ it "excludes custom attributes if specified" do
62
+ hash = serializer.as_json(person, { is_admin?: false })
63
+ hash[:admin_info].should == nil
64
+ end
65
+
66
+ it "includes custom attributes if specified" do
67
+ hash = serializer.as_json(person, { is_admin?: true })
68
+ hash[:admin_info].should == { key: "super_secret_sauce" }
69
+ end
70
+ end
71
+
72
+ context "links" do
73
+ let(:serializer) { SongSerializer.new }
74
+ it "includes 'links' data" do
75
+ @album1 = FactoryGirl.create(:album_with_songs, song_count: 11)
76
+ json = serializer.as_json(@album1.songs.first)
77
+ json[:links].should == {
78
+ artist: @album1.artist_id.to_s,
79
+ album: @album1.id.to_s
80
+ }
81
+ end
82
+ end
83
+ end
84
+
85
+ describe "#model_name" do
86
+ it "extracted the Model name from the Serializer name" do
87
+ PersonSerializer.model_name.should == "Person"
88
+ end
89
+ end
90
+
91
+ describe "#model_class" do
92
+ it "returns the correct class" do
93
+ PersonSerializer.model_class.should == Person
94
+ end
95
+ end
96
+
97
+ describe "#key" do
98
+ it "returns the correct key" do
99
+ PersonSerializer.key.should == :people
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,72 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe RestPack::Serializer::SideLoading do
4
+ context "when side-loading" do
5
+ describe ".belongs_to" do
6
+
7
+ before(:each) do
8
+ FactoryGirl.create(:artist_with_albums, album_count: 2)
9
+ FactoryGirl.create(:artist_with_albums, album_count: 1)
10
+ end
11
+ let(:side_loads) { SongSerializer.side_loads(models, options) }
12
+
13
+ context "with no models" do
14
+ let(:models) { [] }
15
+
16
+ context "no side-loads" do
17
+ let(:options) { RestPack::Serializer::Options.new(Song) }
18
+
19
+ it "returns a hash with no data" do
20
+ side_loads.should == { :meta => {} }
21
+ end
22
+ end
23
+
24
+ context "when including :albums" do
25
+ let(:options) { RestPack::Serializer::Options.new(Song, { "includes" => "albums" }) }
26
+
27
+ it "returns a hash with no data" do
28
+ side_loads.should == { :meta => {} }
29
+ end
30
+ end
31
+ end
32
+
33
+ context "with a single model" do
34
+ let(:models) { [Song.first] }
35
+
36
+ context "when including :albums" do
37
+ let(:options) { RestPack::Serializer::Options.new(Song, { "includes" => "albums" }) }
38
+
39
+ it "returns side-loaded albums" do
40
+ side_loads.should == {
41
+ albums: [AlbumSerializer.as_json(Song.first.album)],
42
+ meta: { }
43
+ }
44
+ end
45
+ end
46
+ end
47
+
48
+ context "with multiple models" do
49
+ let(:artist1) { Artist.find(1) }
50
+ let(:artist2) { Artist.find(2) }
51
+ let(:song1) { artist1.songs.first }
52
+ let(:song2) { artist2.songs.first }
53
+ let(:models) { [song1, song2] }
54
+
55
+ context "when including :albums" do
56
+ let(:options) { RestPack::Serializer::Options.new(Song, { "includes" => "albums" }) }
57
+
58
+ it "returns side-loaded albums" do
59
+ side_loads.should == {
60
+ albums: [
61
+ AlbumSerializer.as_json(song1.album),
62
+ AlbumSerializer.as_json(song2.album)
63
+ ],
64
+ :meta => { }
65
+ }
66
+ end
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,43 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe RestPack::Serializer::SideLoading do
4
+ context "when side-loading" do
5
+ describe ".has_many" do
6
+
7
+ before(:each) do
8
+ @artist1 = FactoryGirl.create(:artist_with_albums, album_count: 2)
9
+ @artist2 = FactoryGirl.create(:artist_with_albums, album_count: 1)
10
+ end
11
+ let(:side_loads) { ArtistSerializer.side_loads(models, options) }
12
+
13
+ context "with a single model" do
14
+ let(:models) { [@artist1] }
15
+
16
+ context "when including :albums" do
17
+ let(:options) { RestPack::Serializer::Options.new(Artist, { "includes" => "albums" }) }
18
+
19
+ it "returns side-loaded albums" do
20
+ side_loads[:albums].count.should == @artist1.albums.count
21
+ side_loads[:meta][:albums][:page].should == 1
22
+ side_loads[:meta][:albums][:count].should == @artist1.albums.count
23
+ end
24
+ end
25
+ end
26
+
27
+ context "with two models" do
28
+ let(:models) { [@artist1, @artist2] }
29
+
30
+ context "when including :albums" do
31
+ let(:options) { RestPack::Serializer::Options.new(Artist, { "includes" => "albums" }) }
32
+
33
+ it "returns side-loaded albums" do
34
+ expected_count = @artist1.albums.count + @artist2.albums.count
35
+ side_loads[:albums].count.should == expected_count
36
+ side_loads[:meta][:albums][:count].should == expected_count
37
+ end
38
+ end
39
+ end
40
+
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,82 @@
1
+ require './spec/spec_helper'
2
+
3
+ describe RestPack::Serializer::SideLoading do
4
+ context "invalid :includes" do
5
+ before(:each) do
6
+ FactoryGirl.create(:song)
7
+ end
8
+
9
+ context "an include to an inexistent model" do
10
+ it "raises an exception" do
11
+ exception = RestPack::Serializer::InvalidInclude
12
+ message = ":wrong is not a valid include for Song"
13
+
14
+ expect do
15
+ SongSerializer.side_loads([Song.first], RestPack::Serializer::Options.new(Song, { "includes" => "wrong" }))
16
+ end.to raise_error(exception, message)
17
+ end
18
+ end
19
+
20
+ context "an include to a model which has not been whitelisted with 'can_include'" do
21
+ it "raises an exception" do
22
+ payment = FactoryGirl.create(:payment)
23
+ exception = RestPack::Serializer::InvalidInclude
24
+ message = ":payments is not a valid include for Artist"
25
+
26
+ expect do
27
+ ArtistSerializer.side_loads([payment.artist], RestPack::Serializer::Options.new(Artist, { "includes" => "payments" }))
28
+ end.to raise_error(exception, message)
29
+ end
30
+ end
31
+ end
32
+
33
+ describe "#can_include" do
34
+ class CustomSerializer
35
+ include RestPack::Serializer
36
+ attributes :a, :b, :c
37
+ end
38
+ it "defaults to empty array" do
39
+ CustomSerializer.can_includes.should == []
40
+ end
41
+
42
+ it "allows includes to be specified" do
43
+ class CustomSerializer
44
+ can_include :model1
45
+ can_include :model2, :model3
46
+ end
47
+
48
+ CustomSerializer.can_includes.should == [:model1, :model2, :model3]
49
+ end
50
+ end
51
+
52
+ describe "#links" do
53
+ AlbumSerializer.links.should == {
54
+ "albums.artists" => {
55
+ :href => "/artists/{albums.artist}.json",
56
+ :type => :artists
57
+ },
58
+ "albums.songs" => {
59
+ :href => "/songs.json?album_id={albums.id}",
60
+ :type => :songs
61
+ }
62
+ }
63
+ end
64
+
65
+ describe "#filterable_by" do
66
+ context "a model with no :belongs_to relations" do
67
+ it "is filterable by :id only" do
68
+ ArtistSerializer.filterable_by.should == [:id]
69
+ end
70
+ end
71
+ context "a model with a single :belongs_torelations" do
72
+ it "is filterable by primary key and foreign keys" do
73
+ AlbumSerializer.filterable_by.should =~ [:id, :artist_id]
74
+ end
75
+ end
76
+ context "a model with multiple :belongs_to relations" do
77
+ it "is filterable by primary key and foreign keys" do
78
+ SongSerializer.filterable_by.should =~ [:id, :artist_id, :album_id]
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,32 @@
1
+ require 'rspec'
2
+ require './lib/restpack_serializer'
3
+ require './spec/fixtures/db'
4
+ require './spec/fixtures/serializers'
5
+ require './spec/support/factory'
6
+ require 'database_cleaner'
7
+
8
+ FactoryGirl.find_definitions
9
+
10
+ RSpec.configure do |config|
11
+ config.include FactoryGirl::Syntax::Methods
12
+
13
+ config.before(:suite) do
14
+ DatabaseCleaner.clean_with(:truncation)
15
+ end
16
+
17
+ config.before(:each) do
18
+ DatabaseCleaner.strategy = :transaction
19
+ end
20
+
21
+ config.before(:each, :js => true) do
22
+ DatabaseCleaner.strategy = :truncation
23
+ end
24
+
25
+ config.before(:each) do
26
+ DatabaseCleaner.start
27
+ end
28
+
29
+ config.after(:each) do
30
+ DatabaseCleaner.clean
31
+ end
32
+ end
@@ -0,0 +1,45 @@
1
+ require 'factory_girl'
2
+
3
+ FactoryGirl.define do
4
+ factory :artist do
5
+ sequence(:name) {|n| "Artist ##{n}" }
6
+ sequence(:website) {|n| "http://website#{n}.com/" }
7
+
8
+ factory :artist_with_albums do
9
+ ignore do
10
+ album_count 3
11
+ end
12
+
13
+ after(:create) do |artist, evaluator|
14
+ create_list(:album_with_songs, evaluator.album_count, artist: artist)
15
+ end
16
+ end
17
+ end
18
+
19
+ factory :album do
20
+ sequence(:title) {|n| "Album ##{n}" }
21
+ sequence(:year) {|n| 1960 + n }
22
+ artist
23
+
24
+ factory :album_with_songs do
25
+ ignore do
26
+ song_count 10
27
+ end
28
+
29
+ after(:create) do |album, evaluator|
30
+ create_list(:song, evaluator.song_count, album: album, artist: album.artist)
31
+ end
32
+ end
33
+ end
34
+
35
+ factory :song do
36
+ sequence(:title) {|n| "Song ##{n}" }
37
+ artist
38
+ album
39
+ end
40
+
41
+ factory :payment do
42
+ amount 999
43
+ artist
44
+ end
45
+ end
metadata ADDED
@@ -0,0 +1,266 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: restpack_serializer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.3
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Gavin Joyce
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '3.0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: activesupport
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '3.0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '3.0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: will_paginate
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: '3.0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '3.0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: rake
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 10.0.3
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 10.0.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: '2.12'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: '2.12'
94
+ - !ruby/object:Gem::Dependency
95
+ name: guard-rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 2.5.4
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 2.5.4
110
+ - !ruby/object:Gem::Dependency
111
+ name: growl
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 1.0.3
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ~>
124
+ - !ruby/object:Gem::Version
125
+ version: 1.0.3
126
+ - !ruby/object:Gem::Dependency
127
+ name: factory_girl
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ~>
132
+ - !ruby/object:Gem::Version
133
+ version: 4.2.0
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ~>
140
+ - !ruby/object:Gem::Version
141
+ version: 4.2.0
142
+ - !ruby/object:Gem::Dependency
143
+ name: sqlite3
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ~>
148
+ - !ruby/object:Gem::Version
149
+ version: 1.3.7
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ~>
156
+ - !ruby/object:Gem::Version
157
+ version: 1.3.7
158
+ - !ruby/object:Gem::Dependency
159
+ name: database_cleaner
160
+ requirement: !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - ~>
164
+ - !ruby/object:Gem::Version
165
+ version: 0.9.1
166
+ type: :development
167
+ prerelease: false
168
+ version_requirements: !ruby/object:Gem::Requirement
169
+ none: false
170
+ requirements:
171
+ - - ~>
172
+ - !ruby/object:Gem::Version
173
+ version: 0.9.1
174
+ - !ruby/object:Gem::Dependency
175
+ name: bump
176
+ requirement: !ruby/object:Gem::Requirement
177
+ none: false
178
+ requirements:
179
+ - - ! '>='
180
+ - !ruby/object:Gem::Version
181
+ version: '0'
182
+ type: :development
183
+ prerelease: false
184
+ version_requirements: !ruby/object:Gem::Requirement
185
+ none: false
186
+ requirements:
187
+ - - ! '>='
188
+ - !ruby/object:Gem::Version
189
+ version: '0'
190
+ description: Model serialization, paging, side-loading and filtering
191
+ email:
192
+ - gavinjoyce@gmail.com
193
+ executables: []
194
+ extensions: []
195
+ extra_rdoc_files: []
196
+ files:
197
+ - .gitignore
198
+ - .rspec
199
+ - .travis.yml
200
+ - Gemfile
201
+ - Gemfile.lock
202
+ - Guardfile
203
+ - LICENSE
204
+ - README.md
205
+ - Rakefile
206
+ - lib/restpack_serializer.rb
207
+ - lib/restpack_serializer/factory.rb
208
+ - lib/restpack_serializer/options.rb
209
+ - lib/restpack_serializer/serializable.rb
210
+ - lib/restpack_serializer/serializable/attributes.rb
211
+ - lib/restpack_serializer/serializable/paging.rb
212
+ - lib/restpack_serializer/serializable/resource.rb
213
+ - lib/restpack_serializer/serializable/side_loading.rb
214
+ - lib/restpack_serializer/version.rb
215
+ - restpack_serializer.gemspec
216
+ - spec/factory/factory_spec.rb
217
+ - spec/fixtures/db.rb
218
+ - spec/fixtures/serializers.rb
219
+ - spec/serializable/attributes_spec.rb
220
+ - spec/serializable/options_spec.rb
221
+ - spec/serializable/paging_spec.rb
222
+ - spec/serializable/resource_spec.rb
223
+ - spec/serializable/serializer_spec.rb
224
+ - spec/serializable/side_loading/belongs_to_spec.rb
225
+ - spec/serializable/side_loading/has_many_spec.rb
226
+ - spec/serializable/side_loading/side_loading_spec.rb
227
+ - spec/spec_helper.rb
228
+ - spec/support/factory.rb
229
+ homepage: https://github.com/RestPack
230
+ licenses: []
231
+ post_install_message:
232
+ rdoc_options: []
233
+ require_paths:
234
+ - lib
235
+ required_ruby_version: !ruby/object:Gem::Requirement
236
+ none: false
237
+ requirements:
238
+ - - ! '>='
239
+ - !ruby/object:Gem::Version
240
+ version: '0'
241
+ required_rubygems_version: !ruby/object:Gem::Requirement
242
+ none: false
243
+ requirements:
244
+ - - ! '>='
245
+ - !ruby/object:Gem::Version
246
+ version: '0'
247
+ requirements: []
248
+ rubyforge_project:
249
+ rubygems_version: 1.8.24
250
+ signing_key:
251
+ specification_version: 3
252
+ summary: Model serialization, paging, side-loading and filtering
253
+ test_files:
254
+ - spec/factory/factory_spec.rb
255
+ - spec/fixtures/db.rb
256
+ - spec/fixtures/serializers.rb
257
+ - spec/serializable/attributes_spec.rb
258
+ - spec/serializable/options_spec.rb
259
+ - spec/serializable/paging_spec.rb
260
+ - spec/serializable/resource_spec.rb
261
+ - spec/serializable/serializer_spec.rb
262
+ - spec/serializable/side_loading/belongs_to_spec.rb
263
+ - spec/serializable/side_loading/has_many_spec.rb
264
+ - spec/serializable/side_loading/side_loading_spec.rb
265
+ - spec/spec_helper.rb
266
+ - spec/support/factory.rb