roar-contrib 0.0.1.alpha1
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 +7 -0
- data/.gitignore +14 -0
- data/.travis.yml +5 -0
- data/CHANGES.md +2 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +22 -0
- data/README.md +228 -0
- data/Rakefile +12 -0
- data/lib/roar/contrib/decorator/collection_representer.rb +32 -0
- data/lib/roar/contrib/decorator/page_representer.rb +74 -0
- data/lib/roar/contrib/version.rb +5 -0
- data/lib/roar-contrib.rb +9 -0
- data/roar-contrib.gemspec +28 -0
- data/test/decorator/collection_representer_test.rb +30 -0
- data/test/decorator/page_representer_test.rb +182 -0
- data/test/test_helper.rb +9 -0
- metadata +175 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 21d28d530f3cc0618a39fd6a54a465371e3f0f07
|
4
|
+
data.tar.gz: a551b007d5df3fcf78fdd7dde7ab53b07237a1ac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 3e7315a588ab63d249f67022b3e7ed86cab7b55b894eb581e851b81078bcb8f84e2752bebb861e7711ded5ddaf29f19833564e1bdcdc0acbb0f20f546f995491
|
7
|
+
data.tar.gz: 16f7746c50492dabf6fc4781290717b917182c4401e14d7c2c8f0618b52efa652cfafe2aca3fea5804907fc40cac0f02fa8716a0a2f72bd4c09060dcb73b4599
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/CHANGES.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Ari Summer
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,228 @@
|
|
1
|
+
# roar-contrib [](https://travis-ci.org/summera/roar-contrib)
|
2
|
+
Collection of useful [Roar](https://github.com/apotonick/roar) contributions and extensions.
|
3
|
+
|
4
|
+
## Installation
|
5
|
+
|
6
|
+
Add this line to your application's Gemfile:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
gem 'roar-contrib'
|
10
|
+
```
|
11
|
+
|
12
|
+
And then execute:
|
13
|
+
|
14
|
+
$ bundle
|
15
|
+
|
16
|
+
Or install it yourself as:
|
17
|
+
|
18
|
+
$ gem install roar-contrib
|
19
|
+
|
20
|
+
## Representers
|
21
|
+
|
22
|
+
### Collections with Decorators
|
23
|
+
When using Decorators, include `Roar::Contrib::Decorator::CollectionRepresenter` to create a Representer for a collection of resources.
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
class SongRepresenter < Roar::Decorator
|
27
|
+
include Roar::JSON
|
28
|
+
|
29
|
+
property :name
|
30
|
+
end
|
31
|
+
|
32
|
+
class SongsRepresenter < Roar::Decorator
|
33
|
+
include Roar::JSON
|
34
|
+
include Roar::Contrib::Decorator::CollectionRepresenter
|
35
|
+
end
|
36
|
+
```
|
37
|
+
|
38
|
+
This will create a collection (`songs` in this case) based on the name of the Representer, using the singular representer (SongRepresenter) to serialize each individual resource in the collection. Therefore, a **GET** request to `/songs` would give you:
|
39
|
+
|
40
|
+
```json
|
41
|
+
{
|
42
|
+
"songs": [
|
43
|
+
{
|
44
|
+
"name": "Thriller"
|
45
|
+
},
|
46
|
+
{
|
47
|
+
"name": "One More Time"
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"name": "Good Vibrations"
|
51
|
+
}
|
52
|
+
]
|
53
|
+
}
|
54
|
+
```
|
55
|
+
|
56
|
+
If you need more custom behavior and want to define your own collection, you can do it like so:
|
57
|
+
```ruby
|
58
|
+
class SongsRepresenter < Roar::Decorator
|
59
|
+
include Roar::JSON
|
60
|
+
|
61
|
+
collection :top_songs,
|
62
|
+
:exec_context => :decorator,
|
63
|
+
:decorator => TopSong
|
64
|
+
|
65
|
+
def top_songs
|
66
|
+
represented
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
### Pagination with Decorators
|
72
|
+
Roar-contrib pagination works with either [will_paginate](https://github.com/mislav/will_paginate) or [Kaminari](https://github.com/amatsuda/kaminari). It is based on Nick Sutterer's [blog post](http://nicksda.apotomo.de/2012/05/ruby-on-rest-6-pagination-with-roar/). You must install one of these for roar-contrib pagination to work. In your Gemfile, include either
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
gem 'will_paginate'
|
76
|
+
```
|
77
|
+
or
|
78
|
+
```ruby
|
79
|
+
gem 'kaminari'
|
80
|
+
```
|
81
|
+
|
82
|
+
To paginate, include `Roar::Contrib::Decorator::PageRepresenter` and define `page_url` in the paginated Representer like so:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
class SongRepresenter < Roar::Decorator
|
86
|
+
include Roar::JSON
|
87
|
+
|
88
|
+
property :name
|
89
|
+
end
|
90
|
+
|
91
|
+
class SongsRepresenter < Roar::Decorator
|
92
|
+
include Roar::JSON
|
93
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
94
|
+
|
95
|
+
collection :songs,
|
96
|
+
:exec_context => :decorator,
|
97
|
+
:decorator => SongRepresenter
|
98
|
+
|
99
|
+
def songs
|
100
|
+
represented
|
101
|
+
end
|
102
|
+
|
103
|
+
# If using roar-rails, url helpers are also available here
|
104
|
+
def page_url(args)
|
105
|
+
"http://www.roar-contrib.com/songs?#{args.to_query}"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
```
|
109
|
+
|
110
|
+
|
111
|
+
As you may have guessed, you can combine the `CollectionRepresenter` and `PageRepresenter` to DRY up the example above. **Woot Woot!** :stuck_out_tongue_closed_eyes: :boom:
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
class SongRepresenter < Roar::Decorator
|
115
|
+
include Roar::JSON
|
116
|
+
|
117
|
+
property :name
|
118
|
+
end
|
119
|
+
|
120
|
+
class SongsRepresenter < Roar::Decorator
|
121
|
+
include Roar::JSON
|
122
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
123
|
+
include Roar::Contrib::Decorator::CollectionRepresenter
|
124
|
+
|
125
|
+
def page_url(args)
|
126
|
+
"http://www.roar-contrib.com/songs?#{args.to_query}"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
```
|
130
|
+
|
131
|
+
If you are using Rails, your controller(s) may look like the following...
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
# Using will_paginate
|
135
|
+
class SongsController < ActionController::Base
|
136
|
+
include Roar::Rails::ControllerAdditions
|
137
|
+
represents :json, Song
|
138
|
+
|
139
|
+
def index
|
140
|
+
@songs = Song.paginate :page => params[:page], :per_page => params[:per_page]
|
141
|
+
|
142
|
+
respond_with @songs
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# Using Kaminari
|
147
|
+
class SongsController < ActionController::Base
|
148
|
+
include Roar::Rails::ControllerAdditions
|
149
|
+
represents :json, Song
|
150
|
+
|
151
|
+
def index
|
152
|
+
@songs = Song.page(params[:page]).per params[:per_page]
|
153
|
+
|
154
|
+
respond_with @songs
|
155
|
+
end
|
156
|
+
end
|
157
|
+
```
|
158
|
+
|
159
|
+
Now, a **GET** request to `/songs?page=3&per_page=1` would give you:
|
160
|
+
|
161
|
+
```json
|
162
|
+
{
|
163
|
+
"total_entries": 3,
|
164
|
+
"links": [
|
165
|
+
{
|
166
|
+
"rel": "self",
|
167
|
+
"href": "http://www.roar-contrib.com/songs?page=3&per_page=1"
|
168
|
+
},
|
169
|
+
{
|
170
|
+
"rel": "previous",
|
171
|
+
"href": "http://www.roar-contrib.com/songs?page=2&per_page=1"
|
172
|
+
}
|
173
|
+
],
|
174
|
+
"songs": [
|
175
|
+
{
|
176
|
+
"name": "Good Vibrations"
|
177
|
+
}
|
178
|
+
]
|
179
|
+
}
|
180
|
+
```
|
181
|
+
|
182
|
+
You can define additional pagination properties in your response such as `per_page` provided by [will_paginate](https://github.com/mislav/will_paginate), or `limit_value` provided by [Kaminari](https://github.com/amatsuda/kaminari), by defining the property in your paginated representer.
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
class SongsRepresenter < Roar::Decorator
|
186
|
+
include Roar::JSON
|
187
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
188
|
+
include Roar::Contrib::Decorator::CollectionRepresenter
|
189
|
+
|
190
|
+
property :per_page # Only works with will_paginate
|
191
|
+
|
192
|
+
def page_url(args)
|
193
|
+
songs_url args
|
194
|
+
end
|
195
|
+
end
|
196
|
+
```
|
197
|
+
|
198
|
+
Roar-contrib provides you with the following methods defined on the Decorator instance that work with either `will_paginate` or `Kaminari`:
|
199
|
+
- `#current_page`
|
200
|
+
- `#next_page`
|
201
|
+
- `#previous_page`
|
202
|
+
- `#per_page`
|
203
|
+
- `#total_entries`
|
204
|
+
|
205
|
+
You can use them as properties by telling Roar to execute the methods in the context of the Decorator.
|
206
|
+
|
207
|
+
```ruby
|
208
|
+
class SongsRepresenter < Roar::Decorator
|
209
|
+
include Roar::JSON
|
210
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
211
|
+
include Roar::Contrib::Decorator::CollectionRepresenter
|
212
|
+
|
213
|
+
property :per_page, :exec_context => :decorator # Works with either will_paginate or Kaminari
|
214
|
+
|
215
|
+
def page_url(args)
|
216
|
+
songs_url args
|
217
|
+
end
|
218
|
+
end
|
219
|
+
```
|
220
|
+
|
221
|
+
## Contributing
|
222
|
+
Contributions welcome!! :smile:
|
223
|
+
|
224
|
+
1. Fork it ( https://github.com/sweatshirtio/roar-contrib/fork )
|
225
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
226
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
227
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
228
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/inflector'
|
3
|
+
|
4
|
+
module Roar
|
5
|
+
module Contrib
|
6
|
+
module Decorator
|
7
|
+
module CollectionRepresenter
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def resource_representer
|
12
|
+
(name.chomp('Representer').singularize << 'Representer').constantize
|
13
|
+
end
|
14
|
+
|
15
|
+
def represented_collection_name
|
16
|
+
name.demodulize.chomp('Representer').underscore.pluralize
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
included do
|
21
|
+
define_method represented_collection_name do
|
22
|
+
represented
|
23
|
+
end
|
24
|
+
|
25
|
+
collection represented_collection_name,
|
26
|
+
:exec_context => :decorator,
|
27
|
+
:decorator => resource_representer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
require 'active_support/inflections'
|
3
|
+
|
4
|
+
module Roar
|
5
|
+
module Contrib
|
6
|
+
module Decorator
|
7
|
+
module PageRepresenter
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
def page_url(args)
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
|
14
|
+
included do
|
15
|
+
# REVIEW: Should we include Hypermedia automatically or raise
|
16
|
+
# an error if not included already?
|
17
|
+
include Roar::Hypermedia
|
18
|
+
|
19
|
+
def current_page
|
20
|
+
represented.current_page
|
21
|
+
end
|
22
|
+
|
23
|
+
def next_page
|
24
|
+
represented.next_page
|
25
|
+
end
|
26
|
+
|
27
|
+
# WillPaginate uses #per_page while Kaminari uses #limit_value
|
28
|
+
def per_page
|
29
|
+
per_page_method = represented.respond_to?(:per_page) ?
|
30
|
+
:per_page : :limit_value
|
31
|
+
|
32
|
+
represented.send per_page_method
|
33
|
+
end
|
34
|
+
|
35
|
+
# WillPaginate uses #previous_page while Kaminari uses #prev_page
|
36
|
+
def previous_page
|
37
|
+
previous_page_method = represented.respond_to?(:previous_page) ?
|
38
|
+
:previous_page : :prev_page
|
39
|
+
|
40
|
+
represented.send previous_page_method
|
41
|
+
end
|
42
|
+
|
43
|
+
# WillPaginate uses #total_entries while Kaminari uses #total_count
|
44
|
+
def total_entries
|
45
|
+
total_entries_method = represented.respond_to?(:total_entries) ?
|
46
|
+
:total_entries : :total_count
|
47
|
+
|
48
|
+
represented.send total_entries_method
|
49
|
+
end
|
50
|
+
|
51
|
+
property :total_entries, exec_context: :decorator
|
52
|
+
|
53
|
+
link :self do |opts|
|
54
|
+
page_url :page => current_page, :per_page => per_page
|
55
|
+
end
|
56
|
+
|
57
|
+
link :next do |opts|
|
58
|
+
page_url(
|
59
|
+
:page => next_page,
|
60
|
+
:per_page => per_page
|
61
|
+
) if next_page
|
62
|
+
end
|
63
|
+
|
64
|
+
link :previous do |opts|
|
65
|
+
page_url(
|
66
|
+
:page => previous_page,
|
67
|
+
:per_page => per_page
|
68
|
+
) if previous_page
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/roar-contrib.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
|
+
require 'roar/contrib/version'
|
3
|
+
|
4
|
+
Gem::Specification.new do |spec|
|
5
|
+
spec.name = 'roar-contrib'
|
6
|
+
spec.version = Roar::Contrib::VERSION
|
7
|
+
spec.authors = ['Ari Summer']
|
8
|
+
spec.email = ['aribsummer@gmail.com']
|
9
|
+
spec.summary = %q{Collection of useful Roar extensions.}
|
10
|
+
spec.description = %q{Roar provides object-oriented representers to define nested REST API documents which can be rendered and parsed. Roar-contrib adds some useful extensions.}
|
11
|
+
spec.homepage = 'https://github.com/summera/roar-contrib'
|
12
|
+
spec.license = 'MIT'
|
13
|
+
|
14
|
+
spec.files = `git ls-files`.split("\n")
|
15
|
+
spec.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
16
|
+
spec.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
17
|
+
spec.require_paths = ['lib']
|
18
|
+
|
19
|
+
spec.add_runtime_dependency 'roar', '~> 1.0'
|
20
|
+
spec.add_runtime_dependency 'activesupport', '>= 3.0.0'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.7'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'minitest', '~> 5.4'
|
25
|
+
spec.add_development_dependency 'minitest-reporters', '~> 1.0'
|
26
|
+
spec.add_development_dependency 'will_paginate', '~> 3.0'
|
27
|
+
spec.add_development_dependency 'kaminari', '~> 0.16'
|
28
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/decorator'
|
3
|
+
|
4
|
+
class CollectionRepresenterTest < MiniTest::Spec
|
5
|
+
class SongRepresenter < Roar::Decorator
|
6
|
+
include Roar::JSON
|
7
|
+
|
8
|
+
property :name
|
9
|
+
end
|
10
|
+
|
11
|
+
class SongsRepresenter < Roar::Decorator
|
12
|
+
include Roar::JSON
|
13
|
+
include Roar::Contrib::Decorator::CollectionRepresenter
|
14
|
+
end
|
15
|
+
|
16
|
+
let(:songs) do
|
17
|
+
[
|
18
|
+
OpenStruct.new(:name => 'Thriller'),
|
19
|
+
OpenStruct.new(:name => 'One More Time'),
|
20
|
+
OpenStruct.new(:name => 'Good Vibrations')
|
21
|
+
]
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'renders a valid collection' do
|
25
|
+
SongsRepresenter
|
26
|
+
.prepare(songs)
|
27
|
+
.to_json
|
28
|
+
.must_equal '{"songs":[{"name":"Thriller"},{"name":"One More Time"},{"name":"Good Vibrations"}]}'
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,182 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/decorator'
|
3
|
+
require 'active_support/core_ext/object/to_query'
|
4
|
+
|
5
|
+
class PageRepresenterTest < MiniTest::Spec
|
6
|
+
let(:songs) do
|
7
|
+
[
|
8
|
+
OpenStruct.new(:name => 'Thriller'),
|
9
|
+
OpenStruct.new(:name => 'One More Time'),
|
10
|
+
OpenStruct.new(:name => 'Good Vibrations')
|
11
|
+
]
|
12
|
+
end
|
13
|
+
|
14
|
+
class SongRepresenter < Roar::Decorator
|
15
|
+
include Roar::JSON
|
16
|
+
|
17
|
+
property :name
|
18
|
+
end
|
19
|
+
|
20
|
+
class SongsRepresenter < Roar::Decorator
|
21
|
+
include Roar::JSON
|
22
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
23
|
+
|
24
|
+
collection :songs,
|
25
|
+
:exec_context => :decorator,
|
26
|
+
:decorator => SongRepresenter
|
27
|
+
|
28
|
+
def songs
|
29
|
+
represented
|
30
|
+
end
|
31
|
+
|
32
|
+
def page_url(args)
|
33
|
+
"http://www.roar-contrib.com/songs?#{args.to_query}"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe 'without #page_url defined' do
|
38
|
+
class NotImplementedSongsRepresenter < Roar::Decorator
|
39
|
+
include Roar::JSON
|
40
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
41
|
+
|
42
|
+
collection :songs,
|
43
|
+
:exec_context => :decorator,
|
44
|
+
:decorator => SongRepresenter
|
45
|
+
|
46
|
+
def songs
|
47
|
+
represented
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'raises NotImplementedError' do
|
52
|
+
proc {
|
53
|
+
NotImplementedSongsRepresenter.prepare(songs.paginate()).to_json
|
54
|
+
}.must_raise NotImplementedError
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe 'without CollectionRepresenter' do
|
59
|
+
describe 'using WillPaginate' do
|
60
|
+
require "will_paginate/array"
|
61
|
+
|
62
|
+
it 'renders a paginated response with no previous or next page' do
|
63
|
+
SongsRepresenter
|
64
|
+
.prepare(songs.paginate())
|
65
|
+
.to_json
|
66
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=1&per_page=30"}],"songs":[{"name":"Thriller"},{"name":"One More Time"},{"name":"Good Vibrations"}]}'
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'renders a paginated response with a previous and next page' do
|
70
|
+
SongsRepresenter
|
71
|
+
.prepare(songs.paginate(:page => 2, :per_page => 1))
|
72
|
+
.to_json
|
73
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=2&per_page=1"},{"rel":"next","href":"http://www.roar-contrib.com/songs?page=3&per_page=1"},{"rel":"previous","href":"http://www.roar-contrib.com/songs?page=1&per_page=1"}],"songs":[{"name":"One More Time"}]}'
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'renders a paginated response with a previous and no next page' do
|
77
|
+
SongsRepresenter
|
78
|
+
.prepare(songs.paginate(:page => 3, :per_page => 1))
|
79
|
+
.to_json
|
80
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=3&per_page=1"},{"rel":"previous","href":"http://www.roar-contrib.com/songs?page=2&per_page=1"}],"songs":[{"name":"Good Vibrations"}]}'
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'renders a paginated response with a next page and no previous page' do
|
84
|
+
SongsRepresenter
|
85
|
+
.prepare(songs.paginate(:page => 1, :per_page => 1))
|
86
|
+
.to_json
|
87
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=1&per_page=1"},{"rel":"next","href":"http://www.roar-contrib.com/songs?page=2&per_page=1"}],"songs":[{"name":"Thriller"}]}'
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe 'using Kaminari' do
|
92
|
+
require 'kaminari/config'
|
93
|
+
require 'kaminari/helpers/paginator'
|
94
|
+
require 'kaminari/models/page_scope_methods'
|
95
|
+
require 'kaminari/models/configuration_methods'
|
96
|
+
require 'kaminari/models/array_extension'
|
97
|
+
|
98
|
+
it 'renders a paginated response with no previous or next page' do
|
99
|
+
SongsRepresenter
|
100
|
+
.prepare(Kaminari.paginate_array(songs).page)
|
101
|
+
.to_json
|
102
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=1&per_page=25"}],"songs":[{"name":"Thriller"},{"name":"One More Time"},{"name":"Good Vibrations"}]}'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'renders a paginated response with a previous and next page' do
|
106
|
+
SongsRepresenter
|
107
|
+
.prepare(Kaminari.paginate_array(songs).page(2).per(1))
|
108
|
+
.to_json
|
109
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=2&per_page=1"},{"rel":"next","href":"http://www.roar-contrib.com/songs?page=3&per_page=1"},{"rel":"previous","href":"http://www.roar-contrib.com/songs?page=1&per_page=1"}],"songs":[{"name":"One More Time"}]}'
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'renders a paginated response with a previous and no next page' do
|
113
|
+
SongsRepresenter
|
114
|
+
.prepare(Kaminari.paginate_array(songs).page(3).per(1))
|
115
|
+
.to_json
|
116
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=3&per_page=1"},{"rel":"previous","href":"http://www.roar-contrib.com/songs?page=2&per_page=1"}],"songs":[{"name":"Good Vibrations"}]}'
|
117
|
+
end
|
118
|
+
|
119
|
+
it 'renders a paginated response with a next page and no previous page' do
|
120
|
+
SongsRepresenter
|
121
|
+
.prepare(Kaminari.paginate_array(songs).page(1).per(1))
|
122
|
+
.to_json
|
123
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=1&per_page=1"},{"rel":"next","href":"http://www.roar-contrib.com/songs?page=2&per_page=1"}],"songs":[{"name":"Thriller"}]}'
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe 'HAL' do
|
129
|
+
require "will_paginate/array"
|
130
|
+
|
131
|
+
class HalSongsRepresenter < Roar::Decorator
|
132
|
+
include Roar::JSON::HAL
|
133
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
134
|
+
|
135
|
+
collection :songs,
|
136
|
+
:exec_context => :decorator,
|
137
|
+
:decorator => SongRepresenter
|
138
|
+
|
139
|
+
def songs
|
140
|
+
represented
|
141
|
+
end
|
142
|
+
|
143
|
+
def page_url(args)
|
144
|
+
"http://www.roar-contrib.com/songs?#{args.to_query}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
it 'renders a paginated response with no previous or next page' do
|
149
|
+
HalSongsRepresenter
|
150
|
+
.prepare(songs.paginate())
|
151
|
+
.to_json
|
152
|
+
.must_equal '{"total_entries":3,"_links":{"self":{"href":"http://www.roar-contrib.com/songs?page=1&per_page=30"}},"songs":[{"name":"Thriller"},{"name":"One More Time"},{"name":"Good Vibrations"}]}'
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
describe 'with CollectionRepresenter' do
|
157
|
+
require "will_paginate/array"
|
158
|
+
|
159
|
+
class TopSongRepresenter < Roar::Decorator
|
160
|
+
include Roar::JSON
|
161
|
+
|
162
|
+
property :name
|
163
|
+
end
|
164
|
+
|
165
|
+
class TopSongsRepresenter < Roar::Decorator
|
166
|
+
include Roar::JSON
|
167
|
+
include Roar::Contrib::Decorator::PageRepresenter
|
168
|
+
include Roar::Contrib::Decorator::CollectionRepresenter
|
169
|
+
|
170
|
+
def page_url(args)
|
171
|
+
"http://www.roar-contrib.com/songs?#{args.to_query}"
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'renders a paginated response with no previous or next page' do
|
176
|
+
TopSongsRepresenter
|
177
|
+
.prepare(songs.paginate())
|
178
|
+
.to_json
|
179
|
+
.must_equal '{"total_entries":3,"links":[{"rel":"self","href":"http://www.roar-contrib.com/songs?page=1&per_page=30"}],"top_songs":[{"name":"Thriller"},{"name":"One More Time"},{"name":"Good Vibrations"}]}'
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: roar-contrib
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1.alpha1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ari Summer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-01-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: roar
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.0.0
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 3.0.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.7'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.7'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: minitest
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '5.4'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '5.4'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: minitest-reporters
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - "~>"
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '1.0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1.0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: will_paginate
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3.0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3.0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: kaminari
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - "~>"
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0.16'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - "~>"
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0.16'
|
125
|
+
description: Roar provides object-oriented representers to define nested REST API
|
126
|
+
documents which can be rendered and parsed. Roar-contrib adds some useful extensions.
|
127
|
+
email:
|
128
|
+
- aribsummer@gmail.com
|
129
|
+
executables: []
|
130
|
+
extensions: []
|
131
|
+
extra_rdoc_files: []
|
132
|
+
files:
|
133
|
+
- ".gitignore"
|
134
|
+
- ".travis.yml"
|
135
|
+
- CHANGES.md
|
136
|
+
- Gemfile
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- Rakefile
|
140
|
+
- lib/roar-contrib.rb
|
141
|
+
- lib/roar/contrib/decorator/collection_representer.rb
|
142
|
+
- lib/roar/contrib/decorator/page_representer.rb
|
143
|
+
- lib/roar/contrib/version.rb
|
144
|
+
- roar-contrib.gemspec
|
145
|
+
- test/decorator/collection_representer_test.rb
|
146
|
+
- test/decorator/page_representer_test.rb
|
147
|
+
- test/test_helper.rb
|
148
|
+
homepage: https://github.com/summera/roar-contrib
|
149
|
+
licenses:
|
150
|
+
- MIT
|
151
|
+
metadata: {}
|
152
|
+
post_install_message:
|
153
|
+
rdoc_options: []
|
154
|
+
require_paths:
|
155
|
+
- lib
|
156
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
157
|
+
requirements:
|
158
|
+
- - ">="
|
159
|
+
- !ruby/object:Gem::Version
|
160
|
+
version: '0'
|
161
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
162
|
+
requirements:
|
163
|
+
- - ">"
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: 1.3.1
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 2.2.2
|
169
|
+
signing_key:
|
170
|
+
specification_version: 4
|
171
|
+
summary: Collection of useful Roar extensions.
|
172
|
+
test_files:
|
173
|
+
- test/decorator/collection_representer_test.rb
|
174
|
+
- test/decorator/page_representer_test.rb
|
175
|
+
- test/test_helper.rb
|