yaks 0.8.1 → 0.8.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +102 -18
- data/lib/yaks/format.rb +4 -1
- data/lib/yaks/runner.rb +3 -3
- data/lib/yaks/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2011212cb9c579cebb6ee58228407bdfde224829
|
4
|
+
data.tar.gz: 96d967888e80337c38850db63923bac9a74446e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6aa331742aabedbf57d46182d72029664f385af6d844bc92b1180e3aa8d0e956782deab1d2406ef8cebac36dbbea57189675a6d558d992dae6f37fd1bf12ad6
|
7
|
+
data.tar.gz: c53bec9f2219b58e7f2d6cd16b0966ec1ceeadc9507556c21569746e753e43fa6e65e7bd099f2b6cbe6d5943476824eea28ec6118beeffbef1665e5bb210cb9e
|
data/README.md
CHANGED
@@ -37,8 +37,7 @@ supporting hypermedia formats in Ruby.
|
|
37
37
|
Yaks can be used in production today, as we do, but until 1.0 is
|
38
38
|
released there will regularly be breaking changes, as we figure out
|
39
39
|
the best way to do things. These are all documented clearly in the
|
40
|
-
[changelog](/CHANGELOG.md).
|
41
|
-
exact version number.
|
40
|
+
[changelog](/CHANGELOG.md).
|
42
41
|
|
43
42
|
## Concepts
|
44
43
|
|
@@ -301,9 +300,14 @@ class FooMapper
|
|
301
300
|
end
|
302
301
|
```
|
303
302
|
|
304
|
-
The env hash will be available to all mappers, so you can use this to
|
303
|
+
The env hash will be available to all mappers, so you can use this to
|
304
|
+
pass around context. In particular context related to the current HTTP
|
305
|
+
request, e.g. the current logged in user, which is why the recommended
|
306
|
+
use is to pass in the Rack environment.
|
305
307
|
|
306
|
-
If `env` contains a `HTTP_ACCEPT` key (Rack's way of representing the
|
308
|
+
If `env` contains a `HTTP_ACCEPT` key (Rack's way of representing the
|
309
|
+
`Accept` header), Yaks will return the format that most closely
|
310
|
+
matches what was requested.
|
307
311
|
|
308
312
|
## Namespace
|
309
313
|
|
@@ -385,23 +389,43 @@ class ErrorMapper < Yaks::Mapper
|
|
385
389
|
end
|
386
390
|
```
|
387
391
|
|
388
|
-
## Resources
|
392
|
+
## Resources, Formatters, Serializers
|
389
393
|
|
390
|
-
Yaks uses an intermediate "Resource" representation to support
|
394
|
+
Yaks uses an intermediate "Resource" representation to support
|
395
|
+
multiple output formats. A mapper turns a domain model into a
|
396
|
+
`Yaks::Resource`. A formatter (e.g. `Yaks::Format::Hal`) takes
|
397
|
+
the resource and outputs the structure of the target format.
|
391
398
|
|
392
|
-
|
399
|
+
Finally a serializer will take this document structure and turn it
|
400
|
+
into a string. For JSON documents the intermediate format consists of
|
401
|
+
Ruby primitives like arrays and hashes. HTML/XML based formats on the
|
402
|
+
other hand return a [Hexp::Node](https://github.com/plexus/hexp).
|
393
403
|
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
404
|
+
For JSON based format there's an extra step between `format` and
|
405
|
+
`serialize` called `primitivize`, this way Ruby objects which don't
|
406
|
+
have an equivalent in the JSON spec, like `Symbol` or `Date`, can be
|
407
|
+
turned into objects that are representable in JSON. See
|
408
|
+
[Primitiver](#primitivizer).
|
409
|
+
|
410
|
+
## Formats
|
399
411
|
|
400
|
-
|
412
|
+
Below follows a brief overview of formats that are available in
|
413
|
+
Yaks. The maturity of these formats varies, since we depend on people
|
414
|
+
that use a certain format actively to contribute. Implementing formats
|
415
|
+
is in generally straightforward, and consists mostly of deciding how
|
416
|
+
the attributes, links, forms, of a `Yaks::Resource` should be
|
417
|
+
represented. Depending on the format this might be a subject for
|
418
|
+
debate. We welcome these discussions, and if your opinion differs from
|
419
|
+
what ends up in Yaks, it should be trivial to change these
|
420
|
+
representations for your use case.
|
401
421
|
|
402
422
|
### HAL
|
403
423
|
|
404
|
-
This is the default. In HAL one decides when building an API which
|
424
|
+
This is the default. In HAL one decides when building an API which
|
425
|
+
links can only be singular (e.g. self), and which are always
|
426
|
+
represented as an array. Yaks defaults to singular as I've found it to
|
427
|
+
be the most common case. If you want specific links to be plural, then
|
428
|
+
configure their rel href as such.
|
405
429
|
|
406
430
|
```ruby
|
407
431
|
hal = Yaks.new do
|
@@ -409,17 +433,43 @@ hal = Yaks.new do
|
|
409
433
|
end
|
410
434
|
```
|
411
435
|
|
412
|
-
CURIEs are not explicitly supported (yet), but it's possible to use
|
436
|
+
CURIEs are not explicitly supported (yet), but it's possible to use
|
437
|
+
them with some manual effort.
|
438
|
+
|
439
|
+
The line between a singular resource and a collection is fuzzy in
|
440
|
+
HAL. To stick close to the spec you're best to create your own
|
441
|
+
singular types that represent collections, rather than rendering a top
|
442
|
+
level CollectionResource.
|
443
|
+
|
444
|
+
### HTML
|
445
|
+
|
446
|
+
The hypermedia format *par excellence*. Yaks can generate a version of
|
447
|
+
your API, including links and forms, that is usable straight from a
|
448
|
+
standard web browser. This allows API interactions to be developed and
|
449
|
+
tested independent from any client application.
|
413
450
|
|
414
|
-
|
451
|
+
If you let Yaks handle your content type negotiation (i.e. pass it the
|
452
|
+
rack env, and honour the content type it detects, see
|
453
|
+
[integration](#integration), simply opening a browser and pointing it
|
454
|
+
at your API entry point should do the trick.
|
415
455
|
|
416
456
|
### JSON-API
|
417
457
|
|
458
|
+
The JSON-API spec has evolved since the Yaks formatter was
|
459
|
+
implemented. It is also not the most suitable format for Yaks
|
460
|
+
feature-set due to its strong convention-driven nature and weak
|
461
|
+
support for hypermedia.
|
462
|
+
|
463
|
+
If you would like to see better JSON-API support, get in touch. We
|
464
|
+
might be able to work something out.
|
465
|
+
|
418
466
|
```ruby
|
419
467
|
default_format :json_api
|
420
468
|
```
|
421
469
|
|
422
|
-
JSON-API has no concept of outbound links, so these will not be
|
470
|
+
JSON-API has no concept of outbound links, so these will not be
|
471
|
+
rendered. Instead the key will be inferred from the mapper class name
|
472
|
+
by default. This can be changed per mapper:
|
423
473
|
|
424
474
|
```ruby
|
425
475
|
class AnimalMapper
|
@@ -524,7 +574,9 @@ yaks = Yaks.new do
|
|
524
574
|
end
|
525
575
|
```
|
526
576
|
|
527
|
-
|
577
|
+
<a id="primitivizer">
|
578
|
+
|
579
|
+
## Primitivizer
|
528
580
|
|
529
581
|
For JSON based formats, the "syntax tree" is merely a structure of Ruby primitives that have a JSON equivalent. If your mappers return non-primitive attribute values, you can define how they should be converted. For example, JSON has no notion of dates. If your mappers return these types as attributes, then Yaks needs to know how to turn these into primitives. To add extra types, use `map_to_primitive`
|
530
582
|
|
@@ -550,6 +602,38 @@ end
|
|
550
602
|
|
551
603
|
Yaks by default "primitivizes" symbols (as strings), and classes that include Enumerable (as arrays).
|
552
604
|
|
605
|
+
|
606
|
+
<a id="integration">
|
607
|
+
|
608
|
+
## Integration
|
609
|
+
|
610
|
+
It is recommended to let Yaks handle the negotiation of media types,
|
611
|
+
so that consumer can request the format they prefer using an `Accept:`
|
612
|
+
header. To do this requires two steps: first make sure you pass the
|
613
|
+
rack env to Yaks, this way it will detect any `Accept` header and
|
614
|
+
honor it. While this is enough to get the correct serialized output,
|
615
|
+
it will likely be served up with the wrong `Content-Type` header by
|
616
|
+
your web framework.
|
617
|
+
|
618
|
+
To fix this, ask Yaks first for the "runner" for a given input, then
|
619
|
+
get the media type and serialized resource from the runner.
|
620
|
+
|
621
|
+
```ruby
|
622
|
+
# Tell your web framework about the supported formats
|
623
|
+
Yaks::Format.all.each do |format|
|
624
|
+
mime_type format.format_name, format.media_type
|
625
|
+
end
|
626
|
+
|
627
|
+
# one time Yaks configuration
|
628
|
+
yaks = Yaks.new {...}
|
629
|
+
|
630
|
+
# on each request
|
631
|
+
runner = yaks.runner(object, env: rack_env)
|
632
|
+
format = runner.format_name
|
633
|
+
output = runner.call
|
634
|
+
```
|
635
|
+
|
636
|
+
|
553
637
|
## Real World Usage
|
554
638
|
|
555
639
|
Yaks is used in production by [Ticketsolve](http://www.ticketsolve.com/). You can find an example API endpoint [here](http://leicestersquaretheatre.ticketsolve.com/api).
|
data/lib/yaks/format.rb
CHANGED
@@ -8,6 +8,8 @@ module Yaks
|
|
8
8
|
# @return [Hash]
|
9
9
|
attr_reader :options
|
10
10
|
|
11
|
+
attr_reader :env
|
12
|
+
|
11
13
|
def_delegators :resource, :links, :attributes, :subresources
|
12
14
|
|
13
15
|
protected :links, :attributes, :subresources, :options
|
@@ -20,7 +22,8 @@ module Yaks
|
|
20
22
|
|
21
23
|
# @param [Yaks::Resource] resource
|
22
24
|
# @return [Hash]
|
23
|
-
def call(resource,
|
25
|
+
def call(resource, env = {})
|
26
|
+
@env = env
|
24
27
|
serialize_resource(resource)
|
25
28
|
end
|
26
29
|
alias serialize call
|
data/lib/yaks/runner.rb
CHANGED
@@ -41,7 +41,7 @@ module Yaks
|
|
41
41
|
Format.by_name(options.fetch(:format) { default_format })
|
42
42
|
}
|
43
43
|
end
|
44
|
-
memoize :format_class
|
44
|
+
memoize :format_class, freezer: :noop
|
45
45
|
|
46
46
|
def steps
|
47
47
|
[[ :map, mapper ],
|
@@ -61,7 +61,7 @@ module Yaks
|
|
61
61
|
def formatter
|
62
62
|
format_class.new(format_options_hash[format_name])
|
63
63
|
end
|
64
|
-
memoize :formatter
|
64
|
+
memoize :formatter, freezer: :noop
|
65
65
|
|
66
66
|
def primitivizer
|
67
67
|
proc do |input|
|
@@ -77,7 +77,7 @@ module Yaks
|
|
77
77
|
def serializer
|
78
78
|
serializers.fetch(format_class.serializer)
|
79
79
|
end
|
80
|
-
memoize :serializer
|
80
|
+
memoize :serializer, freezer: :noop
|
81
81
|
|
82
82
|
def hooks
|
83
83
|
config.hooks + options.fetch(:hooks, [])
|
data/lib/yaks/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yaks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Arne Brasseur
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02
|
11
|
+
date: 2015-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: inflection
|