simple_jsonapi 1.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 +7 -0
- data/.gitignore +10 -0
- data/.rubocop.yml +131 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +5 -0
- data/Jenkinsfile +92 -0
- data/LICENSE.txt +22 -0
- data/README.md +532 -0
- data/Rakefile +10 -0
- data/lib/simple_jsonapi.rb +112 -0
- data/lib/simple_jsonapi/definition/attribute.rb +45 -0
- data/lib/simple_jsonapi/definition/base.rb +50 -0
- data/lib/simple_jsonapi/definition/concerns/has_links_object.rb +36 -0
- data/lib/simple_jsonapi/definition/concerns/has_meta_object.rb +36 -0
- data/lib/simple_jsonapi/definition/error.rb +70 -0
- data/lib/simple_jsonapi/definition/error_source.rb +29 -0
- data/lib/simple_jsonapi/definition/link.rb +27 -0
- data/lib/simple_jsonapi/definition/meta.rb +27 -0
- data/lib/simple_jsonapi/definition/relationship.rb +60 -0
- data/lib/simple_jsonapi/definition/resource.rb +104 -0
- data/lib/simple_jsonapi/error_serializer.rb +76 -0
- data/lib/simple_jsonapi/errors/bad_request.rb +11 -0
- data/lib/simple_jsonapi/errors/exception_serializer.rb +6 -0
- data/lib/simple_jsonapi/errors/wrapped_error.rb +35 -0
- data/lib/simple_jsonapi/errors/wrapped_error_serializer.rb +35 -0
- data/lib/simple_jsonapi/helpers/exceptions.rb +39 -0
- data/lib/simple_jsonapi/helpers/serializer_inferrer.rb +136 -0
- data/lib/simple_jsonapi/helpers/serializer_methods.rb +36 -0
- data/lib/simple_jsonapi/node/attributes.rb +51 -0
- data/lib/simple_jsonapi/node/base.rb +91 -0
- data/lib/simple_jsonapi/node/data/collection.rb +25 -0
- data/lib/simple_jsonapi/node/data/singular.rb +26 -0
- data/lib/simple_jsonapi/node/document/base.rb +62 -0
- data/lib/simple_jsonapi/node/document/collection.rb +17 -0
- data/lib/simple_jsonapi/node/document/errors.rb +17 -0
- data/lib/simple_jsonapi/node/document/singular.rb +17 -0
- data/lib/simple_jsonapi/node/error.rb +55 -0
- data/lib/simple_jsonapi/node/error_source.rb +40 -0
- data/lib/simple_jsonapi/node/errors.rb +28 -0
- data/lib/simple_jsonapi/node/included.rb +45 -0
- data/lib/simple_jsonapi/node/object_links.rb +40 -0
- data/lib/simple_jsonapi/node/object_meta.rb +40 -0
- data/lib/simple_jsonapi/node/relationship.rb +79 -0
- data/lib/simple_jsonapi/node/relationship_data/base.rb +53 -0
- data/lib/simple_jsonapi/node/relationship_data/collection.rb +32 -0
- data/lib/simple_jsonapi/node/relationship_data/singular.rb +33 -0
- data/lib/simple_jsonapi/node/relationships.rb +60 -0
- data/lib/simple_jsonapi/node/resource/base.rb +21 -0
- data/lib/simple_jsonapi/node/resource/full.rb +49 -0
- data/lib/simple_jsonapi/node/resource/linkage.rb +25 -0
- data/lib/simple_jsonapi/parameters/fields_spec.rb +45 -0
- data/lib/simple_jsonapi/parameters/include_spec.rb +57 -0
- data/lib/simple_jsonapi/parameters/sort_spec.rb +107 -0
- data/lib/simple_jsonapi/serializer.rb +89 -0
- data/lib/simple_jsonapi/version.rb +3 -0
- data/simple_jsonapi.gemspec +29 -0
- data/test/errors/bad_request_test.rb +34 -0
- data/test/errors/error_serializer_test.rb +229 -0
- data/test/errors/exception_serializer_test.rb +25 -0
- data/test/errors/wrapped_error_serializer_test.rb +91 -0
- data/test/errors/wrapped_error_test.rb +44 -0
- data/test/parameters/fields_spec_test.rb +56 -0
- data/test/parameters/include_spec_test.rb +58 -0
- data/test/parameters/sort_spec_test.rb +65 -0
- data/test/resources/attributes_test.rb +109 -0
- data/test/resources/extras_test.rb +70 -0
- data/test/resources/id_and_type_test.rb +76 -0
- data/test/resources/inclusion_test.rb +134 -0
- data/test/resources/links_test.rb +63 -0
- data/test/resources/meta_test.rb +49 -0
- data/test/resources/relationships_test.rb +262 -0
- data/test/resources/sorting_test.rb +79 -0
- data/test/resources/sparse_fieldset_test.rb +160 -0
- data/test/root_objects_test.rb +165 -0
- data/test/test_helper.rb +31 -0
- metadata +235 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class LinksTest < Minitest::Spec
|
4
|
+
class Thing < TestModel
|
5
|
+
end
|
6
|
+
|
7
|
+
class NoLinksSerializer < SimpleJsonapi::Serializer
|
8
|
+
end
|
9
|
+
|
10
|
+
class BlocksSerializer < SimpleJsonapi::Serializer
|
11
|
+
link(:self) { |thing| "/api/things/#{thing.id}" }
|
12
|
+
end
|
13
|
+
|
14
|
+
class ProcsSerializer < SimpleJsonapi::Serializer
|
15
|
+
link :self, ->(thing) { "/api/things/#{thing.id}" }
|
16
|
+
end
|
17
|
+
|
18
|
+
class ValuesSerializer < SimpleJsonapi::Serializer
|
19
|
+
link :index, "/api/things"
|
20
|
+
end
|
21
|
+
|
22
|
+
class LinkObjectSerializer < SimpleJsonapi::Serializer
|
23
|
+
link(:self) do |thing|
|
24
|
+
{ href: "/api/things/#{thing.id}", meta: { count: 1 } }
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
let(:thing) { Thing.new(id: 1) }
|
29
|
+
|
30
|
+
describe "Resource links object" do
|
31
|
+
describe "without links" do
|
32
|
+
it "omits the links key" do
|
33
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: NoLinksSerializer)
|
34
|
+
refute serialized.key?(:links)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "rendering string links" do
|
39
|
+
it "accepts a block" do
|
40
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: BlocksSerializer)
|
41
|
+
assert_equal "/api/things/1", serialized.dig(:data, :links, :self)
|
42
|
+
end
|
43
|
+
|
44
|
+
it "accepts a proc" do
|
45
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: ProcsSerializer)
|
46
|
+
assert_equal "/api/things/1", serialized.dig(:data, :links, :self)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "accepts a value" do
|
50
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: ValuesSerializer)
|
51
|
+
assert_equal "/api/things", serialized.dig(:data, :links, :index)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "rendering object links" do
|
56
|
+
it "renders an object link" do
|
57
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: LinkObjectSerializer)
|
58
|
+
expected_link = { href: "/api/things/1", meta: { count: 1 } }
|
59
|
+
assert_equal expected_link, serialized.dig(:data, :links, :self)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class MetaTest < Minitest::Spec
|
4
|
+
class Thing < TestModel
|
5
|
+
end
|
6
|
+
|
7
|
+
class NoMetaSerializer < SimpleJsonapi::Serializer
|
8
|
+
end
|
9
|
+
|
10
|
+
class BlocksSerializer < SimpleJsonapi::Serializer
|
11
|
+
meta(:scalar) { |t| "the id is #{t.id}" }
|
12
|
+
end
|
13
|
+
|
14
|
+
class ProcsSerializer < SimpleJsonapi::Serializer
|
15
|
+
meta :array, ->(_t) { %w[some metadata] }
|
16
|
+
end
|
17
|
+
|
18
|
+
class ValuesSerializer < SimpleJsonapi::Serializer
|
19
|
+
meta :scalar, "some metadata"
|
20
|
+
end
|
21
|
+
|
22
|
+
let(:thing) { Thing.new(id: 1) }
|
23
|
+
|
24
|
+
describe "Resource meta object" do
|
25
|
+
describe "without meta information" do
|
26
|
+
it "omits the meta key" do
|
27
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: NoMetaSerializer)
|
28
|
+
refute serialized.key?(:meta)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "rendering meta information" do
|
33
|
+
it "accepts a block" do
|
34
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: BlocksSerializer)
|
35
|
+
assert_equal "the id is 1", serialized.dig(:data, :meta, :scalar)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "accepts a proc" do
|
39
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: ProcsSerializer)
|
40
|
+
assert_equal %w[some metadata], serialized.dig(:data, :meta, :array)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "accepts a value" do
|
44
|
+
serialized = SimpleJsonapi.render_resource(thing, serializer: ValuesSerializer)
|
45
|
+
assert_equal "some metadata", serialized.dig(:data, :meta, :scalar)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,262 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RelationshipsTest < Minitest::Spec
|
4
|
+
class Order < TestModel
|
5
|
+
attr_accessor :customer
|
6
|
+
attr_writer :products
|
7
|
+
|
8
|
+
def products
|
9
|
+
@products ||= []
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class Customer < TestModel
|
14
|
+
attr_accessor :name
|
15
|
+
end
|
16
|
+
|
17
|
+
class Product < TestModel
|
18
|
+
attr_accessor :name
|
19
|
+
end
|
20
|
+
|
21
|
+
class OrderSerializer < SimpleJsonapi::Serializer
|
22
|
+
has_one :customer
|
23
|
+
has_many :products
|
24
|
+
end
|
25
|
+
|
26
|
+
class CustomerSerializer < SimpleJsonapi::Serializer
|
27
|
+
attribute :name
|
28
|
+
end
|
29
|
+
|
30
|
+
class ProductSerializer < SimpleJsonapi::Serializer
|
31
|
+
attribute :name
|
32
|
+
end
|
33
|
+
|
34
|
+
describe "Relationships" do
|
35
|
+
describe "relationship data" do
|
36
|
+
describe "for a has_one relationship" do
|
37
|
+
it "renders an empty relationship as nil" do
|
38
|
+
order = Order.new(id: 1, customer: nil)
|
39
|
+
relationship = SimpleJsonapi.render_resource(order).dig(:data, :relationships, :customer)
|
40
|
+
assert_includes relationship.keys, :data
|
41
|
+
assert_nil relationship[:data]
|
42
|
+
end
|
43
|
+
|
44
|
+
it "renders a non-empty relationship as an object" do
|
45
|
+
order = Order.new(id: 1, customer: Customer.new(id: 2, name: "Miguel"))
|
46
|
+
relationship = SimpleJsonapi.render_resource(order).dig(:data, :relationships, :customer)
|
47
|
+
assert_instance_of Hash, relationship[:data]
|
48
|
+
assert_equal "2", relationship[:data][:id]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "for a has_many relationship" do
|
53
|
+
it "renders an empty relationship as an empty array" do
|
54
|
+
order = Order.new(id: 1, products: nil)
|
55
|
+
relationship = SimpleJsonapi.render_resource(order).dig(:data, :relationships, :products)
|
56
|
+
assert_instance_of Array, relationship[:data]
|
57
|
+
assert_equal [], relationship[:data]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "renders a non-empty relationship as an array" do
|
61
|
+
order = Order.new(id: 1, products: [Product.new(id: 1), Product.new(id: 2)])
|
62
|
+
relationship = SimpleJsonapi.render_resource(order).dig(:data, :relationships, :products)
|
63
|
+
assert_instance_of Array, relationship[:data]
|
64
|
+
assert_equal(["1", "2"], relationship[:data].map { |obj| obj[:id] })
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe "related resource documents" do
|
69
|
+
it "include only the id and type" do
|
70
|
+
order = Order.new(id: 1, customer: Customer.new(id: 2, name: "Andrei"))
|
71
|
+
customer_doc = SimpleJsonapi.render_resource(order).dig(:data, :relationships, :customer, :data)
|
72
|
+
assert_equal({ id: "2", type: "customers" }, customer_doc.except(:meta))
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "relationship links" do
|
78
|
+
class OrderLinksSerializer < SimpleJsonapi::Serializer
|
79
|
+
has_many :products do
|
80
|
+
link(:self) { |order| "/api/orders/#{order.id}/relationships/products" }
|
81
|
+
link(:related) { |order| "/api/orders/#{order.id}/products" }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
let(:order) { Order.new(id: 1) }
|
86
|
+
let(:serialized) { SimpleJsonapi.render_resource(order, serializer: OrderLinksSerializer) }
|
87
|
+
|
88
|
+
it "renders the links" do
|
89
|
+
expected_value = {
|
90
|
+
self: "/api/orders/1/relationships/products",
|
91
|
+
related: "/api/orders/1/products",
|
92
|
+
}
|
93
|
+
assert_equal expected_value, serialized.dig(:data, :relationships, :products, :links)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe "conditional relationship links" do
|
98
|
+
class ConditionalLinksSerializer < SimpleJsonapi::Serializer
|
99
|
+
has_many :products do
|
100
|
+
link :if_a, "link if a", if: ->(order) { order.id == "a" }
|
101
|
+
link :unless_b, "link unless b", unless: ->(order) { order.id == "b" }
|
102
|
+
link :always, "link always"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
let(:order_a) { Order.new(id: "a") }
|
107
|
+
let(:order_b) { Order.new(id: "b") }
|
108
|
+
|
109
|
+
def links_for(order)
|
110
|
+
SimpleJsonapi
|
111
|
+
.render_resource(order, serializer: ConditionalLinksSerializer)
|
112
|
+
.dig(:data, :relationships, :products, :links)
|
113
|
+
end
|
114
|
+
|
115
|
+
it "renders the links when the 'if' is truthy" do
|
116
|
+
assert_equal "link if a", links_for(order_a)[:if_a]
|
117
|
+
end
|
118
|
+
|
119
|
+
it "renders the links when the 'unless' is falsey" do
|
120
|
+
assert_equal "link unless b", links_for(order_a)[:unless_b]
|
121
|
+
end
|
122
|
+
|
123
|
+
it "omits the links when the 'if' is falsey" do
|
124
|
+
assert_equal [:always], links_for(order_b).keys
|
125
|
+
end
|
126
|
+
|
127
|
+
it "omits the links when the 'unless' is truthy" do
|
128
|
+
assert_equal [:always], links_for(order_b).keys
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe "relationship meta information" do
|
133
|
+
class OrderMetaSerializer < SimpleJsonapi::Serializer
|
134
|
+
has_many :products do
|
135
|
+
meta(:generated_on) { "2017-01-01" }
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
let(:order) { Order.new(id: 1) }
|
140
|
+
let(:serialized) { SimpleJsonapi.render_resource(order, serializer: OrderMetaSerializer) }
|
141
|
+
let(:relationship_doc) { serialized.dig(:data, :relationships, :products) }
|
142
|
+
|
143
|
+
it "renders the meta information" do
|
144
|
+
expected_value = { generated_on: "2017-01-01" }
|
145
|
+
assert_equal expected_value, relationship_doc[:meta]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
describe "conditional relationship meta information" do
|
150
|
+
class ConditionalMetaSerializer < SimpleJsonapi::Serializer
|
151
|
+
has_many :products do
|
152
|
+
# data { |order| order.products }
|
153
|
+
meta :if_a, "meta if a", if: ->(order) { order.id == "a" }
|
154
|
+
meta :unless_b, "meta unless b", unless: ->(order) { order.id == "b" }
|
155
|
+
meta :always, "meta always"
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
let(:order_a) { Order.new(id: "a") }
|
160
|
+
let(:order_b) { Order.new(id: "b") }
|
161
|
+
|
162
|
+
def meta_for(order)
|
163
|
+
SimpleJsonapi
|
164
|
+
.render_resource(order, serializer: ConditionalMetaSerializer)
|
165
|
+
.dig(:data, :relationships, :products, :meta)
|
166
|
+
end
|
167
|
+
|
168
|
+
it "renders the meta object when the 'if' is truthy" do
|
169
|
+
assert_equal "meta if a", meta_for(order_a)[:if_a]
|
170
|
+
end
|
171
|
+
|
172
|
+
it "renders the meta object when the 'unless' is falsey" do
|
173
|
+
assert_equal "meta unless b", meta_for(order_a)[:unless_b]
|
174
|
+
end
|
175
|
+
|
176
|
+
it "omits the meta object when the 'if' is falsey" do
|
177
|
+
assert_equal [:always], meta_for(order_b).keys
|
178
|
+
end
|
179
|
+
|
180
|
+
it "omits the meta object when the 'unless' is truthy" do
|
181
|
+
assert_equal [:always], meta_for(order_b).keys
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
describe "related resource serializers" do
|
186
|
+
class AnotherProductSerializer < ProductSerializer
|
187
|
+
type "another_product"
|
188
|
+
end
|
189
|
+
|
190
|
+
class OrderInferringSerializer < SimpleJsonapi::Serializer
|
191
|
+
has_many :products
|
192
|
+
end
|
193
|
+
|
194
|
+
class OrderClassSerializer < SimpleJsonapi::Serializer
|
195
|
+
has_many :products, serializer: AnotherProductSerializer
|
196
|
+
end
|
197
|
+
|
198
|
+
class OrderStringSerializer < SimpleJsonapi::Serializer
|
199
|
+
has_many :products, serializer: AnotherProductSerializer.name
|
200
|
+
end
|
201
|
+
|
202
|
+
let(:order) { Order.new(id: 1, products: [Product.new(id: 2, name: "thing")]) }
|
203
|
+
|
204
|
+
def data_for(order, serializer_class)
|
205
|
+
SimpleJsonapi
|
206
|
+
.render_resource(order, serializer: serializer_class)
|
207
|
+
.dig(:data, :relationships, :products, :data, 0)
|
208
|
+
end
|
209
|
+
|
210
|
+
it "infers the serializer by default" do
|
211
|
+
assert_equal "products", data_for(order, OrderInferringSerializer)[:type]
|
212
|
+
end
|
213
|
+
|
214
|
+
it "accepts a serializer class" do
|
215
|
+
assert_equal "another_product", data_for(order, OrderClassSerializer)[:type]
|
216
|
+
end
|
217
|
+
|
218
|
+
it "accepts a serializer class name" do
|
219
|
+
assert_equal "another_product", data_for(order, OrderStringSerializer)[:type]
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
describe "tricky situations" do
|
224
|
+
it "handles circular relationships" do
|
225
|
+
order_1, order_2 = Array.new(2) { Order.new }
|
226
|
+
order_1.products = [order_2]
|
227
|
+
order_2.products = [order_1]
|
228
|
+
|
229
|
+
SimpleJsonapi.render_resource(order_1)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe "documentation" do
|
234
|
+
class OrderDocSerializer < SimpleJsonapi::Serializer
|
235
|
+
has_one :customer
|
236
|
+
has_one :recipient, description: "the recipient"
|
237
|
+
has_many :products
|
238
|
+
has_many :shipments, description: "the shipments"
|
239
|
+
end
|
240
|
+
|
241
|
+
it "builds a has_one relationship without documentation" do
|
242
|
+
rel_defn = OrderDocSerializer.definition.relationship_definitions[:customer]
|
243
|
+
assert_nil rel_defn.description
|
244
|
+
end
|
245
|
+
|
246
|
+
it "stores the description of a has_one relationship" do
|
247
|
+
rel_defn = OrderDocSerializer.definition.relationship_definitions[:recipient]
|
248
|
+
assert_equal "the recipient", rel_defn.description
|
249
|
+
end
|
250
|
+
|
251
|
+
it "builds a has_many relationship without documentation" do
|
252
|
+
rel_defn = OrderDocSerializer.definition.relationship_definitions[:products]
|
253
|
+
assert_nil rel_defn.description
|
254
|
+
end
|
255
|
+
|
256
|
+
it "stores the description of a has_many relationship" do
|
257
|
+
rel_defn = OrderDocSerializer.definition.relationship_definitions[:shipments]
|
258
|
+
assert_equal "the shipments", rel_defn.description
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class SortingTest < Minitest::Spec
|
4
|
+
class Customer < TestModel
|
5
|
+
attr_accessor :name, :orders
|
6
|
+
end
|
7
|
+
|
8
|
+
class Order < TestModel
|
9
|
+
attr_accessor :products, :order_number
|
10
|
+
end
|
11
|
+
|
12
|
+
class Product < TestModel
|
13
|
+
attr_accessor :name
|
14
|
+
end
|
15
|
+
|
16
|
+
class CustomerSerializer < SimpleJsonapi::Serializer
|
17
|
+
attribute :name
|
18
|
+
has_many :orders do
|
19
|
+
data do |customer|
|
20
|
+
resources = customer.orders.sort_by { |o| o.send(@sort&.first&.field || :id) }
|
21
|
+
resources.reverse! if @sort&.first&.desc?
|
22
|
+
resources
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class OrderSerializer < SimpleJsonapi::Serializer
|
28
|
+
attribute :order_number
|
29
|
+
has_many :products do
|
30
|
+
data do |order|
|
31
|
+
order.products.sort_by { |p| p.send(@sort&.first&.field || :id) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class ProductSerializer < SimpleJsonapi::Serializer
|
37
|
+
attribute :name
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:customer) { Customer.new(id: 1, name: "John Henry", orders: [order_10, order_11]) }
|
41
|
+
let(:order_10) { Order.new(id: 10, order_number: 202, products: [spike, railtie]) }
|
42
|
+
let(:order_11) { Order.new(id: 11, order_number: 101, products: [spike, hammer]) }
|
43
|
+
let(:spike) { Product.new(id: 21, name: "spike") }
|
44
|
+
let(:railtie) { Product.new(id: 22, name: "railtie") }
|
45
|
+
let(:hammer) { Product.new(id: 23, name: "hammer") }
|
46
|
+
|
47
|
+
def render_customer(sort)
|
48
|
+
SimpleJsonapi.render_resource(customer, include: "orders,orders.products", sort_related: sort)
|
49
|
+
end
|
50
|
+
|
51
|
+
describe "Sorting top-level relationships" do
|
52
|
+
it "provides the relationship with an empty field list" do
|
53
|
+
# serializer's default is to sort by id: [10, 11]
|
54
|
+
serialized = render_customer(nil)
|
55
|
+
assert_equal(["10", "11"], serialized.dig(:data, :relationships, :orders, :data).map { |o| o[:id] })
|
56
|
+
end
|
57
|
+
|
58
|
+
it "provides the relationship with an ascending sort spec" do
|
59
|
+
# sort by order number: [101, 202]
|
60
|
+
serialized = render_customer(orders: "order_number")
|
61
|
+
assert_equal(["11", "10"], serialized.dig(:data, :relationships, :orders, :data).map { |o| o[:id] })
|
62
|
+
end
|
63
|
+
|
64
|
+
it "provides the relationship with a descending sort spec" do
|
65
|
+
# sort by order number: [202, 101]
|
66
|
+
serialized = render_customer(orders: "-order_number")
|
67
|
+
assert_equal(["10", "11"], serialized.dig(:data, :relationships, :orders, :data).map { |o| o[:id] })
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "Sorting lower-level relationships" do
|
72
|
+
it "provides a blank sort spec" do
|
73
|
+
# products for order 10: [spike, railtie] == [21, 22]
|
74
|
+
serialized = render_customer(orders: "id", products: "name")
|
75
|
+
included_order = serialized[:included].find { |obj| obj[:type] == "orders" && obj[:id] == "10" }
|
76
|
+
assert_equal(["21", "22"], included_order.dig(:relationships, :products, :data).map { |p| p[:id] })
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|