yaks 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +158 -56
- data/Rakefile +1 -3
- data/ataru_setup.rb +72 -0
- data/find_missing_tests.rb +34 -0
- data/lib/yaks.rb +8 -10
- data/lib/yaks/breaking_changes.rb +4 -6
- data/lib/yaks/builder.rb +1 -1
- data/lib/yaks/changelog.rb +1 -1
- data/lib/yaks/collection_mapper.rb +8 -5
- data/lib/yaks/collection_resource.rb +0 -1
- data/lib/yaks/config.rb +17 -7
- data/lib/yaks/configurable.rb +20 -14
- data/lib/yaks/default_policy.rb +82 -33
- data/lib/yaks/format.rb +7 -3
- data/lib/yaks/format/collection_json.rb +4 -4
- data/lib/yaks/format/hal.rb +1 -2
- data/lib/yaks/format/halo.rb +2 -4
- data/lib/yaks/format/json_api.rb +46 -27
- data/lib/yaks/html5_forms.rb +0 -2
- data/lib/yaks/mapper.rb +5 -5
- data/lib/yaks/mapper/association.rb +7 -7
- data/lib/yaks/mapper/association_mapper.rb +2 -0
- data/lib/yaks/mapper/attribute.rb +10 -4
- data/lib/yaks/mapper/config.rb +2 -2
- data/lib/yaks/mapper/form.rb +4 -10
- data/lib/yaks/mapper/form/config.rb +16 -17
- data/lib/yaks/mapper/form/dynamic_field.rb +1 -1
- data/lib/yaks/mapper/form/field.rb +16 -7
- data/lib/yaks/mapper/form/field/option.rb +5 -4
- data/lib/yaks/mapper/form/fieldset.rb +1 -1
- data/lib/yaks/mapper/form/legend.rb +18 -0
- data/lib/yaks/mapper/has_many.rb +1 -0
- data/lib/yaks/mapper/link.rb +7 -4
- data/lib/yaks/null_resource.rb +4 -5
- data/lib/yaks/pipeline.rb +2 -2
- data/lib/yaks/primitivize.rb +3 -2
- data/lib/yaks/reader/hal.rb +12 -13
- data/lib/yaks/reader/json_api.rb +50 -33
- data/lib/yaks/resource.rb +6 -7
- data/lib/yaks/resource/form.rb +2 -12
- data/lib/yaks/resource/form/field.rb +4 -3
- data/lib/yaks/resource/form/field/option.rb +1 -1
- data/lib/yaks/resource/form/fieldset.rb +1 -1
- data/lib/yaks/resource/form/legend.rb +18 -0
- data/lib/yaks/resource/has_fields.rb +13 -7
- data/lib/yaks/resource/link.rb +1 -1
- data/lib/yaks/runner.rb +5 -2
- data/lib/yaks/serializer.rb +2 -3
- data/lib/yaks/util.rb +7 -8
- data/lib/yaks/version.rb +1 -1
- data/spec/acceptance/acceptance_spec.rb +53 -38
- data/spec/acceptance/json_shared_examples.rb +45 -12
- data/spec/acceptance/models.rb +1 -1
- data/spec/integration/dynamic_form_fields_spec.rb +0 -1
- data/spec/integration/fieldset_spec.rb +18 -20
- data/spec/integration/map_to_resource_spec.rb +6 -6
- data/spec/json/{confucius.collection.json → confucius.collection_json.json} +0 -0
- data/spec/json/confucius.json_api.json +43 -27
- data/spec/json/list_of_quotes.collection_json.json +43 -0
- data/spec/json/list_of_quotes.hal.json +18 -0
- data/spec/json/list_of_quotes.json_api.json +25 -0
- data/spec/json/youtypeitwepostit.collection_json.json +45 -0
- data/spec/spec_helper.rb +4 -3
- data/spec/support/classes_for_policy_testing.rb +38 -14
- data/spec/support/deep_eql.rb +21 -18
- data/spec/support/pet_mapper.rb +2 -0
- data/spec/support/shared_contexts.rb +9 -9
- data/spec/unit/yaks/builder_spec.rb +41 -18
- data/spec/unit/yaks/collection_mapper_spec.rb +22 -19
- data/spec/unit/yaks/collection_resource_spec.rb +16 -8
- data/spec/unit/yaks/config_spec.rb +215 -19
- data/spec/unit/yaks/configurable_spec.rb +66 -7
- data/spec/unit/yaks/default_policy/derive_mapper_from_collection_spec.rb +47 -0
- data/spec/unit/yaks/default_policy/derive_mapper_from_item_spec.rb +114 -0
- data/spec/unit/yaks/default_policy/derive_mapper_from_object_spec.rb +29 -71
- data/spec/unit/yaks/default_policy_spec.rb +4 -5
- data/spec/unit/yaks/format/collection_json_spec.rb +35 -36
- data/spec/unit/yaks/format/hal_spec.rb +3 -3
- data/spec/unit/yaks/format/json_api_spec.rb +109 -68
- data/spec/unit/yaks/format_spec.rb +34 -0
- data/spec/unit/yaks/fp/callable_spec.rb +5 -3
- data/spec/unit/yaks/mapper/association_mapper_spec.rb +22 -4
- data/spec/unit/yaks/mapper/association_spec.rb +23 -11
- data/spec/unit/yaks/mapper/attribute_spec.rb +46 -7
- data/spec/unit/yaks/mapper/config_spec.rb +2 -3
- data/spec/unit/yaks/mapper/form/config_spec.rb +95 -0
- data/spec/unit/yaks/mapper/form/dynamic_field_spec.rb +30 -0
- data/spec/unit/yaks/mapper/form/field/option_spec.rb +48 -4
- data/spec/unit/yaks/mapper/form/field_spec.rb +43 -2
- data/spec/unit/yaks/mapper/form/fieldset_spec.rb +67 -8
- data/spec/unit/yaks/mapper/form/legend_spec.rb +52 -0
- data/spec/unit/yaks/mapper/form_spec.rb +84 -23
- data/spec/unit/yaks/mapper/has_many_spec.rb +39 -36
- data/spec/unit/yaks/mapper/has_one_spec.rb +28 -20
- data/spec/unit/yaks/mapper/link_spec.rb +68 -16
- data/spec/unit/yaks/mapper_spec.rb +118 -30
- data/spec/unit/yaks/null_resource_spec.rb +83 -52
- data/spec/unit/yaks/pipeline_spec.rb +101 -74
- data/spec/unit/yaks/primitivize_spec.rb +25 -6
- data/spec/unit/yaks/resource/form/field_spec.rb +5 -5
- data/spec/unit/yaks/resource/form/fieldset_spec.rb +7 -0
- data/spec/unit/yaks/resource/form/legend_spec.rb +8 -0
- data/spec/unit/yaks/resource/form_spec.rb +17 -37
- data/spec/unit/yaks/resource/has_fields_spec.rb +44 -3
- data/spec/unit/yaks/resource/link_spec.rb +11 -6
- data/spec/unit/yaks/resource_spec.rb +87 -98
- data/spec/unit/yaks/runner_spec.rb +112 -28
- data/spec/unit/yaks/serializer_spec.rb +1 -1
- data/spec/unit/yaks/util_spec.rb +30 -10
- data/spec/yaml/list_of_quotes.yaml +13 -0
- data/yaks.gemspec +21 -13
- metadata +129 -41
- data/lib/yaks/attributes.rb +0 -86
- data/lib/yaks/fp.rb +0 -26
- data/lib/yaks/identifier/link_relation.rb +0 -17
- data/resources/iana-link-relations.csv +0 -152
- data/spec/json/youtypeitwepostit.collection.json +0 -45
- data/spec/unit/yaks/attributes_spec.rb +0 -178
- data/spec/unit/yaks/fp_spec.rb +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8e26f0f65962ea64eee11346ede1401347525188
|
4
|
+
data.tar.gz: 40881b570c5b8145e79a92251a35275b62da9994
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9b4370186b9d44d56404df20e65bfb58bedd666b6bd5be2cb78684d1022ed74bb2df1a01c6381dc743c9769cadbdc3fcff441d52298108137a4fe60f873c2dab
|
7
|
+
data.tar.gz: 340ea7d369824f9ac7d0ea98e0995c0d4192b63c6a66f9faff2033b78b7b281d494c9044508c7a9bdd085e8a20ffb76b89a54716aef447c8824a27d3080a37ff
|
data/README.md
CHANGED
@@ -1,21 +1,21 @@
|
|
1
1
|
[![Gem Version](https://badge.fury.io/rb/yaks.png)][gem]
|
2
2
|
[![Build Status](https://secure.travis-ci.org/plexus/yaks.png?branch=master)][travis]
|
3
|
-
[![Dependency Status](https://gemnasium.com/plexus/yaks.png)][gemnasium]
|
4
3
|
[![Code Climate](https://codeclimate.com/github/plexus/yaks.png)][codeclimate]
|
5
4
|
[![Gitter](https://badges.gitter.im/Join Chat.svg)][gitter]
|
6
5
|
|
7
6
|
[gem]: https://rubygems.org/gems/yaks
|
8
7
|
[travis]: https://travis-ci.org/plexus/yaks
|
9
|
-
[gemnasium]: https://gemnasium.com/plexus/yaks
|
10
8
|
[codeclimate]: https://codeclimate.com/github/plexus/yaks
|
11
9
|
[gitter]: https://gitter.im/plexus/yaks?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge
|
12
10
|
|
13
11
|
# Yaks
|
14
12
|
|
15
|
-
|
13
|
+
<img align="left" src="https://raw.githubusercontent.com/plexus/yaks/master/logo.png">
|
16
14
|
|
17
15
|
The library that understands hypermedia.
|
18
16
|
|
17
|
+
**If you use Yaks please help out by filling out the [Yaks Users Survey](https://docs.google.com/forms/d/1sZB03Vf32igmNmJ7RP8mo8H4VZHcVIpSrUSbvx2xD8s/viewform)**
|
18
|
+
|
19
19
|
Yaks takes your data and transforms it into hypermedia formats such as
|
20
20
|
HAL, JSON-API, or HTML. It allows you to build APIs that are
|
21
21
|
discoverable and browsable. It is built from the ground up around
|
@@ -33,21 +33,48 @@ requested. These formats are presently supported:
|
|
33
33
|
* HALO
|
34
34
|
* Transit
|
35
35
|
|
36
|
-
##
|
37
|
-
|
38
|
-
|
39
|
-
[
|
40
|
-
|
41
|
-
|
36
|
+
## Table of Contents
|
37
|
+
|
38
|
+
- [State of Development](#user-content-state-of-development)
|
39
|
+
- [Concepts](#user-content-concepts)
|
40
|
+
- [Mappers](#user-content-mappers)
|
41
|
+
- [Attributes](#user-content-attributes)
|
42
|
+
- [Forms](#user-content-forms)
|
43
|
+
- [Filtering](#user-content-filtering)
|
44
|
+
- [Links](#user-content-links)
|
45
|
+
- [Associations](#user-content-associations)
|
46
|
+
- [Calling Yaks](#user-content-calling-yaks)
|
47
|
+
- [Rack env](#user-content-rack-env)
|
48
|
+
- [Namespace](#user-content-namespace)
|
49
|
+
- [Custom attribute/link/subresource handling](#user-content-custom-attributelinksubresource-handling)
|
50
|
+
- [Resources, Formatters, Serializers](#user-content-resources-formatters-serializers)
|
51
|
+
- [Formats](#user-content-formats)
|
52
|
+
- [HAL](#user-content-hal)
|
53
|
+
- [HTML](#user-content-html)
|
54
|
+
- [JSON-API](#user-content-json-api)
|
55
|
+
- [Collection+JSON](#user-content-collection-json)
|
56
|
+
- [Transit](#user-content-transit)
|
57
|
+
- [Hooks](#user-content-hooks)
|
58
|
+
- [Policy over Configuration](#user-content-policy-over-configuration)
|
59
|
+
- [derive_mapper_from_object](#user-content-derive_mapper_from_object)
|
60
|
+
- [derive_mapper_from_association](#user-content-derive_mapper_from_association)
|
61
|
+
- [derive_rel_from_association](#user-content-derive_rel_from_association)
|
62
|
+
- [Primitivizer](#user-content-primitivizer)
|
63
|
+
- [Integration](#user-content-integration)
|
64
|
+
- [Real World Usage](#user-content-real-world-usage)
|
65
|
+
- [Demo](#user-content-demo)
|
66
|
+
- [Cookbook](#user-content-cookbook)
|
67
|
+
- [Standards Based](#user-content-standards-based)
|
68
|
+
- [How to contribute](#user-content-how-to-contribute)
|
69
|
+
- [License](#user-content-license)
|
42
70
|
|
43
|
-
|
44
|
-
to grow and improve. The aim is to create *the reference* for
|
45
|
-
supporting hypermedia formats in Ruby.
|
71
|
+
## State of Development
|
46
72
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
73
|
+
Recent focus has been on stabilizing the core classes, improving
|
74
|
+
format support, and increasing test (mutation) coverage. We are
|
75
|
+
committed to a stable public API and semantic version. On the 0.x line
|
76
|
+
the minor version is bumped when non-backwards compatible changes are
|
77
|
+
introduced. After 1.x regular semver conventions will be used.
|
51
78
|
|
52
79
|
## Concepts
|
53
80
|
|
@@ -59,13 +86,13 @@ yaks = Yaks.new do
|
|
59
86
|
default_format :hal
|
60
87
|
rel_template 'http://api.example.com/rels/{rel}'
|
61
88
|
format_options(:hal, plural_links: [:copyright])
|
62
|
-
|
89
|
+
mapper_namespace ::MyAPI
|
63
90
|
json_serializer do |data|
|
64
|
-
|
91
|
+
JSON.dump(data)
|
65
92
|
end
|
66
93
|
end
|
67
94
|
|
68
|
-
yaks.call(
|
95
|
+
yaks.call(product)
|
69
96
|
```
|
70
97
|
|
71
98
|
Yaks performs this serialization in three steps
|
@@ -115,12 +142,12 @@ yaks = Yaks.new do
|
|
115
142
|
format_options(:hal, plural_links: [:copyright])
|
116
143
|
end
|
117
144
|
|
118
|
-
yaks.call(post, mapper: PostMapper, format: :hal)
|
145
|
+
yaks.call(post, mapper: ::PostMapper, format: :hal)
|
119
146
|
```
|
120
147
|
|
121
148
|
### Attributes
|
122
149
|
|
123
|
-
Use the `attributes` DSL
|
150
|
+
Use the `attribute` or `attributes` DSL methods to specify which attributes of your model you want to expose, as in the example above. You can override the `load_attribute` method to change how attributes are fetched from the model.
|
124
151
|
|
125
152
|
For example, if you are representing data that is stored in a Hash, you could do
|
126
153
|
|
@@ -134,12 +161,14 @@ class PostHashMapper < Yaks::Mapper
|
|
134
161
|
end
|
135
162
|
end
|
136
163
|
```
|
137
|
-
|
138
|
-
The default implementation will first try to find a matching method for an attribute on the mapper itself, and will then fall back to calling the actual model. So you can add extra 'virtual' attributes like so :
|
164
|
+
The `attribute` method may also take a block that will be called with the context of the mapper instance. The default implementation will use the block if provided, otherwise it will first try to find a matching method for an attribute on the mapper itself, and will then fall back to calling the actual model. So you can add extra 'virtual' attributes like so :
|
139
165
|
|
140
166
|
```ruby
|
141
167
|
class CommentMapper < Yaks::Mapper
|
142
|
-
attributes :
|
168
|
+
attributes :body, :date
|
169
|
+
attribute :id do
|
170
|
+
"Id-#{object.id}"
|
171
|
+
end
|
143
172
|
|
144
173
|
def date
|
145
174
|
object.created_at.strftime("at %I:%M%p")
|
@@ -176,7 +205,7 @@ rendering of forms, dynamic form sections, ...
|
|
176
205
|
You can override `#attributes`, or `#associations`.
|
177
206
|
|
178
207
|
```ruby
|
179
|
-
class SongMapper
|
208
|
+
class SongMapper < Yaks::Mapper
|
180
209
|
attributes :title, :duration, :lyrics
|
181
210
|
|
182
211
|
has_one :artist
|
@@ -257,7 +286,7 @@ confirming an order, the previously held cart is no longer valid, you
|
|
257
286
|
could use the IANA standard `invalidates` rel to communicate this.
|
258
287
|
|
259
288
|
``` ruby
|
260
|
-
class OrderMapper <
|
289
|
+
class OrderMapper < Yaks::Mapper
|
261
290
|
link :invalidates, '/api/cart', if: ->{ env['api.invalidate_cart'] }
|
262
291
|
end
|
263
292
|
```
|
@@ -296,10 +325,7 @@ it the data to be serialized, plus options.
|
|
296
325
|
When serializing, Yaks lets you pass in an `env` hash, which will be made available to all mappers.
|
297
326
|
|
298
327
|
```ruby
|
299
|
-
|
300
|
-
yaks.call(foo, env: my_env)
|
301
|
-
|
302
|
-
class FooMapper
|
328
|
+
class FooMapper < Yaks::Mapper
|
303
329
|
attributes :bar
|
304
330
|
|
305
331
|
def bar
|
@@ -308,6 +334,9 @@ class FooMapper
|
|
308
334
|
end
|
309
335
|
end
|
310
336
|
end
|
337
|
+
|
338
|
+
yaks = Yaks.new
|
339
|
+
yaks.call(foo, env: my_env)
|
311
340
|
```
|
312
341
|
|
313
342
|
The env hash will be available to all mappers, so you can use this to
|
@@ -327,7 +356,7 @@ Yaks by default will find your mappers for you if they follow the
|
|
327
356
|
naming convention of appending 'Mapper' to the model class name. This
|
328
357
|
(and all other "conventions") can be easily redefined though, see the
|
329
358
|
<a href="#policy">policy</a> section. If you have your mappers inside a
|
330
|
-
module, use `
|
359
|
+
module, use `mapper_namespace`.
|
331
360
|
|
332
361
|
```ruby
|
333
362
|
module API
|
@@ -339,7 +368,7 @@ module API
|
|
339
368
|
end
|
340
369
|
|
341
370
|
yaks = Yaks.new do
|
342
|
-
|
371
|
+
mapper_namespace API::Mappers
|
343
372
|
end
|
344
373
|
```
|
345
374
|
|
@@ -498,7 +527,9 @@ If you would like to see better JSON-API support, get in touch. We
|
|
498
527
|
might be able to work something out.
|
499
528
|
|
500
529
|
```ruby
|
501
|
-
|
530
|
+
Yaks.new do
|
531
|
+
default_format :json_api
|
532
|
+
end
|
502
533
|
```
|
503
534
|
|
504
535
|
JSON-API has no concept of outbound links, so these will not be
|
@@ -506,8 +537,8 @@ rendered. Instead the key will be inferred from the mapper class name
|
|
506
537
|
by default. This can be changed per mapper:
|
507
538
|
|
508
539
|
```ruby
|
509
|
-
class AnimalMapper
|
510
|
-
|
540
|
+
class AnimalMapper < Yaks::Mapper
|
541
|
+
type :pet
|
511
542
|
end
|
512
543
|
```
|
513
544
|
|
@@ -528,10 +559,12 @@ option can be used. It will map the specified form to a CJ template. Please
|
|
528
559
|
notice that CJ only allows one template per representation.
|
529
560
|
|
530
561
|
```ruby
|
531
|
-
|
562
|
+
Yaks.new do
|
563
|
+
default_format :collection_json
|
532
564
|
|
533
|
-
collection_json = Yaks.new do
|
534
|
-
|
565
|
+
collection_json = Yaks.new do
|
566
|
+
format_options :collection_json, template: :my_template_form
|
567
|
+
end
|
535
568
|
end
|
536
569
|
|
537
570
|
class PostMapper < Yaks::Mapper
|
@@ -589,10 +622,20 @@ In Yaks whenever missing values need to be inferred, like finding an unspecified
|
|
589
622
|
|
590
623
|
```ruby
|
591
624
|
yaks = Yaks.new do
|
625
|
+
mapper_for Post, SpecialMapper
|
626
|
+
|
592
627
|
derive_mapper_from_object do |model|
|
593
628
|
# ...
|
594
629
|
end
|
595
630
|
|
631
|
+
derive_mapper_from_collection do |collection|
|
632
|
+
# ...
|
633
|
+
end
|
634
|
+
|
635
|
+
derive_mapper_from_item do |model|
|
636
|
+
# ...
|
637
|
+
end
|
638
|
+
|
596
639
|
derive_type_from_mapper_class do |mapper_class|
|
597
640
|
# ...
|
598
641
|
end
|
@@ -607,15 +650,18 @@ yaks = Yaks.new do
|
|
607
650
|
end
|
608
651
|
```
|
609
652
|
|
653
|
+
Note that within these blocks, you may call `super()` which would call
|
654
|
+
the default implementation.
|
655
|
+
|
610
656
|
You can also subclass or create from scratch your own policy class
|
611
657
|
|
612
658
|
```ruby
|
613
|
-
class MyPolicy < DefaultPolicy
|
659
|
+
class MyPolicy < Yaks::DefaultPolicy
|
614
660
|
#...
|
615
661
|
end
|
616
662
|
|
617
663
|
yaks = Yaks.new do
|
618
|
-
|
664
|
+
policy_class MyPolicy
|
619
665
|
end
|
620
666
|
```
|
621
667
|
|
@@ -632,11 +678,35 @@ yaks.call(array_of_widgets, mapper: MyCollectionMapper, item_mapper: WidgetMappe
|
|
632
678
|
```
|
633
679
|
|
634
680
|
If the mapper is left unspecified, Yaks will inspect whatever you pass
|
635
|
-
it
|
681
|
+
it. First it will test the given object against the mappings defined using `mapper_for`.
|
682
|
+
If no mapper is found, it will call `derive_mapper_from_item` or `derive_mapper_from_collection`
|
683
|
+
depending on whether the given object is a collection or not. If the object responds
|
684
|
+
to `to_ary` it is considered a collection.
|
685
|
+
|
686
|
+
### mapper_for
|
687
|
+
|
688
|
+
This method allows you to define a one-to-one mapping between a mapping rule and a mapper class.
|
689
|
+
During the lookup, Yaks will check if any mapping rule matches the given object using the `#===`
|
690
|
+
operator.
|
691
|
+
|
692
|
+
Here are a few examples on how to use it:
|
693
|
+
```ruby
|
694
|
+
yaks = Yaks.new do
|
695
|
+
mapper_for(:home, HomeMapper)
|
696
|
+
mapper_for(Post, SpecialMapper)
|
697
|
+
mapper_for(->(author) { author.respond_to?(:name) && author.name == 'doh' }, AuthorMapper)
|
698
|
+
end
|
699
|
+
|
700
|
+
yaks.call(:home) # would map using HomeMapper
|
701
|
+
yaks.call(Post.new) # would map using PostMapper
|
702
|
+
yaks.call(Author.new(name: 'doh')) # would map using AuthorMapper
|
703
|
+
```
|
704
|
+
|
705
|
+
### derive_mapper_from_collection
|
706
|
+
This method will try various constant lookups based on naming. These all happen
|
636
707
|
in the configured namespace, which defaults to the Ruby top level.
|
637
708
|
|
638
|
-
If the object
|
639
|
-
the first object in the collection has a class of `Widget`, and the
|
709
|
+
If the first object in the collection has a class of `Widget`, and the
|
640
710
|
configured namespace is `API`, then these are tried in turn
|
641
711
|
|
642
712
|
* `API::WidgetCollectionMapper`
|
@@ -649,13 +719,35 @@ it's important that empty collections are handled by the right mapper
|
|
649
719
|
(e.g. to set a specific `self` or `profile` link), then you have to be
|
650
720
|
explicit.
|
651
721
|
|
652
|
-
|
653
|
-
|
654
|
-
|
722
|
+
### derive_mapper_from_item
|
723
|
+
|
724
|
+
When using this method, the lookup happens based on the class name,
|
725
|
+
and will traverse up the class hierarchy in the configured namespace if
|
726
|
+
no suitable mapper is found. Take the following
|
727
|
+
code:
|
728
|
+
```ruby
|
729
|
+
module Stuff
|
730
|
+
class Thing ; end
|
731
|
+
class Widget < Thing ; end
|
732
|
+
end
|
733
|
+
```
|
734
|
+
The lookup we'll be done as followed.
|
735
|
+
|
736
|
+
* If the `namespace` option is set (to `Mappers` for example):
|
737
|
+
* `Mappers::Stuff::WidgetMapper`
|
738
|
+
* `Mappers::Stuff::ThingMapper`
|
739
|
+
* `Mappers::Stuff::ObjectMapper`
|
740
|
+
* `Mappers::Stuff::BasicObjectMapper`
|
741
|
+
* `Mappers::WidgetMapper`
|
742
|
+
* `Mappers::ThingMapper`
|
655
743
|
|
656
|
-
* `
|
657
|
-
* `
|
658
|
-
* `
|
744
|
+
* If the `namespace` option is not set:
|
745
|
+
* `Stuff::WidgetMapper`
|
746
|
+
* `Stuff::ThingMapper`
|
747
|
+
* `Stuff::ObjectMapper`
|
748
|
+
* `Stuff::BasicObjectMapper`
|
749
|
+
* `WidgetMapper`
|
750
|
+
* `ThingMapper`
|
659
751
|
|
660
752
|
If none of these are found an error is raised.
|
661
753
|
|
@@ -695,10 +787,13 @@ yaks = Yaks.new do
|
|
695
787
|
rel_template "http://api.example.com/rel/{rel}"
|
696
788
|
end
|
697
789
|
|
698
|
-
|
790
|
+
class MyMapper < Yaks::Mapper
|
791
|
+
# rel: "http://api.example.com/rel/widgets"
|
792
|
+
has_many :widgets
|
699
793
|
|
700
|
-
|
701
|
-
has_one :widget
|
794
|
+
# rel: "http://api.example.com/rel/widget"
|
795
|
+
has_one :widget
|
796
|
+
end
|
702
797
|
```
|
703
798
|
|
704
799
|
<a id="primitivizer"></a>
|
@@ -752,10 +847,10 @@ Yaks::Format.all.each do |format|
|
|
752
847
|
end
|
753
848
|
|
754
849
|
# one time Yaks configuration
|
755
|
-
yaks = Yaks.new
|
850
|
+
yaks = Yaks.new
|
756
851
|
|
757
852
|
# on each request
|
758
|
-
runner = yaks.runner(
|
853
|
+
runner = yaks.runner(post, env: rack_env)
|
759
854
|
format = runner.format_name
|
760
855
|
output = runner.call
|
761
856
|
```
|
@@ -763,12 +858,19 @@ output = runner.call
|
|
763
858
|
|
764
859
|
## Real World Usage
|
765
860
|
|
766
|
-
Yaks is used in production by
|
861
|
+
Yaks is used in production by
|
862
|
+
|
863
|
+
* [Ticketsolve](http://www.ticketsolve.com/). You can find an example API endpoint [here](http://leicestersquaretheatre.ticketsolve.com/api).
|
864
|
+
* Advertile Mobile for their product AppBounty (internal API)
|
767
865
|
|
768
866
|
## Demo
|
769
867
|
|
770
868
|
You can find an outdated example app at [Yakports](https://github.com/plexus/yakports), or browse the HAL api directly using the [HAL browser](http://yaks-airports.herokuapp.com/browser.html).
|
771
869
|
|
870
|
+
## Cookbook
|
871
|
+
|
872
|
+
See the [cookbook](COOKBOOK.md) for some usage examples taking from a real world app.
|
873
|
+
|
772
874
|
## Standards Based
|
773
875
|
|
774
876
|
Yaks is based on internet standards, including
|
@@ -781,7 +883,7 @@ Yaks is based on internet standards, including
|
|
781
883
|
|
782
884
|
## How to contribute
|
783
885
|
|
784
|
-
Run the tests, the examples, try it with your own stuff and leave your impressions in the issues.
|
886
|
+
Run the tests, the examples, try it with your own stuff and leave your impressions in the issues.
|
785
887
|
|
786
888
|
To fix a bug
|
787
889
|
|
data/Rakefile
CHANGED
@@ -58,8 +58,6 @@ task :mutant_chunked do
|
|
58
58
|
# >> Yaks::Format::Transit::ReadHandler
|
59
59
|
# >> Yaks::Format::Transit::WriteHandler
|
60
60
|
# >> Yaks::HTML5Forms
|
61
|
-
# >> Yaks::Identifier
|
62
|
-
# >> Yaks::Identifier::LinkRelation
|
63
61
|
# >> Yaks::IllegalStateError
|
64
62
|
# >> Yaks::Mapper
|
65
63
|
# >> Yaks::Mapper::Association
|
@@ -85,7 +83,7 @@ task :mutant_chunked do
|
|
85
83
|
# Yaks::Resource::Form::Field,
|
86
84
|
# Yaks::Resource::Form::Field::Option,
|
87
85
|
# Yaks::Resource::Form::Fieldset,
|
88
|
-
#Yaks::Resource::Link,
|
86
|
+
# Yaks::Resource::Link,
|
89
87
|
Yaks::Resource::HasFields,
|
90
88
|
# >> Yaks::Runner
|
91
89
|
# >> Yaks::RuntimeError
|
data/ataru_setup.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
# "Require your project source code, with the correct path"
|
2
|
+
|
3
|
+
require "yaks"
|
4
|
+
require "hamster"
|
5
|
+
|
6
|
+
Post = Struct.new(:id, :title, :author, :comments)
|
7
|
+
Author = Struct.new(:name)
|
8
|
+
|
9
|
+
module MyAPI
|
10
|
+
Product = Struct.new(:id, :label)
|
11
|
+
|
12
|
+
class ProductMapper < Yaks::Mapper
|
13
|
+
attributes :id, :label
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class AuthorMapper < Yaks::Mapper
|
18
|
+
end
|
19
|
+
|
20
|
+
class CommentMapper < Yaks::Mapper
|
21
|
+
end
|
22
|
+
|
23
|
+
class PostMapper < Yaks::Mapper
|
24
|
+
link :self, '/api/posts/{id}'
|
25
|
+
|
26
|
+
attributes :id, :title
|
27
|
+
|
28
|
+
has_one :author
|
29
|
+
has_many :comments
|
30
|
+
end
|
31
|
+
|
32
|
+
class HomeMapper < Yaks::Mapper; end
|
33
|
+
|
34
|
+
class SpecialMapper < Yaks::Mapper; end
|
35
|
+
|
36
|
+
module Setup
|
37
|
+
def setup
|
38
|
+
# Do some nice setup that is run before every snippet
|
39
|
+
# If you'd like to use instance variables define them here, e.g
|
40
|
+
# @important_variable_i_will_use_in_my_code_snippets = true
|
41
|
+
end
|
42
|
+
|
43
|
+
def teardown
|
44
|
+
# Do some cleanup that is run after every snippet
|
45
|
+
end
|
46
|
+
|
47
|
+
# If you like local variables you can define methods, e.g
|
48
|
+
# def number_of_wishes
|
49
|
+
# 101
|
50
|
+
# end
|
51
|
+
|
52
|
+
def my_env
|
53
|
+
{'something' => true}
|
54
|
+
end
|
55
|
+
alias_method :rack_env, :my_env
|
56
|
+
|
57
|
+
def post
|
58
|
+
Post.new(7, "Yaks is Al Dente", nil, [])
|
59
|
+
end
|
60
|
+
alias_method :foo, :post
|
61
|
+
|
62
|
+
def product
|
63
|
+
MyAPI::Product.new(42, "Shiny thing")
|
64
|
+
end
|
65
|
+
|
66
|
+
# # Tell your web framework about the supported formats
|
67
|
+
# Yaks::Format.all.each do |format|
|
68
|
+
# mime_type format.format_name, format.media_type
|
69
|
+
# end
|
70
|
+
def mime_type(*_args)
|
71
|
+
end
|
72
|
+
end
|