Skip to content

Commit eafd543

Browse files
committed
Merge pull request #1 from bacarini/feature/pagination
add feature to include pagination links in response
2 parents c4af610 + 97b155a commit eafd543

File tree

6 files changed

+101
-4
lines changed

6 files changed

+101
-4
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ test/version_tmp
1919
tmp
2020
*.swp
2121
.ruby-version
22+
.ruby-gemset

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,18 @@ And you can change the JSON key that the serializer should use for a particular
273273
The `url` declaration describes which named routes to use while generating URLs
274274
for your JSON. Not every adapter will require URLs.
275275

276+
## Pagination
277+
278+
If you want pagination links in your response, specify it in the `render`
279+
280+
```ruby
281+
render json: @posts, pagination: true
282+
```
283+
284+
AMS relies on either Kaminari or WillPaginate. Please install either dependency by adding one of those to your Gemfile.
285+
286+
Pagination links will only be included in your response if you are using an Adapter that supports `root`, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have `root`.
287+
276288
## Caching
277289

278290
To cache a serializer, call ```cache``` and pass its options.

lib/active_model/serializer/adapter.rb

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,12 @@ def serializable_hash(options = nil)
2121
end
2222

2323
def as_json(options = nil)
24-
hash = serializable_hash(options)
25-
include_meta(hash) unless self.class == FlattenJson
26-
hash
24+
serializable_hash(options).tap do |hash|
25+
return hash if self.class == FlattenJson
26+
27+
include_meta(hash)
28+
include_pagination_links(hash) if options && options[:pagination]
29+
end
2730
end
2831

2932
def self.create(resource, options = {})
@@ -94,6 +97,21 @@ def include_meta(json)
9497
json[meta_key] = meta if meta
9598
json
9699
end
100+
101+
def include_pagination_links(json)
102+
return unless page_links
103+
104+
links?(json) ? json.merge!(page_links) : json['links'] = page_links
105+
json
106+
end
107+
108+
def page_links
109+
@links ||= serializer.page_links
110+
end
111+
112+
def links?(json)
113+
!json['links'].nil?
114+
end
97115
end
98116
end
99117
end

lib/active_model/serializer/array_serializer.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ class ArraySerializer
44
NoSerializerError = Class.new(StandardError)
55
include Enumerable
66
delegate :each, to: :@objects
7+
delegate :page_links, to: :pagination
78

8-
attr_reader :root, :meta, :meta_key
9+
attr_reader :root, :meta, :meta_key, :pagination
910

1011
def initialize(objects, options = {})
1112
@root = options[:root]
@@ -24,6 +25,7 @@ def initialize(objects, options = {})
2425
end
2526
@meta = options[:meta]
2627
@meta_key = options[:meta_key]
28+
@pagination = ActiveModel::Serializer::Pagination.new(objects) if options[:pagination]
2729
end
2830

2931
def json_key
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
module ActiveModel
2+
class Serializer
3+
class Pagination
4+
attr_reader :collection
5+
6+
def initialize(collection)
7+
@collection = collection
8+
end
9+
10+
def page_links
11+
send(default_adapter)
12+
end
13+
14+
private
15+
16+
def kaminari
17+
build_links collection.size
18+
end
19+
20+
def will_paginate
21+
setup_will_paginate
22+
build_links collection.per_page
23+
end
24+
25+
def build_links(per_page)
26+
pages = pages_from.each_with_object({}) do |(key, value), hash|
27+
hash[key] = "?page=#{value}&per_page=#{per_page}"
28+
end
29+
{ pages: pages } unless pages.empty?
30+
end
31+
32+
def pages_from
33+
return {} if collection.total_pages == 1
34+
35+
{}.tap do |pages|
36+
unless collection.first_page?
37+
pages[:first] = 1
38+
pages[:prev] = collection.current_page - 1
39+
end
40+
41+
unless collection.last_page?
42+
pages[:next] = collection.current_page + 1
43+
pages[:last] = collection.total_pages
44+
end
45+
end
46+
end
47+
48+
def default_adapter
49+
return :kaminari if defined?(Kaminari)
50+
return :will_paginate if defined?(WillPaginate::CollectionMethods)
51+
raise "AMS relies on either Kaminari or WillPaginate." +
52+
"Please install either dependency by adding one of those to your Gemfile"
53+
end
54+
55+
def setup_will_paginate
56+
WillPaginate::CollectionMethods.module_eval do
57+
def first_page?() !previous_page end
58+
def last_page?() !next_page end
59+
end
60+
end
61+
end
62+
end
63+
end

lib/active_model_serializers.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
require 'active_model/serializer/version'
33
require 'active_model/serializer'
44
require 'active_model/serializer/fieldset'
5+
require 'active_model/serializer/pagination'
56
require 'active_model/serializable_resource'
67

78
begin

0 commit comments

Comments
 (0)