roar 1.0.4 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +14 -6
- data/CHANGES.markdown +75 -58
- data/CONTRIBUTING.md +31 -0
- data/Gemfile +12 -2
- data/ISSUE_TEMPLATE.md +20 -0
- data/LICENSE +1 -1
- data/README.markdown +126 -250
- data/Rakefile +3 -1
- data/examples/example.rb +0 -0
- data/examples/example_server.rb +0 -0
- data/lib/roar.rb +3 -3
- data/lib/roar/client.rb +8 -3
- data/lib/roar/decorator.rb +2 -2
- data/lib/roar/http_verbs.rb +0 -16
- data/lib/roar/hypermedia.rb +30 -56
- data/lib/roar/json.rb +5 -5
- data/lib/roar/json/collection.rb +10 -2
- data/lib/roar/json/hal.rb +72 -82
- data/lib/roar/version.rb +1 -1
- data/lib/roar/xml.rb +1 -1
- data/roar.gemspec +6 -6
- data/test/client_test.rb +1 -1
- data/test/coercion_feature_test.rb +7 -2
- data/test/decorator_test.rb +17 -7
- data/test/hal_json_test.rb +98 -106
- data/test/hypermedia_feature_test.rb +13 -31
- data/test/hypermedia_test.rb +26 -92
- data/test/{decorator_client_test.rb → integration/decorator_client_test.rb} +5 -4
- data/test/{faraday_http_transport_test.rb → integration/faraday_http_transport_test.rb} +1 -0
- data/test/{http_verbs_test.rb → integration/http_verbs_test.rb} +3 -2
- data/test/integration/json_collection_test.rb +35 -0
- data/test/{net_http_transport_test.rb → integration/net_http_transport_test.rb} +1 -0
- data/test/integration/runner.rb +2 -3
- data/test/integration/server.rb +6 -0
- data/test/json_representer_test.rb +2 -29
- data/test/lonely_test.rb +1 -2
- data/test/ssl_client_certs_test.rb +1 -1
- data/test/test_helper.rb +21 -3
- data/test/xml_representer_test.rb +6 -5
- metadata +22 -36
- data/gemfiles/Gemfile.representable-1.7 +0 -6
- data/gemfiles/Gemfile.representable-1.8 +0 -6
- data/gemfiles/Gemfile.representable-2.0 +0 -5
- data/gemfiles/Gemfile.representable-2.1 +0 -5
- data/gemfiles/Gemfile.representable-head +0 -6
- data/lib/roar/json/collection_json.rb +0 -208
- data/lib/roar/json/json_api.rb +0 -233
- data/test/collection_json_test.rb +0 -132
- data/test/hal_links_test.rb +0 -31
- data/test/json_api_test.rb +0 -451
- data/test/lib/runner.rb +0 -134
data/lib/roar/version.rb
CHANGED
data/lib/roar/xml.rb
CHANGED
@@ -35,10 +35,10 @@ module Roar
|
|
35
35
|
# FIXME: this doesn't belong into the generic XML representer.
|
36
36
|
{
|
37
37
|
:as => :link,
|
38
|
-
:collection => true,
|
39
38
|
:class => Hypermedia::Hyperlink,
|
40
39
|
:extend => XML::HyperlinkRepresenter,
|
41
40
|
:exec_context => :decorator,
|
41
|
+
collection: true
|
42
42
|
} # TODO: merge with JSON.
|
43
43
|
end
|
44
44
|
end
|
data/roar.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |s|
|
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ["Nick Sutterer"]
|
9
9
|
s.email = ["apotonick@gmail.com"]
|
10
|
-
s.homepage = "http://
|
10
|
+
s.homepage = "http://trailblazer.to/gems/roar"
|
11
11
|
s.summary = %q{Parse and render REST API documents using representers.}
|
12
12
|
s.description = %q{Object-oriented representers help you defining nested REST API documents which can then be rendered and parsed using one and the same concept.}
|
13
13
|
s.license = 'MIT'
|
@@ -17,14 +17,14 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
18
|
s.require_paths = ["lib"]
|
19
19
|
|
20
|
-
s.add_runtime_dependency "representable", "
|
20
|
+
s.add_runtime_dependency "representable", "~> 3.0.0"
|
21
21
|
|
22
22
|
s.add_development_dependency "rake", ">= 0.10.1"
|
23
23
|
s.add_development_dependency "test_xml", "0.1.6"
|
24
|
-
s.add_development_dependency
|
25
|
-
s.add_development_dependency "sinatra"
|
26
|
-
s.add_development_dependency "sinatra-contrib"
|
24
|
+
s.add_development_dependency 'minitest', '>= 5.10'
|
25
|
+
s.add_development_dependency "sinatra", '>= 2.0.0'
|
26
|
+
s.add_development_dependency "sinatra-contrib", '>= 2.0.0'
|
27
27
|
s.add_development_dependency "virtus", ">= 1.0.0"
|
28
28
|
s.add_development_dependency "faraday"
|
29
|
-
s.add_development_dependency "
|
29
|
+
s.add_development_dependency "multi_json"
|
30
30
|
end
|
data/test/client_test.rb
CHANGED
@@ -30,7 +30,7 @@ class ClientTest < MiniTest::Spec
|
|
30
30
|
# since this is considered dangerous, we test the mutuable options.
|
31
31
|
it "adds links: false to options" do
|
32
32
|
song.to_hash(options = {})
|
33
|
-
options.must_equal({:
|
33
|
+
options.must_equal(user_options: {links: false})
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -1,14 +1,17 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'roar/coercion'
|
3
|
+
require 'roar/decorator'
|
3
4
|
|
4
5
|
class CoercionFeatureTest < MiniTest::Spec
|
5
6
|
describe "Coercion" do
|
6
|
-
class
|
7
|
+
class SongDecorator < Roar::Decorator
|
7
8
|
include Roar::JSON
|
8
9
|
include Roar::Coercion
|
9
10
|
|
10
11
|
property :composed_at, :type => DateTime, :default => "May 12th, 2012"
|
12
|
+
end
|
11
13
|
|
14
|
+
class ImmigrantSong
|
12
15
|
attr_accessor :composed_at
|
13
16
|
def composed_at=(v) # in ruby 2.2, #label= is not there, all at sudden. what *is* that?
|
14
17
|
@composed_at = v
|
@@ -16,7 +19,9 @@ class CoercionFeatureTest < MiniTest::Spec
|
|
16
19
|
end
|
17
20
|
|
18
21
|
it "coerces into the provided type" do
|
19
|
-
song
|
22
|
+
song = ImmigrantSong.new
|
23
|
+
decorator = SongDecorator.new(song)
|
24
|
+
decorator.from_json("{\"composed_at\":\"November 18th, 1983\"}")
|
20
25
|
assert_equal DateTime.parse("Fri, 18 Nov 1983 00:00:00 +0000"), song.composed_at
|
21
26
|
end
|
22
27
|
end
|
data/test/decorator_test.rb
CHANGED
@@ -27,11 +27,15 @@ class DecoratorTest < MiniTest::Spec
|
|
27
27
|
describe "JSON" do
|
28
28
|
let (:decorator_class) { rpr_mod = rpr
|
29
29
|
Class.new(Roar::Decorator) do
|
30
|
+
include Roar::JSON
|
31
|
+
include Roar::Hypermedia
|
32
|
+
|
30
33
|
include rpr_mod
|
31
34
|
end }
|
32
35
|
let (:decorator) { decorator_class.new(model) }
|
33
36
|
|
34
|
-
it "
|
37
|
+
it "xxxrendering links works" do
|
38
|
+
pp decorator.send(:representable_attrs)
|
35
39
|
decorator.to_hash.must_equal({"links"=>[{"rel"=>"self", "href"=>"http://self"}]})
|
36
40
|
end
|
37
41
|
|
@@ -42,7 +46,7 @@ class DecoratorTest < MiniTest::Spec
|
|
42
46
|
|
43
47
|
it "does not set links on represented" do
|
44
48
|
decorator_class.new(model_with_links).from_hash("links"=>[{:rel=>:self, :href=>"http://self"}])
|
45
|
-
model_with_links.links.
|
49
|
+
model_with_links.links.must_be_nil
|
46
50
|
end
|
47
51
|
|
48
52
|
class ConsumingDecorator < Roar::Decorator
|
@@ -63,10 +67,10 @@ class DecoratorTest < MiniTest::Spec
|
|
63
67
|
decorator.from_hash("links"=>[{:rel=>:self, :href=>"http://percolator"}])
|
64
68
|
|
65
69
|
# links are always set on decorator instance.
|
66
|
-
decorator
|
70
|
+
decorator.links["self"].must_equal(link(:rel=>:self, :href=>"http://percolator"))
|
67
71
|
|
68
72
|
# and propagated to represented with HypermediaConsumer.
|
69
|
-
model_with_links.links[
|
73
|
+
model_with_links.links["self"].must_equal(link(:rel=>:self, :href=>"http://percolator"))
|
70
74
|
end
|
71
75
|
end
|
72
76
|
end
|
@@ -78,6 +82,8 @@ class DecoratorTest < MiniTest::Spec
|
|
78
82
|
end
|
79
83
|
let (:decorator_class) { rpr_mod = rpr
|
80
84
|
Class.new(Roar::Decorator) do
|
85
|
+
include Roar::XML
|
86
|
+
include Roar::Hypermedia
|
81
87
|
include rpr_mod
|
82
88
|
self.representation_wrap = :song
|
83
89
|
end
|
@@ -97,10 +103,13 @@ class DecoratorTest < MiniTest::Spec
|
|
97
103
|
|
98
104
|
describe "JSON::HAL" do
|
99
105
|
representer_for([Roar::JSON::HAL]) do
|
106
|
+
# feature Roar::JSON::HAL
|
100
107
|
link(:self) { "http://self" }
|
101
108
|
end
|
102
109
|
let (:decorator_class) { rpr_mod = rpr
|
103
110
|
Class.new(Roar::Decorator) do
|
111
|
+
include Roar::JSON::HAL
|
112
|
+
|
104
113
|
include rpr_mod
|
105
114
|
end
|
106
115
|
}
|
@@ -116,15 +125,16 @@ class DecoratorTest < MiniTest::Spec
|
|
116
125
|
end
|
117
126
|
|
118
127
|
describe "Decorator::HypermediaClient" do
|
119
|
-
let (:
|
128
|
+
let (:decorator_class) { rpr_mod = rpr
|
120
129
|
Class.new(Roar::Decorator) do
|
130
|
+
include Roar::JSON::HAL
|
121
131
|
include rpr_mod
|
122
132
|
include Roar::Decorator::HypermediaConsumer
|
123
133
|
end }
|
124
134
|
|
125
135
|
it "propagates links to represented" do
|
126
|
-
|
127
|
-
model_with_links.links[
|
136
|
+
decorator_class.new(model_with_links).from_hash("_links"=>{"self"=>{:href=>"http://self"}})
|
137
|
+
model_with_links.links["self"].must_equal(link(:rel=>"self", :href=>"http://self"))
|
128
138
|
end
|
129
139
|
end
|
130
140
|
end
|
data/test/hal_json_test.rb
CHANGED
@@ -2,8 +2,8 @@ require 'test_helper'
|
|
2
2
|
require 'roar/json/hal'
|
3
3
|
|
4
4
|
class HalJsonTest < MiniTest::Spec
|
5
|
-
let(:
|
6
|
-
|
5
|
+
let(:decorator_class) do
|
6
|
+
Class.new(Roar::Decorator) do
|
7
7
|
include Roar::JSON
|
8
8
|
include Roar::JSON::HAL
|
9
9
|
|
@@ -18,112 +18,107 @@ class HalJsonTest < MiniTest::Spec
|
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
subject { Object.new
|
21
|
+
subject { decorator_class.new(Object.new) }
|
22
22
|
|
23
23
|
describe "links" do
|
24
24
|
describe "parsing" do
|
25
25
|
it "parses link array" do # TODO: remove me.
|
26
26
|
obj = subject.from_json("{\"_links\":{\"self\":[{\"lang\":\"en\",\"href\":\"http://en.hit\"},{\"lang\":\"de\",\"href\":\"http://de.hit\"}]}}")
|
27
|
-
|
27
|
+
subject.links.must_equal "self" => [link("rel" => "self", "href" => "http://en.hit", "lang" => "en"), link("rel" => "self", "href" => "http://de.hit", "lang" => "de")]
|
28
28
|
end
|
29
29
|
|
30
30
|
it "parses single links" do # TODO: remove me.
|
31
31
|
obj = subject.from_json("{\"_links\":{\"next\":{\"href\":\"http://next\"}}}")
|
32
|
-
|
32
|
+
subject.links.must_equal "next" => link("rel" => "next", "href" => "http://next")
|
33
33
|
end
|
34
34
|
|
35
35
|
it "parses link and link array" do
|
36
|
-
obj = subject.from_json(
|
37
|
-
|
36
|
+
obj = subject.from_json(%@{"_links":{"next":{"href":"http://next"}, "self":[{"lang":"en","href":"http://en.hit"},{"lang":"de","href":"http://de.hit"}]}}@)
|
37
|
+
subject._links.must_equal "next"=>link("rel" => "next", "href" => "http://next"), "self"=>[link("rel" => "self", "href" => "http://en.hit", "lang" => "en"), link("rel" => "self", "href" => "http://de.hit", "lang" => "de")]
|
38
38
|
end
|
39
39
|
|
40
40
|
it "parses empty link array" do
|
41
|
-
subject.from_json("{\"_links\":{\"self\":[]}}")
|
41
|
+
subject.from_json("{\"_links\":{\"self\":[]}}")
|
42
|
+
subject.links[:self].must_be_nil
|
42
43
|
end
|
43
44
|
|
44
45
|
it "parses non-existent link array" do
|
45
|
-
subject.from_json("{\"_links\":{}}")
|
46
|
+
subject.from_json("{\"_links\":{}}")
|
47
|
+
subject.links[:self].must_be_nil # DISCUSS: should this be []?
|
46
48
|
end
|
47
49
|
|
48
|
-
it "rejects single links declared as array" do
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
50
|
+
# it "rejects single links declared as array" do
|
51
|
+
# assert_raises TypeError do
|
52
|
+
# subject.from_json("{\"_links\":{\"self\":{\"href\":\"http://next\"}}}")
|
53
|
+
# end
|
54
|
+
# end
|
53
55
|
end
|
54
56
|
|
55
57
|
describe "rendering" do
|
56
58
|
it "renders link and link array" do
|
57
59
|
subject.to_json.must_equal "{\"_links\":{\"self\":[{\"lang\":\"en\",\"href\":\"http://en.hit\"},{\"lang\":\"de\",\"href\":\"http://de.hit\"}],\"next\":{\"href\":\"http://next\"}}}"
|
58
60
|
end
|
61
|
+
end
|
62
|
+
end
|
59
63
|
|
60
|
-
|
61
|
-
|
62
|
-
|
64
|
+
describe "empty link array" do
|
65
|
+
let(:decorator_class) do
|
66
|
+
Class.new(Roar::Decorator) do
|
67
|
+
include Roar::JSON
|
68
|
+
include Roar::JSON::HAL
|
63
69
|
|
64
|
-
|
65
|
-
end
|
66
|
-
subject = Object.new.extend(rpr)
|
67
|
-
|
68
|
-
subject.to_json.must_equal "{\"_links\":{\"self\":[]}}"
|
70
|
+
links(:self) { [] }
|
69
71
|
end
|
70
72
|
end
|
71
|
-
end
|
72
73
|
|
73
|
-
|
74
|
-
# it "should map link arrays correctly" do
|
75
|
-
# subject.send :prepare_links!, {}
|
76
|
-
# subject.links.must_equal :self => [link("rel" => "self", "href" => "http://en.hit", "lang" => "en"),link("rel" => :self, "href" => "http://de.hit", "lang" => "de")], "next" => link("href" => "http://next", "rel" => "next")
|
77
|
-
# end
|
78
|
-
# end
|
74
|
+
subject { decorator_class.new(Object.new) }
|
79
75
|
|
80
|
-
|
81
|
-
|
82
|
-
subject.send(:link_array_rels).must_equal [:self]
|
76
|
+
it "gets render" do
|
77
|
+
subject.to_json.must_equal %@{"_links":{"self":[]}}@
|
83
78
|
end
|
84
79
|
end
|
85
80
|
|
86
81
|
|
87
|
-
describe "
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
"http://songs/#{title}"
|
93
|
-
end
|
94
|
-
end
|
82
|
+
describe "_links and _embedded" do
|
83
|
+
let(:decorator_class) do
|
84
|
+
Class.new(Roar::Decorator) do
|
85
|
+
include Roar::JSON
|
86
|
+
include Roar::JSON::HAL
|
95
87
|
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
88
|
+
property :id
|
89
|
+
collection :songs, class: Song, embedded: true do
|
90
|
+
include Roar::JSON::HAL
|
91
|
+
|
92
|
+
property :title
|
93
|
+
link(:self) { "http://songs/#{represented.title}" }
|
94
|
+
end
|
95
|
+
|
96
|
+
link(:self) { "http://albums/#{represented.id}" }
|
101
97
|
end
|
102
98
|
end
|
103
99
|
|
104
|
-
|
105
|
-
|
106
|
-
end
|
100
|
+
let(:album) { Album.new(:songs => [Song.new(:title => "Beer")], :id => 1) }
|
101
|
+
subject { decorator_class.new(album) }
|
107
102
|
|
108
103
|
it "render links and embedded resources according to HAL" do
|
109
|
-
|
104
|
+
subject.to_json.must_equal "{\"id\":1,\"_embedded\":{\"songs\":[{\"title\":\"Beer\",\"_links\":{\"self\":{\"href\":\"http://songs/Beer\"}}}]},\"_links\":{\"self\":{\"href\":\"http://albums/1\"}}}"
|
110
105
|
end
|
111
106
|
|
112
107
|
it "parses links and resources following the mighty HAL" do
|
113
|
-
|
114
|
-
assert_equal 2,
|
115
|
-
assert_equal "Coffee",
|
116
|
-
assert_equal "http://songs/Coffee",
|
117
|
-
assert_equal "http://albums/2",
|
108
|
+
subject.from_json("{\"id\":2,\"_embedded\":{\"songs\":[{\"title\":\"Coffee\",\"_links\":{\"self\":{\"href\":\"http://songs/Coffee\"}}}]},\"_links\":{\"self\":{\"href\":\"http://albums/2\"}}}")
|
109
|
+
assert_equal 2, album.id
|
110
|
+
assert_equal "Coffee", album.songs.first.title
|
111
|
+
# FIXME assert_equal "http://songs/Coffee", subject.songs.first.links["self"].href
|
112
|
+
assert_equal "http://albums/2", subject.links["self"].href
|
118
113
|
end
|
119
114
|
|
120
115
|
it "doesn't require _links and _embedded to be present" do
|
121
|
-
|
122
|
-
assert_equal 2,
|
116
|
+
subject.from_json("{\"id\":2}")
|
117
|
+
assert_equal 2, album.id
|
123
118
|
|
124
119
|
# in newer representables, this is not overwritten to an empty [] anymore.
|
125
|
-
assert_equal ["Beer"],
|
126
|
-
|
120
|
+
assert_equal ["Beer"], album.songs.map(&:title)
|
121
|
+
album.links.must_be_nil
|
127
122
|
end
|
128
123
|
end
|
129
124
|
|
@@ -134,73 +129,70 @@ class JsonHalTest < MiniTest::Spec
|
|
134
129
|
Artist = Struct.new(:name)
|
135
130
|
Song = Struct.new(:title)
|
136
131
|
|
137
|
-
def self.representer!
|
138
|
-
super([Roar::JSON::HAL])
|
139
|
-
end
|
140
|
-
|
141
|
-
def representer
|
142
|
-
rpr
|
143
|
-
end
|
144
|
-
|
145
132
|
describe "render_nil: false" do
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
133
|
+
let(:decorator_class) do
|
134
|
+
Class.new(Roar::Decorator) do
|
135
|
+
include Roar::JSON
|
136
|
+
include Roar::JSON::HAL
|
150
137
|
|
151
|
-
|
152
|
-
|
138
|
+
property :artist, embedded: true, render_nil: false do
|
139
|
+
property :name
|
140
|
+
end
|
141
|
+
|
142
|
+
collection :songs, embedded: true, render_empty: false do
|
143
|
+
property :title
|
144
|
+
end
|
153
145
|
end
|
154
146
|
end
|
155
147
|
|
156
|
-
it { Album.new(Artist.new("Bare, Jr."), [Song.new("Tobacco Spit")])
|
157
|
-
it { Album.new
|
148
|
+
it { decorator_class.new(Album.new(Artist.new("Bare, Jr."), [Song.new("Tobacco Spit")])).to_hash.must_equal({"_embedded"=>{"artist"=>{"name"=>"Bare, Jr."}, "songs"=>[{"title"=>"Tobacco Spit"}]}}) }
|
149
|
+
it { decorator_class.new(Album.new).to_hash.must_equal({}) }
|
158
150
|
end
|
159
151
|
|
160
152
|
describe "as: alias" do
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
153
|
+
let(:decorator_class) do
|
154
|
+
Class.new(Roar::Decorator) do
|
155
|
+
include Roar::JSON
|
156
|
+
include Roar::JSON::HAL
|
165
157
|
|
166
|
-
|
167
|
-
|
158
|
+
property :artist, as: :my_artist, class: Artist, embedded: true do
|
159
|
+
property :name
|
160
|
+
end
|
161
|
+
|
162
|
+
collection :songs, as: :my_songs, class: Song, embedded: true do
|
163
|
+
property :title
|
164
|
+
end
|
168
165
|
end
|
169
166
|
end
|
170
167
|
|
171
|
-
it { Album.new(Artist.new("Bare, Jr."), [Song.new("Tobacco Spit")])
|
172
|
-
it { Album.new
|
168
|
+
it { decorator_class.new(Album.new(Artist.new("Bare, Jr."), [Song.new("Tobacco Spit")])).to_hash.must_equal({"_embedded"=>{"my_artist"=>{"name"=>"Bare, Jr."}, "my_songs"=>[{"title"=>"Tobacco Spit"}]}}) }
|
169
|
+
it { decorator_class.new(Album.new).from_hash({"_embedded"=>{"my_artist"=>{"name"=>"Bare, Jr."}, "my_songs"=>[{"title"=>"Tobacco Spit"}]}}).inspect.must_equal "#<struct JsonHalTest::Album artist=#<struct JsonHalTest::Artist name=\"Bare, Jr.\">, songs=[#<struct JsonHalTest::Song title=\"Tobacco Spit\">]>" }
|
173
170
|
end
|
174
171
|
end
|
175
172
|
|
173
|
+
class HalCurieTest < MiniTest::Spec
|
174
|
+
let(:decorator_class) do
|
175
|
+
Class.new(Roar::Decorator) do
|
176
|
+
include Roar::JSON
|
177
|
+
include Roar::JSON::HAL
|
176
178
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
it "returns true for array link" do
|
181
|
-
subject.is_array?(:self).must_equal true
|
182
|
-
subject.is_array?("self").must_equal true
|
183
|
-
end
|
184
|
-
|
185
|
-
it "returns false otherwise" do
|
186
|
-
subject.is_array?("prev").must_equal false
|
187
|
-
end
|
188
|
-
end
|
189
|
-
end
|
190
|
-
|
179
|
+
link "doc:self" do
|
180
|
+
"/"
|
181
|
+
end
|
191
182
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
"/"
|
196
|
-
end
|
183
|
+
links "doc:link_collection" do
|
184
|
+
[{:name => "link_collection", :href => "/"}]
|
185
|
+
end
|
197
186
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
187
|
+
curies do
|
188
|
+
[{:name => :doc,
|
189
|
+
:href => "//docs/{rel}",
|
190
|
+
:templated => true}]
|
191
|
+
end
|
202
192
|
end
|
203
193
|
end
|
204
194
|
|
205
|
-
|
195
|
+
subject { decorator_class.new(Object.new) }
|
196
|
+
|
197
|
+
it { subject.to_hash.must_equal({"_links"=>{"doc:self"=>{"href"=>"/"}, "doc:link_collection"=>[{"name"=>"link_collection", "href"=>"/"}], "curies"=>[{"name"=>:doc, "href"=>"//docs/{rel}", "templated"=>true}]}}) }
|
206
198
|
end
|