simple_jsonapi 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|