oat 0.4.5 → 0.4.6
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/.travis.yml +0 -1
- data/CHANGELOG.md +121 -0
- data/README.md +74 -4
- data/lib/oat/adapters/hal.rb +18 -3
- data/lib/oat/adapters/json_api.rb +24 -5
- data/lib/oat/adapters/siren.rb +16 -1
- data/lib/oat/version.rb +1 -1
- data/spec/adapters/hal_spec.rb +18 -0
- data/spec/adapters/json_api_spec.rb +8 -2
- data/spec/adapters/siren_spec.rb +5 -0
- data/spec/fixtures.rb +23 -2
- metadata +19 -18
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a56613cc3b7d20d015369d97b0690153f7dcadf9
|
|
4
|
+
data.tar.gz: 2f786daef5e0b151100f7da50facb9654b31110d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fcedb948f276b849b4252a3955e8deac185062d5130154f188a252bb653a390cbd37b9a19fe11609b7eaa6fb4ef6f1e09dd7a9d37bc71870bdc90a519be69ed6
|
|
7
|
+
data.tar.gz: 70e5907449c358f1ebaa2b386b886abc37623b46200c785fc32202997d16bac2201a3323ebec0c9bdeb99ca20670c916448fe3c41c68fcc976737f0983782c16
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## [v0.4.5](https://github.com/ismasan/oat/tree/v0.4.5)
|
|
4
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.4.4...v0.4.5)
|
|
5
|
+
#### 09/07/14
|
|
6
|
+
- *Merged pull-request:* Fix serializer ampersand warning [\#43](https://github.com/ismasan/oat/pull/43) ([iainbeeston](https://github.com/iainbeeston))
|
|
7
|
+
|
|
8
|
+
- *Merged pull-request:* Update build matrix [\#42](https://github.com/ismasan/oat/pull/42) ([iainbeeston](https://github.com/iainbeeston))
|
|
9
|
+
|
|
10
|
+
- *Merged pull-request:* Update to rspec3 [\#41](https://github.com/ismasan/oat/pull/41) ([iainbeeston](https://github.com/iainbeeston))
|
|
11
|
+
|
|
12
|
+
- *Closed issue:* Thread Safety [\#39](https://github.com/ismasan/oat/issues/39)
|
|
13
|
+
|
|
14
|
+
## [v0.4.4](https://github.com/ismasan/oat/tree/v0.4.4)
|
|
15
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.4.3...v0.4.4)
|
|
16
|
+
#### 26/05/14
|
|
17
|
+
- *Merged pull-request:* Add title addribute to siren action's fields [\#38](https://github.com/ismasan/oat/pull/38) ([erezesk](https://github.com/erezesk))
|
|
18
|
+
|
|
19
|
+
- *Closed issue:* Top level json api meta [\#28](https://github.com/ismasan/oat/issues/28)
|
|
20
|
+
|
|
21
|
+
## [v0.4.3](https://github.com/ismasan/oat/tree/v0.4.3)
|
|
22
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.4.2...v0.4.3)
|
|
23
|
+
#### 01/05/14
|
|
24
|
+
- *Merged pull-request:* json-api: Don't add templated links to the resource [\#37](https://github.com/ismasan/oat/pull/37) ([kjg](https://github.com/kjg))
|
|
25
|
+
|
|
26
|
+
## [v0.4.2](https://github.com/ismasan/oat/tree/v0.4.2)
|
|
27
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.4.1...v0.4.2)
|
|
28
|
+
#### 29/04/14
|
|
29
|
+
- *Merged pull-request:* Add type attribute for siren actions [\#36](https://github.com/ismasan/oat/pull/36) ([erezesk](https://github.com/erezesk))
|
|
30
|
+
|
|
31
|
+
- *Closed issue:* Errors management [\#35](https://github.com/ismasan/oat/issues/35)
|
|
32
|
+
|
|
33
|
+
## [v0.4.1](https://github.com/ismasan/oat/tree/v0.4.1)
|
|
34
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.4.0...v0.4.1)
|
|
35
|
+
#### 25/04/14
|
|
36
|
+
- *Merged pull-request:* Add meta property [\#32](https://github.com/ismasan/oat/pull/32) ([ahx](https://github.com/ahx))
|
|
37
|
+
|
|
38
|
+
## [v0.4.0](https://github.com/ismasan/oat/tree/v0.4.0)
|
|
39
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.3.0...v0.4.0)
|
|
40
|
+
#### 07/04/14
|
|
41
|
+
- *Merged pull-request:* Don't block NoMethodErrors from raising [\#31](https://github.com/ismasan/oat/pull/31) ([shekibobo](https://github.com/shekibobo))
|
|
42
|
+
|
|
43
|
+
- *Closed issue:* Does this support any type of caching? [\#30](https://github.com/ismasan/oat/issues/30)
|
|
44
|
+
|
|
45
|
+
## [v0.3.0](https://github.com/ismasan/oat/tree/v0.3.0)
|
|
46
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.2.5...v0.3.0)
|
|
47
|
+
#### 25/03/14
|
|
48
|
+
- *Merged pull-request:* Don't allow rake 10.2 on ruby 1.8.7 [\#29](https://github.com/ismasan/oat/pull/29) ([kjg](https://github.com/kjg))
|
|
49
|
+
|
|
50
|
+
- *Merged pull-request:* Json api link templates [\#27](https://github.com/ismasan/oat/pull/27) ([kjg](https://github.com/kjg))
|
|
51
|
+
|
|
52
|
+
- *Merged pull-request:* Json api attribute links [\#26](https://github.com/ismasan/oat/pull/26) ([kjg](https://github.com/kjg))
|
|
53
|
+
|
|
54
|
+
- *Merged pull-request:* Serializer from block or class update [\#16](https://github.com/ismasan/oat/pull/16) ([kjg](https://github.com/kjg))
|
|
55
|
+
|
|
56
|
+
- *Closed issue:* How to serialize many records? [\#24](https://github.com/ismasan/oat/issues/24)
|
|
57
|
+
|
|
58
|
+
## [v0.2.5](https://github.com/ismasan/oat/tree/v0.2.5)
|
|
59
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.2.4...v0.2.5)
|
|
60
|
+
#### 20/03/14
|
|
61
|
+
- *Merged pull-request:* Json api nil entities [\#25](https://github.com/ismasan/oat/pull/25) ([kjg](https://github.com/kjg))
|
|
62
|
+
|
|
63
|
+
## [v0.2.4](https://github.com/ismasan/oat/tree/v0.2.4)
|
|
64
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.2.3...v0.2.4)
|
|
65
|
+
#### 24/02/14
|
|
66
|
+
- *Merged pull-request:* Allow for serializing json api resource collections into root key [\#23](https://github.com/ismasan/oat/pull/23) ([kjg](https://github.com/kjg))
|
|
67
|
+
|
|
68
|
+
- *Merged pull-request:* Json api subent top linked [\#22](https://github.com/ismasan/oat/pull/22) ([kjg](https://github.com/kjg))
|
|
69
|
+
|
|
70
|
+
## [v0.2.3](https://github.com/ismasan/oat/tree/v0.2.3)
|
|
71
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.2.2...v0.2.3)
|
|
72
|
+
#### 17/02/14
|
|
73
|
+
- *Merged pull-request:* Json api sub behaviour [\#20](https://github.com/ismasan/oat/pull/20) ([kjg](https://github.com/kjg))
|
|
74
|
+
|
|
75
|
+
- *Merged pull-request:* Add version badge to README [\#18](https://github.com/ismasan/oat/pull/18) ([shekibobo](https://github.com/shekibobo))
|
|
76
|
+
|
|
77
|
+
## [v0.2.2](https://github.com/ismasan/oat/tree/v0.2.2)
|
|
78
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.1.2...v0.2.2)
|
|
79
|
+
#### 17/02/14
|
|
80
|
+
- *Merged pull-request:* Test more combinations in travis [\#17](https://github.com/ismasan/oat/pull/17) ([kjg](https://github.com/kjg))
|
|
81
|
+
|
|
82
|
+
- *Merged pull-request:* Make specs more accurate and using updated syntax [\#15](https://github.com/ismasan/oat/pull/15) ([shekibobo](https://github.com/shekibobo))
|
|
83
|
+
|
|
84
|
+
- *Merged pull-request:* Better Context [\#14](https://github.com/ismasan/oat/pull/14) ([shekibobo](https://github.com/shekibobo))
|
|
85
|
+
|
|
86
|
+
- *Merged pull-request:* Less active support [\#11](https://github.com/ismasan/oat/pull/11) ([kjg](https://github.com/kjg))
|
|
87
|
+
|
|
88
|
+
- *Closed issue:* Remove activesupport dependency [\#10](https://github.com/ismasan/oat/issues/10)
|
|
89
|
+
|
|
90
|
+
## [v0.1.2](https://github.com/ismasan/oat/tree/v0.1.2)
|
|
91
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.1.1...v0.1.2)
|
|
92
|
+
#### 13/02/14
|
|
93
|
+
- *Merged pull-request:* Support ruby 1.8.7 [\#12](https://github.com/ismasan/oat/pull/12) ([kjg](https://github.com/kjg))
|
|
94
|
+
|
|
95
|
+
- *Closed issue:* Serializing collections [\#9](https://github.com/ismasan/oat/issues/9)
|
|
96
|
+
|
|
97
|
+
## [v0.1.1](https://github.com/ismasan/oat/tree/v0.1.1)
|
|
98
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.1.0...v0.1.1)
|
|
99
|
+
#### 26/01/14
|
|
100
|
+
- *Merged pull-request:* Don't add invalid link relations to HAL output [\#8](https://github.com/ismasan/oat/pull/8) ([shekibobo](https://github.com/shekibobo))
|
|
101
|
+
|
|
102
|
+
## [v0.1.0](https://github.com/ismasan/oat/tree/v0.1.0)
|
|
103
|
+
[Full Changelog](https://github.com/ismasan/oat/compare/v0.0.1...v0.1.0)
|
|
104
|
+
#### 14/01/14
|
|
105
|
+
- *Merged pull-request:* Add Serializer#map\_properties to DRY property definitions [\#6](https://github.com/ismasan/oat/pull/6) ([shekibobo](https://github.com/shekibobo))
|
|
106
|
+
|
|
107
|
+
- *Merged pull-request:* Add action support for Siren. [\#4](https://github.com/ismasan/oat/pull/4) ([SebastianEdwards](https://github.com/SebastianEdwards))
|
|
108
|
+
|
|
109
|
+
- *Merged pull-request:* Don't try to serialize nil with an entity serializer [\#3](https://github.com/ismasan/oat/pull/3) ([shekibobo](https://github.com/shekibobo))
|
|
110
|
+
|
|
111
|
+
- *Merged pull-request:* Fix a small typo in the README [\#2](https://github.com/ismasan/oat/pull/2) ([stevenharman](https://github.com/stevenharman))
|
|
112
|
+
|
|
113
|
+
- *Closed issue:* DRY property declaration [\#5](https://github.com/ismasan/oat/issues/5)
|
|
114
|
+
|
|
115
|
+
## [v0.0.1](https://github.com/ismasan/oat/tree/v0.0.1)
|
|
116
|
+
#### 18/11/13
|
|
117
|
+
- *Merged pull-request:* Fix a few spelling and grammar errors [\#1](https://github.com/ismasan/oat/pull/1) ([leemachin](https://github.com/leemachin))
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
\* *This changelog was generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
data/README.md
CHANGED
|
@@ -162,7 +162,7 @@ adapter Oat::Adapters::Siren
|
|
|
162
162
|
```
|
|
163
163
|
At the moment Oat ships with adapters for [HAL](http://stateless.co/hal_specification.html), [Siren](https://github.com/kevinswiber/siren) and [JsonAPI](http://jsonapi.org/), but it's easy to write your own.
|
|
164
164
|
|
|
165
|
-
Note: Oat adapters are not *required* by default. Your code should
|
|
165
|
+
Note: Oat adapters are not *required* by default. Your code should explicitly require the ones it needs:
|
|
166
166
|
|
|
167
167
|
```ruby
|
|
168
168
|
# HAL
|
|
@@ -183,7 +183,7 @@ ProductSerializer.new(product, nil, Oat::Adapters::HAL)
|
|
|
183
183
|
|
|
184
184
|
That means that your app could switch adapters on run time depending, for example, on the request's `Accept` header or anything you need.
|
|
185
185
|
|
|
186
|
-
Note: a different library could be written to make adapter-switching auto-magical for different frameworks, for example using [Responders](http://api.rubyonrails.org/classes/ActionController/Responder.html) in Rails.
|
|
186
|
+
Note: a different library could be written to make adapter-switching auto-magical for different frameworks, for example using [Responders](http://api.rubyonrails.org/classes/ActionController/Responder.html) in Rails. Also see [Rails Integration](#rails-integration).
|
|
187
187
|
|
|
188
188
|
## Nested serializers
|
|
189
189
|
|
|
@@ -198,8 +198,10 @@ class AccountSerializer < Oat::Serializer
|
|
|
198
198
|
property :status, item.status
|
|
199
199
|
# user entities
|
|
200
200
|
entities :users, item.users do |user, user_serializer|
|
|
201
|
-
user_serializer.
|
|
202
|
-
|
|
201
|
+
user_serializer.properties do |props|
|
|
202
|
+
props.name user.name
|
|
203
|
+
props.email user.email
|
|
204
|
+
end
|
|
203
205
|
end
|
|
204
206
|
end
|
|
205
207
|
end
|
|
@@ -277,6 +279,12 @@ The way sub-entities are rendered in the final payload is up to the adapter. In
|
|
|
277
279
|
}
|
|
278
280
|
```
|
|
279
281
|
|
|
282
|
+
## Nested serializers when using the `JsonAPI` adapter
|
|
283
|
+
|
|
284
|
+
Collections are easy to express in HAL and Siren because they're no different from any other "entity". JsonAPI, however, doesn't work that way. In JsonAPI there's a distinction between "side-loaded" entities and the collection that is the subject of the resource. For this reason a `collection` method was added to the Oat DSL specifically for use with the `JsonAPI` adapter.
|
|
285
|
+
|
|
286
|
+
In the `HAL` and `Siren` adapters, `collection` is aliased to `entities`, but in the `JsonAPI` adapter, it sets the resource's main collection array as per the spec. `entities` keep the current behaviour of side-loading entities in the resource.
|
|
287
|
+
|
|
280
288
|
## Subclassing
|
|
281
289
|
|
|
282
290
|
Serializers can be subclassed, for example if you want all your serializers to share the same adapter or add shared helper methods.
|
|
@@ -577,6 +585,68 @@ The result for the SocialHalAdapter is:
|
|
|
577
585
|
|
|
578
586
|
You can take a look at [the built-in Hypermedia adapters](https://github.com/ismasan/oat/tree/master/lib/oat/adapters) for guidance.
|
|
579
587
|
|
|
588
|
+
## Rails Integration
|
|
589
|
+
The Rails responder functionality works out of the box with Oat when the
|
|
590
|
+
requests specify JSON as their response format via a header
|
|
591
|
+
`Accept: application/json` or query parameter `format=json`.
|
|
592
|
+
|
|
593
|
+
However, if you want to also support the mime type of your Hypermedia
|
|
594
|
+
format of choice, it will require a little bit of code.
|
|
595
|
+
|
|
596
|
+
The example below uses Siren, but the same pattern can be used for HAL and
|
|
597
|
+
JsonAPI.
|
|
598
|
+
|
|
599
|
+
Register the Siren mime-type and a responder:
|
|
600
|
+
|
|
601
|
+
```ruby
|
|
602
|
+
# config/initializers/oat.rb
|
|
603
|
+
Mime::Type.register 'application/vnd.siren+json', :siren
|
|
604
|
+
|
|
605
|
+
ActionController::Renderers.add :siren do |resource, options|
|
|
606
|
+
self.content_type ||= Mime[:siren]
|
|
607
|
+
resource.to_siren
|
|
608
|
+
end
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
In your controller, add `:siren` to the `respond_to`:
|
|
612
|
+
|
|
613
|
+
```ruby
|
|
614
|
+
class UsersController < ApplicationController
|
|
615
|
+
respond_to :siren, :json
|
|
616
|
+
|
|
617
|
+
def show
|
|
618
|
+
user = User.find(params[:id])
|
|
619
|
+
respond_with UserSerializer.new(user)
|
|
620
|
+
end
|
|
621
|
+
end
|
|
622
|
+
```
|
|
623
|
+
|
|
624
|
+
Finally, add a `to_siren` method to your serializer:
|
|
625
|
+
|
|
626
|
+
```ruby
|
|
627
|
+
class UserSerializer < Oat::Serializer
|
|
628
|
+
adapter Oat::Adapters::Siren
|
|
629
|
+
|
|
630
|
+
schema do
|
|
631
|
+
property :name, item.name
|
|
632
|
+
property :email, item.name
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
def to_siren
|
|
636
|
+
to_json
|
|
637
|
+
end
|
|
638
|
+
end
|
|
639
|
+
```
|
|
640
|
+
|
|
641
|
+
Now http requests that specify the Siren mime type will work as
|
|
642
|
+
expected.
|
|
643
|
+
|
|
644
|
+
**NOTE**
|
|
645
|
+
The key thing that makes this all hang together is that the
|
|
646
|
+
object passed to `respond_with` implements a `to_FORMAT` method, where
|
|
647
|
+
`FORMAT` is the symbol used to register the mime type and responder
|
|
648
|
+
(`:siren`). Without it, Rails will not invoke your responder block.
|
|
649
|
+
|
|
580
650
|
## Installation
|
|
581
651
|
|
|
582
652
|
Add this line to your application's Gemfile:
|
data/lib/oat/adapters/hal.rb
CHANGED
|
@@ -3,7 +3,11 @@ module Oat
|
|
|
3
3
|
module Adapters
|
|
4
4
|
class HAL < Oat::Adapter
|
|
5
5
|
def link(rel, opts = {})
|
|
6
|
-
|
|
6
|
+
if opts.is_a?(Array)
|
|
7
|
+
data[:_links][rel] = opts.select { |link_obj| link_obj.include?(:href) }
|
|
8
|
+
else
|
|
9
|
+
data[:_links][rel] = opts if opts[:href]
|
|
10
|
+
end
|
|
7
11
|
end
|
|
8
12
|
|
|
9
13
|
def properties(&block)
|
|
@@ -16,19 +20,30 @@ module Oat
|
|
|
16
20
|
|
|
17
21
|
alias_method :meta, :property
|
|
18
22
|
|
|
23
|
+
def rel(rels)
|
|
24
|
+
# no-op to maintain interface compatibility with the Siren adapter
|
|
25
|
+
end
|
|
26
|
+
|
|
19
27
|
def entity(name, obj, serializer_class = nil, context_options = {}, &block)
|
|
20
28
|
entity_serializer = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
|
|
21
|
-
data[:_embedded][name] = entity_serializer ? entity_serializer.to_hash : nil
|
|
29
|
+
data[:_embedded][entity_name(name)] = entity_serializer ? entity_serializer.to_hash : nil
|
|
22
30
|
end
|
|
23
31
|
|
|
24
32
|
def entities(name, collection, serializer_class = nil, context_options = {}, &block)
|
|
25
|
-
data[:_embedded][name] = collection.map do |obj|
|
|
33
|
+
data[:_embedded][entity_name(name)] = collection.map do |obj|
|
|
26
34
|
entity_serializer = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
|
|
27
35
|
entity_serializer ? entity_serializer.to_hash : nil
|
|
28
36
|
end
|
|
29
37
|
end
|
|
30
38
|
alias_method :collection, :entities
|
|
31
39
|
|
|
40
|
+
def entity_name(name)
|
|
41
|
+
# entity name may be an array, but HAL only uses the first
|
|
42
|
+
name.respond_to?(:first) ? name.first : name
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private :entity_name
|
|
46
|
+
|
|
32
47
|
end
|
|
33
48
|
end
|
|
34
49
|
end
|
|
@@ -19,6 +19,10 @@ module Oat
|
|
|
19
19
|
@meta = {}
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
+
def rel(rels)
|
|
23
|
+
# no-op to maintain interface compatibility with the Siren adapter
|
|
24
|
+
end
|
|
25
|
+
|
|
22
26
|
def type(*types)
|
|
23
27
|
@root_name = types.first.to_s.pluralize.to_sym
|
|
24
28
|
end
|
|
@@ -69,15 +73,21 @@ module Oat
|
|
|
69
73
|
ent = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
|
|
70
74
|
if ent
|
|
71
75
|
ent_hash = ent.to_hash
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
76
|
+
_name = entity_name(name)
|
|
77
|
+
link_name = _name.to_s.pluralize.to_sym
|
|
78
|
+
data[:links][_name] = ent_hash[:id]
|
|
79
|
+
|
|
80
|
+
entity_hash[link_name] ||= []
|
|
81
|
+
unless entity_hash[link_name].include? ent_hash
|
|
82
|
+
entity_hash[link_name] << ent_hash
|
|
83
|
+
end
|
|
75
84
|
end
|
|
76
85
|
end
|
|
77
86
|
|
|
78
87
|
def entities(name, collection, serializer_class = nil, context_options = {}, &block)
|
|
79
88
|
return if collection.nil? || collection.empty?
|
|
80
|
-
|
|
89
|
+
_name = entity_name(name)
|
|
90
|
+
link_name = _name.to_s.pluralize.to_sym
|
|
81
91
|
data[:links][link_name] = []
|
|
82
92
|
|
|
83
93
|
collection.each do |obj|
|
|
@@ -86,11 +96,20 @@ module Oat
|
|
|
86
96
|
if ent
|
|
87
97
|
ent_hash = ent.to_hash
|
|
88
98
|
data[:links][link_name] << ent_hash[:id]
|
|
89
|
-
entity_hash[link_name]
|
|
99
|
+
unless entity_hash[link_name].include? ent_hash
|
|
100
|
+
entity_hash[link_name] << ent_hash
|
|
101
|
+
end
|
|
90
102
|
end
|
|
91
103
|
end
|
|
92
104
|
end
|
|
93
105
|
|
|
106
|
+
def entity_name(name)
|
|
107
|
+
# entity name may be an array, but JSON API only uses the first
|
|
108
|
+
name.respond_to?(:first) ? name.first : name
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
private :entity_name
|
|
112
|
+
|
|
94
113
|
def collection(name, collection, serializer_class = nil, context_options = {}, &block)
|
|
95
114
|
@treat_as_resource_collection = true
|
|
96
115
|
data[:resource_collection] = [] unless data[:resource_collection].is_a?(Array)
|
data/lib/oat/adapters/siren.rb
CHANGED
|
@@ -10,6 +10,13 @@ module Oat
|
|
|
10
10
|
data[:actions] = []
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
+
# Sub-Entities have a required rel attribute
|
|
14
|
+
# https://github.com/kevinswiber/siren#rel
|
|
15
|
+
def rel(rels)
|
|
16
|
+
# rel must be an array.
|
|
17
|
+
data[:rel] = Array(rels)
|
|
18
|
+
end
|
|
19
|
+
|
|
13
20
|
def type(*types)
|
|
14
21
|
data[:class] = types
|
|
15
22
|
end
|
|
@@ -30,7 +37,15 @@ module Oat
|
|
|
30
37
|
|
|
31
38
|
def entity(name, obj, serializer_class = nil, context_options = {}, &block)
|
|
32
39
|
ent = serializer_from_block_or_class(obj, serializer_class, context_options, &block)
|
|
33
|
-
|
|
40
|
+
if ent
|
|
41
|
+
# use the name as the sub-entities rel to the parent resource.
|
|
42
|
+
ent.rel(name)
|
|
43
|
+
ent_hash = ent.to_hash
|
|
44
|
+
|
|
45
|
+
unless data[:entities].include? ent_hash
|
|
46
|
+
data[:entities] << ent_hash
|
|
47
|
+
end
|
|
48
|
+
end
|
|
34
49
|
end
|
|
35
50
|
|
|
36
51
|
def entities(name, collection, serializer_class = nil, context_options = {}, &block)
|
data/lib/oat/version.rb
CHANGED
data/spec/adapters/hal_spec.rb
CHANGED
|
@@ -81,5 +81,23 @@ describe Oat::Adapters::HAL do
|
|
|
81
81
|
)
|
|
82
82
|
end
|
|
83
83
|
end
|
|
84
|
+
|
|
85
|
+
let(:array_of_linked_objects_serializer) {
|
|
86
|
+
array_of_linked_objects_serializer_class.new(friendly_user, nil, Oat::Adapters::HAL)
|
|
87
|
+
}
|
|
88
|
+
let(:linked_objects_hash) { array_of_linked_objects_serializer.to_hash }
|
|
89
|
+
|
|
90
|
+
context 'with an array of linked objects' do
|
|
91
|
+
it 'produces a HAL-compliant hash' do
|
|
92
|
+
expect(linked_objects_hash.fetch(:_links).fetch(:related).size).to be 3
|
|
93
|
+
expect(linked_objects_hash.fetch(:_links)).to include(
|
|
94
|
+
:related => [
|
|
95
|
+
{:type=>"friend", :href=>"http://foo.bar.com/1"},
|
|
96
|
+
{:type=>"friend", :href=>"http://foo.bar.com/2"},
|
|
97
|
+
{:type=>"friend", :href=>"http://foo.bar.com/3"}
|
|
98
|
+
]
|
|
99
|
+
)
|
|
100
|
+
end
|
|
101
|
+
end
|
|
84
102
|
end
|
|
85
103
|
end
|
|
@@ -84,7 +84,10 @@ describe Oat::Adapters::JsonAPI do
|
|
|
84
84
|
|
|
85
85
|
context 'using #entity' do
|
|
86
86
|
subject(:linked_managers){ hash.fetch(:linked).fetch(:managers) }
|
|
87
|
-
|
|
87
|
+
|
|
88
|
+
it "does not duplicate an entity that is associated with 2 objects" do
|
|
89
|
+
expect(linked_managers.size).to eq(1)
|
|
90
|
+
end
|
|
88
91
|
|
|
89
92
|
it "contains the correct properties and links" do
|
|
90
93
|
expect(linked_managers.first).to include(
|
|
@@ -313,7 +316,10 @@ describe Oat::Adapters::JsonAPI do
|
|
|
313
316
|
|
|
314
317
|
context 'sub entity' do
|
|
315
318
|
subject(:linked_managers){ collection_hash.fetch(:linked).fetch(:managers) }
|
|
316
|
-
|
|
319
|
+
|
|
320
|
+
it "does not duplicate an entity that is associated with multiple objects" do
|
|
321
|
+
expect(linked_managers.size).to eq(1)
|
|
322
|
+
end
|
|
317
323
|
|
|
318
324
|
it "contains the correct properties and links" do
|
|
319
325
|
expect(linked_managers.first).to include(
|
data/spec/adapters/siren_spec.rb
CHANGED
|
@@ -45,6 +45,10 @@ describe Oat::Adapters::Siren do
|
|
|
45
45
|
:href => "http://foo.bar.com/#{friend.id}"
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
+
# sub-entity rel is an array, so it may have multiple values
|
|
49
|
+
expect(embedded_friends.first.fetch(:rel)).to include(:friends)
|
|
50
|
+
expect(embedded_friends.first.fetch(:rel)).to include('http://example.org/rels/person')
|
|
51
|
+
|
|
48
52
|
embedded_managers = hash.fetch(:entities).select{ |o| o[:class].include? "manager" }
|
|
49
53
|
expect(embedded_managers.size).to be 1
|
|
50
54
|
expect(embedded_managers.first.fetch(:properties)).to include(
|
|
@@ -56,6 +60,7 @@ describe Oat::Adapters::Siren do
|
|
|
56
60
|
:rel => [:self],
|
|
57
61
|
:href => "http://foo.bar.com/#{manager.id}"
|
|
58
62
|
)
|
|
63
|
+
expect(embedded_managers.first.fetch(:rel)).to include(:manager)
|
|
59
64
|
|
|
60
65
|
# action close_account
|
|
61
66
|
actions = hash.fetch(:actions)
|
data/spec/fixtures.rb
CHANGED
|
@@ -3,8 +3,9 @@ module Fixtures
|
|
|
3
3
|
def self.included(base)
|
|
4
4
|
base.let(:user_class) { Struct.new(:name, :age, :id, :friends, :manager) }
|
|
5
5
|
base.let(:friend) { user_class.new('Joe', 33, 2, []) }
|
|
6
|
-
base.let(:manager) { user_class.new('Jane', 29, 3, []) }
|
|
6
|
+
base.let(:manager) { user_class.new('Jane', 29, 3, [friend]) }
|
|
7
7
|
base.let(:user) { user_class.new('Ismael', 35, 1, [friend], manager) }
|
|
8
|
+
base.let(:friendly_user) { user_class.new('Jeff', 33, 1, [friend, manager, user]) }
|
|
8
9
|
base.let(:serializer_class) do
|
|
9
10
|
Class.new(Oat::Serializer) do
|
|
10
11
|
klass = self
|
|
@@ -23,7 +24,7 @@ module Fixtures
|
|
|
23
24
|
attrs.message_from_above context[:message]
|
|
24
25
|
end
|
|
25
26
|
|
|
26
|
-
entities :friends, item.friends, klass, :message => "Merged into parent's context"
|
|
27
|
+
entities [:friends, 'http://example.org/rels/person'], item.friends, klass, :message => "Merged into parent's context"
|
|
27
28
|
|
|
28
29
|
entity :manager, item.manager do |manager, s|
|
|
29
30
|
s.type 'manager'
|
|
@@ -33,6 +34,8 @@ module Fixtures
|
|
|
33
34
|
attrs.name manager.name
|
|
34
35
|
attrs.age manager.age
|
|
35
36
|
end
|
|
37
|
+
|
|
38
|
+
entities [:friends, 'http://example.org/rels/person'], item.friends, klass, :message => "Merged into parent's context"
|
|
36
39
|
end
|
|
37
40
|
|
|
38
41
|
if adapter.respond_to?(:action)
|
|
@@ -50,6 +53,24 @@ module Fixtures
|
|
|
50
53
|
end
|
|
51
54
|
end
|
|
52
55
|
|
|
56
|
+
def url_for(id)
|
|
57
|
+
"http://foo.bar.com/#{id}"
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
base.let(:array_of_linked_objects_serializer_class) do
|
|
62
|
+
Class.new(Oat::Serializer) do
|
|
63
|
+
schema do
|
|
64
|
+
type 'user'
|
|
65
|
+
|
|
66
|
+
link :self, :href => url_for(item.id)
|
|
67
|
+
link :related, item.friends.map { |friend|
|
|
68
|
+
{:type => 'friend', :href => url_for(friend.id)}
|
|
69
|
+
}.sort_by { |link_obj|
|
|
70
|
+
link_obj[:href]
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
53
74
|
def url_for(id)
|
|
54
75
|
"http://foo.bar.com/#{id}"
|
|
55
76
|
end
|
metadata
CHANGED
|
@@ -1,83 +1,83 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: oat
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.6
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ismael Celis
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2015-02-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activesupport
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- -
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
19
|
version: '0'
|
|
20
20
|
type: :runtime
|
|
21
21
|
prerelease: false
|
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
23
|
requirements:
|
|
24
|
-
- -
|
|
24
|
+
- - ">="
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '0'
|
|
27
27
|
- !ruby/object:Gem::Dependency
|
|
28
28
|
name: bundler
|
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
|
30
30
|
requirements:
|
|
31
|
-
- - ~>
|
|
31
|
+
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
33
|
version: '1.3'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
|
-
- - ~>
|
|
38
|
+
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
40
|
version: '1.3'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: rake
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
|
-
- -
|
|
45
|
+
- - ">="
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
47
|
version: '0'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
|
-
- -
|
|
52
|
+
- - ">="
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
54
|
version: '0'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: rspec
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
|
-
- -
|
|
59
|
+
- - ">="
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
61
|
version: '3.0'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
|
-
- -
|
|
66
|
+
- - ">="
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
68
|
version: '3.0'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: rspec-its
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
|
-
- -
|
|
73
|
+
- - ">="
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
75
|
version: '0'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
|
-
- -
|
|
80
|
+
- - ">="
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
82
|
version: '0'
|
|
83
83
|
description: Oat helps you separate your API schema definitions from the underlying
|
|
@@ -89,9 +89,10 @@ executables: []
|
|
|
89
89
|
extensions: []
|
|
90
90
|
extra_rdoc_files: []
|
|
91
91
|
files:
|
|
92
|
-
- .gitignore
|
|
93
|
-
- .rspec
|
|
94
|
-
- .travis.yml
|
|
92
|
+
- ".gitignore"
|
|
93
|
+
- ".rspec"
|
|
94
|
+
- ".travis.yml"
|
|
95
|
+
- CHANGELOG.md
|
|
95
96
|
- Gemfile
|
|
96
97
|
- LICENSE
|
|
97
98
|
- LICENSE.txt
|
|
@@ -130,17 +131,17 @@ require_paths:
|
|
|
130
131
|
- lib
|
|
131
132
|
required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
133
|
requirements:
|
|
133
|
-
- -
|
|
134
|
+
- - ">="
|
|
134
135
|
- !ruby/object:Gem::Version
|
|
135
136
|
version: '0'
|
|
136
137
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
137
138
|
requirements:
|
|
138
|
-
- -
|
|
139
|
+
- - ">="
|
|
139
140
|
- !ruby/object:Gem::Version
|
|
140
141
|
version: '0'
|
|
141
142
|
requirements: []
|
|
142
143
|
rubyforge_project:
|
|
143
|
-
rubygems_version: 2.
|
|
144
|
+
rubygems_version: 2.2.2
|
|
144
145
|
signing_key:
|
|
145
146
|
specification_version: 4
|
|
146
147
|
summary: Adapters-based serializers with Hypermedia support
|