jei 0.1.0 → 0.2.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 +4 -4
- data/CHANGELOG.md +22 -0
- data/README.md +474 -6
- data/lib/jei.rb +15 -13
- data/lib/jei/attribute.rb +1 -19
- data/lib/jei/builders/attributes_node_builder.rb +5 -3
- data/lib/jei/builders/data_node_builder.rb +3 -1
- data/lib/jei/builders/document_builder.rb +24 -31
- data/lib/jei/builders/included_node_builder.rb +9 -6
- data/lib/jei/builders/links_node_builder.rb +3 -1
- data/lib/jei/builders/relationship_node_builder.rb +6 -4
- data/lib/jei/builders/relationships_node_builder.rb +5 -3
- data/lib/jei/builders/resource_node_builder.rb +13 -6
- data/lib/jei/document.rb +14 -10
- data/lib/jei/error.rb +4 -0
- data/lib/jei/field.rb +22 -0
- data/lib/jei/fieldset.rb +15 -0
- data/lib/jei/nodes/attribute_node.rb +14 -12
- data/lib/jei/nodes/attributes_node.rb +9 -7
- data/lib/jei/nodes/collection_data_node.rb +10 -8
- data/lib/jei/nodes/data_node.rb +14 -12
- data/lib/jei/nodes/document_node.rb +7 -5
- data/lib/jei/nodes/included_node.rb +9 -7
- data/lib/jei/nodes/json_api_node.rb +7 -5
- data/lib/jei/nodes/link_node.rb +17 -15
- data/lib/jei/nodes/links_node.rb +9 -7
- data/lib/jei/nodes/meta_node.rb +12 -10
- data/lib/jei/nodes/node.rb +13 -11
- data/lib/jei/nodes/relationship_node.rb +14 -12
- data/lib/jei/nodes/relationships_node.rb +9 -7
- data/lib/jei/nodes/resource_identifier_node.rb +13 -11
- data/lib/jei/nodes/resource_node.rb +7 -5
- data/lib/jei/path.rb +13 -12
- data/lib/jei/relationship.rb +8 -5
- data/lib/jei/serializer.rb +70 -12
- data/lib/jei/version.rb +1 -1
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7bf0d7bbd5077695a2e1219961576f894a5cd41f
|
4
|
+
data.tar.gz: 34cb6f17efada6cd82e01d23e8e67a16f7f2414e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 89a27cbfe0af409953efaf4da6d83f7a8f78659bf2ca58a40a22a1b148d8df1eb9d48a2b65e76f374b38598618a2fcf8310b425d001977ef0580a2a3186ed59b
|
7
|
+
data.tar.gz: 5972dc16d4c2df09654730607ffbfa92165751a12fc3c6284923b4516af448c987e2b7747f99c4d39bf7266bfb09a5915b0bec0b2496685049bd5388c78764e3
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
## HEAD
|
4
|
+
|
5
|
+
## 0.2.0 (2016-03-22)
|
6
|
+
|
7
|
+
* [ADD] Add `:fields` document build option for sparse fieldsets.
|
8
|
+
* [BREAKING] A relationship links `Proc` is no longer passed the context as
|
9
|
+
an argument. Update usages of `links: ->(_) {}` to `links: -> {}`.
|
10
|
+
* [ADD] Raise `Jei::Path::NameError` on bad relationship names.
|
11
|
+
* [BREAKING] Rename relationship option `no_data` to `data`. Take the
|
12
|
+
inverse of each occurance to update, e.g., change `no_data: true` to
|
13
|
+
`data: false`.
|
14
|
+
* [ADD] Add `:serializer` option to relationships to override the default
|
15
|
+
serializer class used.
|
16
|
+
* [CHANGE] Serializers are compared via a `(type, id)` tuple rather than
|
17
|
+
object identity.
|
18
|
+
* [FIX] Fix include usage when serializing a collection.
|
19
|
+
|
20
|
+
## 0.1.0 (2016-03-15)
|
21
|
+
|
22
|
+
* Initial release
|
data/README.md
CHANGED
@@ -17,6 +17,7 @@ install it manually.
|
|
17
17
|
```ruby
|
18
18
|
require 'jei'
|
19
19
|
|
20
|
+
# Create resource serializers.
|
20
21
|
class ArtistSerializer < Jei::Serializer
|
21
22
|
attribute :name
|
22
23
|
has_many :albums
|
@@ -26,18 +27,15 @@ class AlbumSerializer < Jei::Serializer
|
|
26
27
|
belongs_to :artist
|
27
28
|
end
|
28
29
|
|
29
|
-
class Artist < OpenStruct; end
|
30
|
-
class Album < OpenStruct; end
|
31
|
-
|
32
30
|
artist = Artist.new(id: 1, name: 'FIESTAR', albums: [])
|
33
|
-
|
31
|
+
artist.albums << Album.new(id: 1, artist: artist)
|
32
|
+
artist.albums << Album.new(id: 2, artist: artist)
|
34
33
|
|
34
|
+
# Build a JSON API document from the resource.
|
35
35
|
document = Jei::Document.build(artist)
|
36
36
|
document.to_json
|
37
37
|
```
|
38
38
|
|
39
|
-
This emits
|
40
|
-
|
41
39
|
```json
|
42
40
|
{
|
43
41
|
"data": {
|
@@ -57,3 +55,473 @@ This emits
|
|
57
55
|
}
|
58
56
|
}
|
59
57
|
```
|
58
|
+
|
59
|
+
### Serializers
|
60
|
+
|
61
|
+
A `Serializer` defines what attributes and relationships are serialized in a
|
62
|
+
document.
|
63
|
+
|
64
|
+
Jei uses reflection to automatically find the correct serailizer for a
|
65
|
+
resource. To do this, create a class that extends `Jei::Serializer` and name it
|
66
|
+
`#{resource.class.name}Serializer`. For example, an `Artist` resource would
|
67
|
+
have a matching serializer named `ArtistSerializer` in the global namespace.
|
68
|
+
|
69
|
+
```ruby
|
70
|
+
class Artist; end
|
71
|
+
class ArtistSerializer < Jei::Serializer; end
|
72
|
+
```
|
73
|
+
|
74
|
+
#### Attributes
|
75
|
+
|
76
|
+
Attributes represent model data. They are defined in a serializer by using the
|
77
|
+
`attribute` or `attributes` methods.
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
class AlbumSerializer < Jei::Serializer
|
81
|
+
# Attributes can be listed by name. Each name is used as an attribute key
|
82
|
+
# and its value is invoked by its name on the resource.
|
83
|
+
attributes :kind, :name
|
84
|
+
|
85
|
+
# Attributes can also be added individually.
|
86
|
+
attribute :released_on
|
87
|
+
|
88
|
+
# This is useful because `attribute` optionally takes a block. It can be
|
89
|
+
# used to rename an attribute in the document when the resource responds to
|
90
|
+
# a different name.
|
91
|
+
attribute(:release_date) { resource.released_on }
|
92
|
+
|
93
|
+
# Or it can be use to create entirely new attributes and values.
|
94
|
+
attribute :formatted_name do
|
95
|
+
date = resource.released_on.strftime('%Y.%m.%d')
|
96
|
+
"[#{date}] #{resource.name}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
album = Album.new(id: 1, kind: :ep, name: 'A Delicate Sense', released_on: Date.new(2016, 3, 9))
|
101
|
+
Jei::Document.build(album).to_json
|
102
|
+
```
|
103
|
+
|
104
|
+
```json
|
105
|
+
{
|
106
|
+
"data": {
|
107
|
+
"id": "1",
|
108
|
+
"type": "albums",
|
109
|
+
"attributes": {
|
110
|
+
"kind": "ep",
|
111
|
+
"name": "A Delicate Sense",
|
112
|
+
"released_on": "2016-03-09",
|
113
|
+
"release_date": "2016-03-09",
|
114
|
+
"formatted_name": "[2016.03.09] A Delicate Sense"
|
115
|
+
}
|
116
|
+
}
|
117
|
+
}
|
118
|
+
```
|
119
|
+
|
120
|
+
#### Relationships
|
121
|
+
|
122
|
+
Relationships describe how the primary resource relates to other resources. A
|
123
|
+
one-to-one relationship is defined by the `belongs_to` method, and a
|
124
|
+
one-to-many relationship, `has_many`.
|
125
|
+
|
126
|
+
The relationship names are invoked on the resource. A
|
127
|
+
belongs-to relationship returns a single resource, whereas has-many returns a
|
128
|
+
collection.
|
129
|
+
|
130
|
+
```ruby
|
131
|
+
class AlbumSerializer < Jei::Serializer
|
132
|
+
belongs_to :artist
|
133
|
+
has_many :tracks
|
134
|
+
|
135
|
+
# Like attributes, relationships can also take a block to override its value.
|
136
|
+
has_many :even_tracks do
|
137
|
+
resource.tracks.select { |t| t.id.even? }
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
class ArtistSerializer < Jei::Serializer; end
|
142
|
+
class TrackSerializer < Jei::Serializer; end
|
143
|
+
|
144
|
+
artist = Artist.new(id: 1)
|
145
|
+
tracks = [Track.new(id: 1), Track.new(id: 2)]
|
146
|
+
album = Album.new(id: 1, artist: artist, tracks: tracks)
|
147
|
+
|
148
|
+
Jei::Document.build(album).to_json
|
149
|
+
```
|
150
|
+
|
151
|
+
```json
|
152
|
+
{
|
153
|
+
"data": {
|
154
|
+
"id": "1",
|
155
|
+
"type": "albums",
|
156
|
+
"relationships": {
|
157
|
+
"artist": {
|
158
|
+
"data": { "id": "1", "type": "artists" }
|
159
|
+
},
|
160
|
+
"tracks": {
|
161
|
+
"data": [
|
162
|
+
{ "id": "1", "type": "tracks" },
|
163
|
+
{ "id": "2", "type": "tracks" }
|
164
|
+
]
|
165
|
+
},
|
166
|
+
"even_tracks": {
|
167
|
+
"data": [
|
168
|
+
{ "id": "2", "type": "tracks" }
|
169
|
+
]
|
170
|
+
}
|
171
|
+
}
|
172
|
+
}
|
173
|
+
}
|
174
|
+
```
|
175
|
+
|
176
|
+
##### Options
|
177
|
+
|
178
|
+
Each relationship object can be modified with the following options.
|
179
|
+
|
180
|
+
* `data`: (`Boolean`; default: `true`) Setting this to `false` supresses
|
181
|
+
building a data object with resource identifiers. Note that doing so does not
|
182
|
+
emit a valid JSON API document unless a links or meta object is present.
|
183
|
+
|
184
|
+
```ruby
|
185
|
+
class ArtistSerializer < Jei::Serializer
|
186
|
+
has_many :albums, data: false
|
187
|
+
end
|
188
|
+
|
189
|
+
albums = [Album.new(id: 1), Album.new(id: 2)]
|
190
|
+
artist = Artist.new(id: 1, albums: albums)
|
191
|
+
|
192
|
+
Jei::Document.build(artist).to_json
|
193
|
+
```
|
194
|
+
|
195
|
+
```json
|
196
|
+
{
|
197
|
+
"data": {
|
198
|
+
"id": "1",
|
199
|
+
"type": "artists",
|
200
|
+
"relationships": {
|
201
|
+
"albums": {}
|
202
|
+
}
|
203
|
+
}
|
204
|
+
}
|
205
|
+
```
|
206
|
+
|
207
|
+
* `links`: (`Proc -> Array<Jei::Link>`) This is for relationship level links.
|
208
|
+
The `Proc` must return a list of `Link`s and is run in the context of the
|
209
|
+
serializer.
|
210
|
+
|
211
|
+
```ruby
|
212
|
+
class ArtistSerializer < Jei::Serializer
|
213
|
+
has_many :albums, links: -> {
|
214
|
+
[Jei::Link.new(:related, "/#{type}/#{id}/albums")]
|
215
|
+
}
|
216
|
+
end
|
217
|
+
|
218
|
+
class AlbumSerializer < Jei::Serializer; end
|
219
|
+
|
220
|
+
albums = [Album.new(id: 1), Album.new(id: 2)]
|
221
|
+
artist = Artist.new(id: 1, albums: albums)
|
222
|
+
Jei::Document.build(artist).to_json
|
223
|
+
```
|
224
|
+
|
225
|
+
```json
|
226
|
+
{
|
227
|
+
"data": {
|
228
|
+
"id": "1",
|
229
|
+
"type": "artists",
|
230
|
+
"relationships": {
|
231
|
+
"albums": {
|
232
|
+
"data": [
|
233
|
+
{ "id": "1", "type": "albums" },
|
234
|
+
{ "id": "2", "type": "albums" }
|
235
|
+
],
|
236
|
+
"links": {
|
237
|
+
"related": "/artists/1/albums"
|
238
|
+
}
|
239
|
+
}
|
240
|
+
}
|
241
|
+
}
|
242
|
+
}
|
243
|
+
```
|
244
|
+
|
245
|
+
* `serializer`: (`Class`) Overrides the default serializer used for each
|
246
|
+
related resource.
|
247
|
+
|
248
|
+
```ruby
|
249
|
+
class RecordSerializer < Jei::Serializer
|
250
|
+
def type
|
251
|
+
'records'
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
255
|
+
class ArtistSerializer < Jei::Serializer
|
256
|
+
has_many :albums, serializer: RecordSerializer
|
257
|
+
end
|
258
|
+
|
259
|
+
artist = Artist.new(id: 1, albums: [Album.new(id: 1)])
|
260
|
+
Jei::Document.build(artist).to_json
|
261
|
+
```
|
262
|
+
|
263
|
+
```json
|
264
|
+
{
|
265
|
+
"data": {
|
266
|
+
"id": "1",
|
267
|
+
"type": "artists",
|
268
|
+
"relationships": {
|
269
|
+
"albums": {
|
270
|
+
"data": [
|
271
|
+
{ "id": "1", "type": "records" }
|
272
|
+
]
|
273
|
+
}
|
274
|
+
}
|
275
|
+
}
|
276
|
+
}
|
277
|
+
```
|
278
|
+
|
279
|
+
### Document
|
280
|
+
|
281
|
+
As seen in previous examples, `Jei::Document` represents a JSON API document.
|
282
|
+
After building the structure from a resource or collection of resources using
|
283
|
+
`Document.build`, it can be serialized to a Ruby hash (`#to_h`) or a JSON
|
284
|
+
string (`#to_json`).
|
285
|
+
|
286
|
+
#### Options
|
287
|
+
|
288
|
+
Top level objects can be added using the following options.
|
289
|
+
|
290
|
+
* `:fields`: (`Hash<String, String>`) A map of resource type-fields that define
|
291
|
+
sparse fieldsets. Keys are resource types, and fields are a comma-separated
|
292
|
+
list of field names. For example, `{ 'artists' => 'name,albums', 'albums' =>
|
293
|
+
'released_on' }`.
|
294
|
+
|
295
|
+
```ruby
|
296
|
+
class ArtistSerializer < Jei::Serializer
|
297
|
+
attributes :kind, :name
|
298
|
+
has_many :albums
|
299
|
+
end
|
300
|
+
|
301
|
+
artist = Artist.new(id: 1, kind: :group, name: 'FIESTAR', albums: [])
|
302
|
+
|
303
|
+
Jei::Document.build(artist, fields: { 'artists' => 'name' }).to_json
|
304
|
+
```
|
305
|
+
|
306
|
+
```json
|
307
|
+
{
|
308
|
+
"data": {
|
309
|
+
"id": "1",
|
310
|
+
"type": "artists",
|
311
|
+
"attributes": {
|
312
|
+
"name": "FIESTAR"
|
313
|
+
}
|
314
|
+
}
|
315
|
+
}
|
316
|
+
```
|
317
|
+
|
318
|
+
* `:include`: (`String`) A comma separated list of relationship paths. Each
|
319
|
+
path is a list of relationship names, separated by a period. For example, a
|
320
|
+
valid list of paths would be `artist,tracks.song`. The set of resources are
|
321
|
+
all unique resources on the include path.
|
322
|
+
|
323
|
+
```ruby
|
324
|
+
class ArtistSerializer < Jei::Serializer
|
325
|
+
attribute :name
|
326
|
+
has_many :albums
|
327
|
+
end
|
328
|
+
|
329
|
+
class AlbumSerializer < Jei::Serializer
|
330
|
+
attributes :name, :release_date
|
331
|
+
belongs_to :artist
|
332
|
+
has_many :tracks
|
333
|
+
end
|
334
|
+
|
335
|
+
class TrackSerializer < Jei::Serializer
|
336
|
+
attributes :position, :name
|
337
|
+
belongs_to :album
|
338
|
+
end
|
339
|
+
|
340
|
+
artist = Artist.new(id: 1, name: 'FIESTAR')
|
341
|
+
album1 = Album.new(id: 1, name: 'A Delicate Sense', release_date: '2016-03-09', artist: artist)
|
342
|
+
album2 = Album.new(id: 2, name: 'Black Label', release_date: '2015-03-04', artist: artist)
|
343
|
+
artist.albums = [album1, album2]
|
344
|
+
album1.tracks = [Track.new(id: 1, position: 2, name: 'Mirror', album: album1)]
|
345
|
+
album2.tracks = [Track.new(id: 2, position: 1, name: "You're Pitiful", album: album2)]
|
346
|
+
|
347
|
+
Jei::Document.build(artist, include: 'albums.tracks').to_json
|
348
|
+
```
|
349
|
+
|
350
|
+
```json
|
351
|
+
{
|
352
|
+
"data": {
|
353
|
+
"id": "1",
|
354
|
+
"type": "artists",
|
355
|
+
"attributes": {
|
356
|
+
"name": "FIESTAR"
|
357
|
+
},
|
358
|
+
"relationships": {
|
359
|
+
"albums": {
|
360
|
+
"data": [
|
361
|
+
{ "id": "1", "type": "albums" },
|
362
|
+
{ "id": "2", "type": "albums" }
|
363
|
+
]
|
364
|
+
}
|
365
|
+
}
|
366
|
+
},
|
367
|
+
"included": [
|
368
|
+
{
|
369
|
+
"id": "1",
|
370
|
+
"type": "albums",
|
371
|
+
"attributes": {
|
372
|
+
"name": "A Delicate Sense",
|
373
|
+
"release_date": "2016-03-09"
|
374
|
+
},
|
375
|
+
"relationships": {
|
376
|
+
"artist": {
|
377
|
+
"data": { "id": "1", "type": "artists" }
|
378
|
+
},
|
379
|
+
"tracks": {
|
380
|
+
"data": [
|
381
|
+
{ "id": "1", "type": "tracks" }
|
382
|
+
]
|
383
|
+
}
|
384
|
+
}
|
385
|
+
},
|
386
|
+
// ...
|
387
|
+
]
|
388
|
+
}
|
389
|
+
```
|
390
|
+
|
391
|
+
* `:jsonapi`: (`Boolean`) Includes a JSON API object in top level of the
|
392
|
+
document.
|
393
|
+
|
394
|
+
```ruby
|
395
|
+
Jei::Document.build(nil, jsonapi: true).to_json
|
396
|
+
```
|
397
|
+
|
398
|
+
```json
|
399
|
+
{
|
400
|
+
"jsonapi": {
|
401
|
+
"version": "1.0"
|
402
|
+
},
|
403
|
+
"data": null
|
404
|
+
}
|
405
|
+
```
|
406
|
+
|
407
|
+
* `:links`: (`Array<Link>`) Includes a links object in the top level of the
|
408
|
+
document.
|
409
|
+
|
410
|
+
```ruby
|
411
|
+
links = [
|
412
|
+
Jei::Link.new(:self, '/artists?page[number]=2'),
|
413
|
+
Jei::Link.new(:prev, '/artists?page[number]=1'),
|
414
|
+
Jei::Link.new(:next, '/artists?page[number]=3')
|
415
|
+
]
|
416
|
+
Jei::Document.build(nil, links: links).to_json
|
417
|
+
```
|
418
|
+
|
419
|
+
```json
|
420
|
+
{
|
421
|
+
"links": {
|
422
|
+
"self": "/artists?page[number]=2",
|
423
|
+
"prev": "/artists?page[number]=1",
|
424
|
+
"next": "/artists?page[number]=3"
|
425
|
+
},
|
426
|
+
"data": null
|
427
|
+
}
|
428
|
+
```
|
429
|
+
|
430
|
+
* `:meta`: (`Hash<Symbol, Object>`) Includes a meta object in the top level of
|
431
|
+
the document.
|
432
|
+
|
433
|
+
```ruby
|
434
|
+
Jei::Document.build(nil, meta: { total_pages: 10 }).to_json
|
435
|
+
```
|
436
|
+
|
437
|
+
```json
|
438
|
+
{
|
439
|
+
"meta": {
|
440
|
+
"total_pages": 10
|
441
|
+
},
|
442
|
+
"data": null
|
443
|
+
}
|
444
|
+
```
|
445
|
+
|
446
|
+
* `:serializer`: (`Class`) Overrides the default serializer used for the
|
447
|
+
primary resource.
|
448
|
+
|
449
|
+
```ruby
|
450
|
+
class SimpleArtistSerializer < Jei::Serializer
|
451
|
+
attribute :name
|
452
|
+
end
|
453
|
+
|
454
|
+
artist = Artist.new(id: 1, name: 'FIESTAR')
|
455
|
+
Jei::Document.build(artist, serializer: SimpleArtistSerializer).to_json
|
456
|
+
```
|
457
|
+
|
458
|
+
```json
|
459
|
+
{
|
460
|
+
"data": {
|
461
|
+
"id": "1",
|
462
|
+
"type": "artists",
|
463
|
+
"attributes": {
|
464
|
+
"name": "FIESTAR"
|
465
|
+
}
|
466
|
+
}
|
467
|
+
}
|
468
|
+
```
|
469
|
+
|
470
|
+
## Integration
|
471
|
+
|
472
|
+
Jei is not tied to any framework and can be integrated as a normal gem.
|
473
|
+
|
474
|
+
### Rails
|
475
|
+
|
476
|
+
The simplest usage with [Rails][rails] is to define a new renderer.
|
477
|
+
|
478
|
+
```ruby
|
479
|
+
# config/initializers/jei.rb
|
480
|
+
ActionController::Renderers.add(:jsonapi) do |resource, options|
|
481
|
+
document = Jei::Document.build(resource, options)
|
482
|
+
json = document.to_json
|
483
|
+
self.content_type = Mime::Type.lookup_by_extension(:jsonapi)
|
484
|
+
self.response_body = json
|
485
|
+
end
|
486
|
+
|
487
|
+
# config/initializers/mime_types.rb
|
488
|
+
Mime::Type.register 'application/vnd.api+json', :jsonapi
|
489
|
+
```
|
490
|
+
|
491
|
+
Serializers can be placed in `app/serializers`. Include Rails' url helpers to
|
492
|
+
have them conveniently accessible in the serializer context for links.
|
493
|
+
|
494
|
+
```ruby
|
495
|
+
# app/serializers/application_serializer.rb
|
496
|
+
class ApplicationSerializer < Jei::Serializer
|
497
|
+
include Rails.application.routes.url_helpers
|
498
|
+
end
|
499
|
+
|
500
|
+
# app/serializers/album_serializer.rb
|
501
|
+
class AlbumSerializer < ApplicationSerializer
|
502
|
+
attributes :kind, :name, :release_date
|
503
|
+
belongs_to :artist
|
504
|
+
end
|
505
|
+
|
506
|
+
# app/serializers/artist_serializer.rb
|
507
|
+
class ArtistSerializer < ApplicationSerializer
|
508
|
+
attributes :name
|
509
|
+
has_many :albums, data: false, links: -> {
|
510
|
+
[Jei::Link.new(:related, album_path(resource))]
|
511
|
+
}
|
512
|
+
end
|
513
|
+
```
|
514
|
+
|
515
|
+
Specify the `jsonapi` format defined earlier when rendering in a controller.
|
516
|
+
|
517
|
+
```ruby
|
518
|
+
# app/controllers/artists_controller.rb
|
519
|
+
class ArtistsController < ApplicationController
|
520
|
+
def show
|
521
|
+
artist = Artist.find(params[:id])
|
522
|
+
render jsonapi: artist, include: params[:include]
|
523
|
+
end
|
524
|
+
end
|
525
|
+
```
|
526
|
+
|
527
|
+
[rails]: http://rubyonrails.org/
|