jsonapi-materializer 1.1.0 → 2.0.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a2f61a86bda571eb041aa543a16338d80c82b742708f90be0c321e45f27eb97e
4
- data.tar.gz: fb22fbb7a3998c2ca6563c85a65b12980fae019feb96972523850c8074160485
3
+ metadata.gz: 9556e194a2e69b081bad43a8ddfbab23c55b9707a2250598222854943118b50c
4
+ data.tar.gz: 14653444ae546e3f3ecb4a4611b9739e247538b82d032a475b7931fe8a97f2ef
5
5
  SHA512:
6
- metadata.gz: 1a27fc6d325e69296ae5ce9e73a21caf13194eba084b71f127a81574c63fe839cba0be3701b2be43f812efa7e9d22428f20891d46703eb30fe7d2cba73d2f3b8
7
- data.tar.gz: 7c661026d63ac185e4f7d01db31b83547945d3903c14775273dbe06b05455a57209286efc5237c764b26853c3a8bfe733c4064aa3b081e1fd38e287a675a36c3
6
+ metadata.gz: a0985c0cfcbdab3e5c6d6115838a3f30699e40a819cd4c00c2a58b9bf27181e5d5bce12d4da230e6d2c3ba9564df9e04a777a5086e5074c1bf6b757ff7b8d456
7
+ data.tar.gz: 82e6d60d6806c0d37c043bbe16783dacb9601eb9651c200decf078efc012292d87d36a605b55697e8c6ef8afeb0bc03bf300eca8104b1e707aadc4f18438e0d9
@@ -13,47 +13,18 @@ module JSONAPI
13
13
  attr_writer(:includes)
14
14
  attr_writer(:pagination)
15
15
 
16
- delegate(:first_page?, to: :object)
17
- delegate(:prev_page, to: :object)
18
- delegate(:total_pages, to: :object)
19
- delegate(:next_page, to: :object)
20
- delegate(:last_page?, to: :object)
21
- delegate(:limit_value, to: :object)
22
-
23
16
  def as_json(*)
24
17
  {
25
- links: if pagination
26
- {
27
- first: (links_pagination.expand(offset: 1, limit: limit_value).to_s unless total_pages.zero? || first_page?),
28
- prev: (links_pagination.expand(offset: prev_page, limit: limit_value).to_s unless total_pages.zero? || first_page?),
29
- self: (links_self unless total_pages.zero?),
30
- next: (links_pagination.expand(offset: next_page, limit: limit_value).to_s unless total_pages.zero? || last_page?),
31
- last: (links_pagination.expand(offset: total_pages, limit: limit_value).to_s unless total_pages.zero? || last_page?)
32
- }.compact
33
- else
34
- {}
35
- end,
36
- data: resources,
37
- included:
38
- }.transform_values(&:presence).compact
18
+ links: pagination,
19
+ included:,
20
+ meta:
21
+ }.transform_values(&:presence).compact.merge(data: resources)
39
22
  end
40
23
 
41
24
  private def materializers
42
25
  @materializers ||= object.map { |subobject| self.class.module_parent.new(object: subobject, selects:, includes:) }
43
26
  end
44
27
 
45
- private def links_pagination
46
- Addressable::Template.new(
47
- "#{origin}/#{type}?page[offset]={offset}&page[limit]={limit}"
48
- )
49
- end
50
-
51
- private def links_self
52
- Addressable::Template.new(
53
- "#{origin}/#{type}"
54
- ).pattern
55
- end
56
-
57
28
  private def origin
58
29
  self.class.module_parent.instance_variable_get(:@origin)
59
30
  end
@@ -74,6 +45,36 @@ module JSONAPI
74
45
  @includes || []
75
46
  end
76
47
 
48
+ private def pagination
49
+ if @pagination
50
+ {
51
+ first: (pagination_link_template.expand(offset: 1, limit: @pagination.in).to_s unless @pagination.pages.zero? || @pagination.prev.nil?),
52
+ prev: (pagination_link_template.expand(offset: @pagination.prev, limit: @pagination.in).to_s unless @pagination.pages.zero? || @pagination.prev.nil?),
53
+ self: (pagination_link_template.expand(offset: @pagination.page, limit: @pagination.in).to_s unless @pagination.pages.zero?),
54
+ next: (pagination_link_template.expand(offset: @pagination.next, limit: @pagination.in).to_s unless @pagination.pages.zero? || @pagination.next.nil?),
55
+ last: (pagination_link_template.expand(offset: @pagination.pages, limit: @pagination.in).to_s unless @pagination.pages.zero? || @pagination.next.nil?)
56
+ }.compact
57
+ else
58
+ {}
59
+ end
60
+ end
61
+
62
+ private def pagination_link_template
63
+ Addressable::Template.new(
64
+ "#{origin}/#{type}?page[offset]={offset}&page[limit]={limit}"
65
+ )
66
+ end
67
+
68
+ private def self_link_template
69
+ Addressable::Template.new(
70
+ "#{origin}/#{type}"
71
+ ).pattern
72
+ end
73
+
74
+ private def meta
75
+ {}
76
+ end
77
+
77
78
  private def included
78
79
  @included ||= materializers.flat_map do |materializer|
79
80
  includes.flat_map do |path|
@@ -85,9 +86,8 @@ module JSONAPI
85
86
  end
86
87
  end
87
88
  end
88
- end.uniq.map(&:as_data)
89
+ end.uniq.compact.map(&:as_data)
89
90
  end
90
- # rubocop:enable Metrics/PerceivedComplexity, Metrics/CyclomaticComplexity
91
91
  end
92
92
  end
93
93
  end
@@ -2,9 +2,26 @@
2
2
 
3
3
  require("spec_helper")
4
4
 
5
+ PaginationAdapter = Struct.new(:in, :page, :pages, :prev, :next)
6
+
5
7
  RSpec.describe(JSONAPI::Materializer::Collection) do
6
8
  let(:described_class) { ArticleMaterializer::Collection }
7
- let(:collection) { described_class.new(object:, includes: [["comments"], ["author"]]) }
9
+ let(:collection) do
10
+ described_class.new(
11
+ object:,
12
+ includes: [["comments"], ["author"]],
13
+ pagination:
14
+ )
15
+ end
16
+ let(:pagination) do
17
+ PaginationAdapter.new(
18
+ 10, # items in page
19
+ 9, # current page
20
+ 10, # total pages
21
+ 100, # previous page
22
+ 80 # next page
23
+ )
24
+ end
8
25
 
9
26
  describe("#as_json") do
10
27
  subject { collection.as_json.deep_stringify_keys }
@@ -54,12 +71,84 @@ RSpec.describe(JSONAPI::Materializer::Collection) do
54
71
  }]))
55
72
  end
56
73
 
57
- it("has a links key at root with pagination") do
58
- expect(subject.fetch("links")).to(eq(
59
- "self" => "http://example.com/articles",
60
- "next" => "http://example.com/articles?page[offset]=2&page[limit]=1",
61
- "last" => "http://example.com/articles?page[offset]=3&page[limit]=1"
62
- ))
74
+ context("when on the first page") do
75
+ let(:pagination) do
76
+ PaginationAdapter.new(
77
+ 10, # items in page
78
+ 1, # current page
79
+ 10, # total pages
80
+ nil, # previous page
81
+ 2 # next page
82
+ )
83
+ end
84
+
85
+ it("has a links key at root with pagination") do
86
+ expect(subject.fetch("links")).to(eq(
87
+ "last" => "http://example.com/articles?page[offset]=10&page[limit]=10",
88
+ "next" => "http://example.com/articles?page[offset]=2&page[limit]=10",
89
+ "self" => "http://example.com/articles?page[offset]=1&page[limit]=10"
90
+ ))
91
+ end
92
+ end
93
+
94
+ context("when on the last page") do
95
+ let(:pagination) do
96
+ PaginationAdapter.new(
97
+ 10, # items in page
98
+ 10, # current page
99
+ 10, # total pages
100
+ 9, # previous page
101
+ nil # next page
102
+ )
103
+ end
104
+
105
+ it("has a links key at root with pagination") do
106
+ expect(subject.fetch("links")).to(eq(
107
+ "first" => "http://example.com/articles?page[offset]=1&page[limit]=10",
108
+ "prev" => "http://example.com/articles?page[offset]=9&page[limit]=10",
109
+ "self" => "http://example.com/articles?page[offset]=10&page[limit]=10"
110
+ ))
111
+ end
112
+ end
113
+
114
+ context("when on the middle page") do
115
+ let(:pagination) do
116
+ PaginationAdapter.new(
117
+ 10, # items in page
118
+ 5, # current page
119
+ 10, # total pages
120
+ 4, # previous page
121
+ 6 # next page
122
+ )
123
+ end
124
+
125
+ it("has a links key at root with pagination") do
126
+ expect(subject.fetch("links")).to(eq(
127
+ "first" => "http://example.com/articles?page[offset]=1&page[limit]=10",
128
+ "last" => "http://example.com/articles?page[offset]=10&page[limit]=10",
129
+ "next" => "http://example.com/articles?page[offset]=6&page[limit]=10",
130
+ "prev" => "http://example.com/articles?page[offset]=4&page[limit]=10",
131
+ "self" => "http://example.com/articles?page[offset]=5&page[limit]=10"
132
+ ))
133
+ end
134
+ end
135
+
136
+ context("when on the only page") do
137
+ let(:pagination) do
138
+ PaginationAdapter.new(
139
+ 10, # items in page
140
+ 1, # current page
141
+ 1, # total pages
142
+ nil, # previous page
143
+ nil # next page
144
+ )
145
+ end
146
+
147
+ it("has a links key at root with pagination") do
148
+ expect(subject.fetch("links")).to(eq(
149
+ "self" => "http://example.com/articles?page[offset]=1&page[limit]=10"
150
+ ))
151
+ end
63
152
  end
64
153
 
65
154
  it("has a included key at root with included models") do
@@ -45,7 +45,6 @@ module JSONAPI
45
45
  end
46
46
  end
47
47
  end
48
- # rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity
49
48
 
50
49
  def using(parent)
51
50
  Resource::Relationship.new(related: self, parent:)
@@ -24,8 +24,7 @@ module JSONAPI
24
24
  links: {
25
25
  self: links_self,
26
26
  related: links_related
27
- },
28
- meta: {}
27
+ }
29
28
  }.transform_values(&:presence).compact
30
29
  end
31
30
 
@@ -204,7 +204,7 @@ module JSONAPI
204
204
  subject.relation(key).for(subject)
205
205
  end
206
206
  end
207
- end.map(&:as_data)
207
+ end.compact.map(&:as_data)
208
208
  end
209
209
  end
210
210
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module JSONAPI
4
4
  module Materializer
5
- VERSION = "1.1.0"
5
+ VERSION = "2.0.0"
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jsonapi-materializer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kurtis Rainbolt-Greene
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-08 00:00:00.000000000 Z
11
+ date: 2023-10-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport