roar 0.8.2 → 0.8.3
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.markdown +4 -1
- data/README.textile +7 -1
- data/Rakefile +1 -1
- data/lib/roar/representer/base.rb +2 -3
- data/lib/roar/representer/feature/http_verbs.rb +4 -5
- data/lib/roar/representer/feature/hypermedia.rb +31 -6
- data/lib/roar/representer/json.rb +2 -3
- data/lib/roar/representer/xml.rb +3 -3
- data/lib/roar/version.rb +1 -1
- data/roar.gemspec +1 -1
- data/test/Gemfile +1 -0
- data/test/fake_server.rb +22 -1
- data/test/http_verbs_feature_test.rb +39 -18
- data/test/hypermedia_feature_test.rb +42 -1
- data/test/integration_test.rb +63 -100
- data/test/json_representer_test.rb +7 -14
- data/test/model_representing_test.rb +3 -3
- data/test/representer_test.rb +8 -4
- data/test/test_helper.rb +0 -3
- data/test/xml_representer_test.rb +8 -8
- metadata +6 -6
data/CHANGES.markdown
CHANGED
data/README.textile
CHANGED
@@ -64,8 +64,12 @@ h2. Representers
|
|
64
64
|
To render a representational document, the backend service has to define a representer.
|
65
65
|
|
66
66
|
<pre>
|
67
|
+
require 'roar/representer/json'
|
68
|
+
require 'roar/representer/feature/hypermedia'
|
69
|
+
|
67
70
|
class Article
|
68
71
|
include Roar::Representer::JSON
|
72
|
+
include Roar::Representer::Feature::Hypermedia
|
69
73
|
|
70
74
|
property :title
|
71
75
|
property :id
|
@@ -121,7 +125,8 @@ Since orders may contain a composition of articles, how would the order service
|
|
121
125
|
<pre>
|
122
126
|
class Order
|
123
127
|
include Roar::Representer::JSON
|
124
|
-
|
128
|
+
include Roar::Representer::Feature::Hypermedia
|
129
|
+
|
125
130
|
property :id
|
126
131
|
property :client_id
|
127
132
|
|
@@ -150,6 +155,7 @@ If we were to implement an endpoint for creating new orders, we'd allow POST to
|
|
150
155
|
post "/orders" do
|
151
156
|
incoming = Order.deserialize(request.body.string)
|
152
157
|
puts incoming.to_attributes #=> {:client_id => 815}
|
158
|
+
end
|
153
159
|
</pre>
|
154
160
|
|
155
161
|
Look how the @#to_attributes@ method helps extracting data from the incoming document and, again, @#to_json@ returns the freshly created order's representation. Roar's representers are truely working in both directions, rendering and parsing and thus prevent you from redundant knowledge sharing.
|
data/Rakefile
CHANGED
@@ -7,7 +7,7 @@ task :default => [:test, :testrails]
|
|
7
7
|
|
8
8
|
Rake::TestTask.new(:test) do |test|
|
9
9
|
test.libs << 'test'
|
10
|
-
test.test_files = FileList['test/*_test.rb'] - ['test/integration_test.rb']
|
10
|
+
test.test_files = FileList['test/*_test.rb'] - ['test/integration_test.rb', 'test/active_record_integration_test.rb']
|
11
11
|
test.verbose = true
|
12
12
|
end
|
13
13
|
|
@@ -52,10 +52,9 @@ module Roar
|
|
52
52
|
# This method is subject to change and might be removed, soon.
|
53
53
|
def deserialize_block_for_options(options)
|
54
54
|
return unless props = options[:except] || options[:include]
|
55
|
-
props.collect!{ |name| name.to_s }
|
56
55
|
|
57
|
-
lambda do |
|
58
|
-
res = props.include?(
|
56
|
+
lambda do |name|
|
57
|
+
res = props.include?(name)
|
59
58
|
options[:include] ? res : !res
|
60
59
|
end
|
61
60
|
end
|
@@ -8,15 +8,14 @@ module Roar
|
|
8
8
|
def self.included(base)
|
9
9
|
base.extend ClassMethods
|
10
10
|
end
|
11
|
-
|
11
|
+
# TODO: read format and base url defaults from Roar::Config.
|
12
12
|
|
13
13
|
module ClassMethods
|
14
14
|
include Transport
|
15
15
|
|
16
|
-
def get(url, format)
|
17
|
-
|
18
|
-
|
19
|
-
deserialize(representation)
|
16
|
+
def get(url, format)
|
17
|
+
document = get_uri(url, format).body
|
18
|
+
deserialize(document)
|
20
19
|
end
|
21
20
|
|
22
21
|
def post(url, body, format)
|
@@ -34,11 +34,14 @@ module Roar
|
|
34
34
|
protected
|
35
35
|
# Setup hypermedia links by invoking their blocks. Usually called by #serialize.
|
36
36
|
def prepare_links!
|
37
|
-
links_def
|
37
|
+
links_def = find_links_definition or return
|
38
|
+
hyperlink_class = links_def.sought_type
|
39
|
+
|
38
40
|
links_def.rel2block.each do |link|
|
39
|
-
links
|
40
|
-
|
41
|
-
|
41
|
+
links.update_link(hyperlink_class.from_attributes( # create Hyperlink representer.
|
42
|
+
:rel => link[:rel],
|
43
|
+
:href => run_link_block(link[:block]))
|
44
|
+
)
|
42
45
|
end
|
43
46
|
end
|
44
47
|
|
@@ -46,16 +49,38 @@ module Roar
|
|
46
49
|
instance_exec(&block)
|
47
50
|
end
|
48
51
|
|
52
|
+
def find_links_definition
|
53
|
+
representable_attrs.find { |d| d.is_a?(LinksDefinition) }
|
54
|
+
end
|
55
|
+
|
49
56
|
|
50
57
|
class LinkCollection < Array
|
51
58
|
def [](rel)
|
52
59
|
link = find { |l| l.rel.to_s == rel.to_s } and return link.href
|
53
60
|
end
|
61
|
+
|
62
|
+
# Checks if the link is already contained by querying for its +rel+.
|
63
|
+
# If so, it gets replaced. Otherwise, the new link gets appended.
|
64
|
+
def update_link(link)
|
65
|
+
if i = find_index { |l| l.rel.to_s == link.rel.to_s }
|
66
|
+
return self[i] = link
|
67
|
+
end
|
68
|
+
self << link
|
69
|
+
end
|
54
70
|
end
|
55
71
|
|
56
72
|
|
57
73
|
module ClassMethods
|
58
|
-
#
|
74
|
+
# Declares a hypermedia link in the document.
|
75
|
+
#
|
76
|
+
# Example:
|
77
|
+
#
|
78
|
+
# link :self do
|
79
|
+
# "http://orders/#{id}"
|
80
|
+
# end
|
81
|
+
#
|
82
|
+
# The block is executed in instance context, so you may call properties or other accessors.
|
83
|
+
# Note that you're free to put decider logic into #link blocks, too.
|
59
84
|
def link(rel, &block)
|
60
85
|
unless links = find_links_definition
|
61
86
|
links = LinksDefinition.new(:links, links_definition_options)
|
@@ -66,7 +91,7 @@ module Roar
|
|
66
91
|
end
|
67
92
|
|
68
93
|
def find_links_definition
|
69
|
-
representable_attrs.find
|
94
|
+
representable_attrs.find { |d| d.is_a?(LinksDefinition) }
|
70
95
|
end
|
71
96
|
end
|
72
97
|
|
@@ -15,7 +15,7 @@ module Roar
|
|
15
15
|
end
|
16
16
|
|
17
17
|
module InstanceMethods
|
18
|
-
def
|
18
|
+
def to_hash(*args)
|
19
19
|
before_serialize(*args)
|
20
20
|
super
|
21
21
|
end
|
@@ -44,7 +44,7 @@ module Roar
|
|
44
44
|
|
45
45
|
# TODO: move to instance method, or remove?
|
46
46
|
def links_definition_options
|
47
|
-
{:as =>
|
47
|
+
{:as => Hyperlink , :collection => true}
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
@@ -52,7 +52,6 @@ module Roar
|
|
52
52
|
# Encapsulates a hypermedia link.
|
53
53
|
class Hyperlink
|
54
54
|
include JSON
|
55
|
-
self.representation_name = :link
|
56
55
|
|
57
56
|
property :rel
|
58
57
|
property :href
|
data/lib/roar/representer/xml.rb
CHANGED
@@ -27,7 +27,7 @@ module Roar
|
|
27
27
|
|
28
28
|
def to_xml(*args)
|
29
29
|
before_serialize(*args)
|
30
|
-
super
|
30
|
+
super
|
31
31
|
end
|
32
32
|
|
33
33
|
# Generic entry-point for rendering.
|
@@ -41,7 +41,7 @@ module Roar
|
|
41
41
|
include Representable::XML::ClassMethods
|
42
42
|
|
43
43
|
def links_definition_options
|
44
|
-
{:from => :link, :as =>
|
44
|
+
{:from => :link, :as => Hyperlink, :collection => true}
|
45
45
|
end
|
46
46
|
|
47
47
|
# Generic entry-point for parsing.
|
@@ -56,7 +56,7 @@ module Roar
|
|
56
56
|
# TODO: make XML a module to include in Hyperlink < Base.
|
57
57
|
include XML
|
58
58
|
|
59
|
-
self.
|
59
|
+
self.representation_wrap = :link
|
60
60
|
|
61
61
|
property :rel, :from => "@rel"
|
62
62
|
property :href, :from => "@href"
|
data/lib/roar/version.rb
CHANGED
data/roar.gemspec
CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_runtime_dependency "representable", "~> 0.
|
22
|
+
s.add_runtime_dependency "representable", "~> 0.10.3"
|
23
23
|
s.add_runtime_dependency "hooks", "~> 0.1.4"
|
24
24
|
|
25
25
|
s.add_development_dependency "test_xml"
|
data/test/Gemfile
CHANGED
data/test/fake_server.rb
CHANGED
@@ -1,9 +1,30 @@
|
|
1
1
|
require "bundler/setup"
|
2
2
|
require 'sinatra/base'
|
3
3
|
require 'sinatra/reloader'
|
4
|
+
require 'roar/representer/xml'
|
5
|
+
|
6
|
+
# Usually shared in a gem between service and clients.
|
7
|
+
module BandRepresenter
|
8
|
+
include Roar::Representer::XML
|
9
|
+
property :name
|
10
|
+
property :label
|
11
|
+
end
|
12
|
+
|
13
|
+
Band = Struct.new(:name, :label)
|
14
|
+
Band.class_eval do
|
15
|
+
include Roar::Representer::XML
|
16
|
+
include BandRepresenter
|
17
|
+
end
|
4
18
|
|
5
19
|
|
6
|
-
class FakeServer < Sinatra::Base
|
20
|
+
class FakeServer < Sinatra::Base
|
21
|
+
BANDS = {"belvedere" => Band.new("Belvedere", "canadian maple")}
|
22
|
+
|
23
|
+
get "/bands/:id" do
|
24
|
+
BANDS[params[:id]].to_xml
|
25
|
+
end
|
26
|
+
|
27
|
+
|
7
28
|
get "/method" do
|
8
29
|
"<method>get</method>"
|
9
30
|
end
|
@@ -13,34 +13,55 @@ class HttpVerbsTest < MiniTest::Spec
|
|
13
13
|
|
14
14
|
describe "HttpVerbs" do
|
15
15
|
before do
|
16
|
-
@r = Band.new
|
16
|
+
@r = @band = Band.new
|
17
17
|
end
|
18
18
|
|
19
19
|
# TODO: assert that Restfulie#post receives the correct document.
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
describe "#post" do
|
22
|
+
it "#deserializes the incoming representation and returns it" do
|
23
|
+
@r.name = "Strung Out"
|
24
|
+
rep = @r.post("http://localhost:9999/band", "application/xml")
|
25
|
+
assert_equal "Strung Out", rep.name
|
26
|
+
assert_equal "n/a", rep.label
|
27
|
+
end
|
26
28
|
end
|
27
29
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
30
|
+
describe "#post!" do
|
31
|
+
it "#post! deserializes the incoming representation and replaces attributes" do
|
32
|
+
@r.name = "Strung Out"
|
33
|
+
assert_equal nil, @r.label
|
34
|
+
@r.post!("http://localhost:9999/band", "application/xml")
|
35
|
+
assert_equal "Strung Out", @r.name
|
36
|
+
assert_equal "n/a", @r.label
|
37
|
+
end
|
34
38
|
end
|
35
39
|
|
40
|
+
describe "#put!" do
|
41
|
+
it "deserializes the incoming representation and returns it" do
|
42
|
+
@r.name = "Strung Out"
|
43
|
+
@r.label = "Fat Wreck"
|
44
|
+
rep = @r.put("http://localhost:9999/band/strungout", "application/xml")
|
45
|
+
assert_equal "Strung Out", rep.name
|
46
|
+
assert_equal "Fat Wreck", rep.label
|
47
|
+
end
|
48
|
+
end
|
36
49
|
|
50
|
+
describe ".get" do
|
51
|
+
it "returns the deserialized retrieved doc" do
|
52
|
+
band = Band.get("http://localhost:9999/bands/belvedere", "application/xml")
|
53
|
+
assert_equal "Belvedere", band.name
|
54
|
+
assert_equal "canadian maple", band.label
|
55
|
+
end
|
56
|
+
end
|
37
57
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
58
|
+
describe "#get!" do
|
59
|
+
it "retrieves, deserializes and updates properties" do
|
60
|
+
band = @band.get!("http://localhost:9999/bands/belvedere", "application/xml")
|
61
|
+
assert_equal "Belvedere", band.name
|
62
|
+
assert_equal "canadian maple", band.label
|
63
|
+
end
|
44
64
|
end
|
65
|
+
|
45
66
|
end
|
46
67
|
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
require 'roar/representer/feature/hypermedia'
|
3
|
+
require 'roar/representer/json'
|
3
4
|
|
4
5
|
class HypermediaTest
|
5
6
|
describe "Hypermedia Feature" do
|
@@ -8,11 +9,13 @@ class HypermediaTest
|
|
8
9
|
include Roar::Representer::XML
|
9
10
|
include Roar::Representer::Feature::Hypermedia
|
10
11
|
|
11
|
-
self.
|
12
|
+
self.representation_wrap = "bookmarks"
|
12
13
|
end
|
13
14
|
|
14
15
|
@bookmarks_with_links = Class.new(@bookmarks)
|
15
16
|
@bookmarks_with_links.class_eval do
|
17
|
+
self.representation_wrap = "bookmarks"
|
18
|
+
|
16
19
|
property :id
|
17
20
|
link :self do "http://bookmarks" end
|
18
21
|
link :all do "http://bookmarks/all" end
|
@@ -39,10 +42,32 @@ class HypermediaTest
|
|
39
42
|
</bookmarks>',
|
40
43
|
@bookmarks_with_links.from_attributes(:id => 1).to_xml(:links => false)
|
41
44
|
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#to_json" do
|
48
|
+
class Note
|
49
|
+
include Roar::Representer::JSON
|
50
|
+
include Roar::Representer::Feature::Hypermedia
|
51
|
+
link(:self) { "http://me" }
|
52
|
+
end
|
53
|
+
|
54
|
+
it "works twice" do
|
55
|
+
note = Note.new
|
56
|
+
assert_equal note.to_json, note.to_json
|
57
|
+
end
|
42
58
|
|
59
|
+
it "sets up links even when nested" do
|
60
|
+
class Page
|
61
|
+
include Roar::Representer::JSON
|
62
|
+
property :note, :as => Note
|
63
|
+
end
|
64
|
+
|
65
|
+
assert_equal "{\"note\":{\"links\":[{\"rel\":\"self\",\"href\":\"http://me\"}]}}", Page.from_attributes(note: Note.new).to_json
|
66
|
+
end
|
43
67
|
end
|
44
68
|
|
45
69
|
|
70
|
+
|
46
71
|
describe "#from_xml" do
|
47
72
|
it "extracts links from document" do
|
48
73
|
doc = @bookmarks_with_links.from_xml(%{
|
@@ -130,3 +155,19 @@ class LinksDefinitionTest < MiniTest::Spec
|
|
130
155
|
|
131
156
|
end
|
132
157
|
end
|
158
|
+
|
159
|
+
class LinkCollectionTest < MiniTest::Spec
|
160
|
+
describe "LinkCollection" do
|
161
|
+
it "provides #update_link" do
|
162
|
+
collection = Roar::Representer::Feature::Hypermedia::LinkCollection.new
|
163
|
+
link = Roar::Representer::XML::Hyperlink.from_attributes(rel: "self", href: "http://self")
|
164
|
+
|
165
|
+
collection.update_link(link)
|
166
|
+
assert_equal 1, collection.size
|
167
|
+
|
168
|
+
collection.update_link(link)
|
169
|
+
assert_equal 1, collection.size
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
data/test/integration_test.rb
CHANGED
@@ -1,122 +1,85 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
|
3
|
-
require 'roar/representer/xml'
|
4
2
|
require 'roar/representer/json'
|
5
|
-
|
6
|
-
require 'roar/representer/feature/http_verbs'
|
7
3
|
require 'roar/representer/feature/hypermedia'
|
8
4
|
|
9
|
-
class
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
link :search do
|
21
|
-
search_url
|
22
|
-
end
|
23
|
-
|
24
|
-
link :self do
|
25
|
-
order_url(represented)
|
26
|
-
end
|
5
|
+
class IntegrationTest < MiniTest::Spec
|
6
|
+
class Beer
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
include Roar::Representer::Feature::Hypermedia
|
9
|
+
|
10
|
+
property :name
|
11
|
+
|
12
|
+
link :self do
|
13
|
+
"http://beers/#{name.downcase}"
|
27
14
|
end
|
28
15
|
end
|
29
16
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
property :name
|
36
|
-
property :label
|
37
|
-
|
38
|
-
include Roar::Representer::Feature::HttpVerbs
|
39
|
-
include Roar::Representer::Feature::Hypermedia
|
40
|
-
|
41
|
-
|
42
|
-
link :search do
|
43
|
-
search_url
|
44
|
-
end
|
45
|
-
|
46
|
-
link :self do
|
47
|
-
order_url(represented)
|
48
|
-
end
|
49
|
-
end
|
17
|
+
class Beers
|
18
|
+
include Roar::Representer::JSON
|
19
|
+
include Roar::Representer::Feature::Hypermedia
|
20
|
+
|
21
|
+
collection :items, :as => Beer
|
50
22
|
end
|
51
23
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
@r = @r.post("http://localhost:9999/band", "application/band+json")
|
62
|
-
assert_equal "n/a", @r.label
|
63
|
-
|
64
|
-
# check HATEOAS:
|
65
|
-
#@r.extend Roar::Representer::Feature::Hypermedia
|
66
|
-
assert_equal "http://search", @r.links[:search]
|
67
|
-
assert_equal "http://band/strungout", @r.links[:self]
|
24
|
+
describe "Beer service" do
|
25
|
+
it "provides a document for a particular beer" do
|
26
|
+
assert_equal "{\"beer\":{\"name\":\"Eisenbahn\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/eisenbahn\"}]}}", Beer.from_attributes(name: "Eisenbahn").to_json
|
27
|
+
end
|
28
|
+
|
29
|
+
it "provides a detailed beers list" do
|
30
|
+
beers = ["Jever", "Becks", "Eisenbahn", "Colorado"].collect do |name|
|
31
|
+
Beer.from_attributes(name: name)
|
68
32
|
end
|
69
33
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
assert_equal "http://localhost:9999/orders/1", @o.links[:self]
|
82
|
-
|
83
|
-
|
84
|
-
# manually POST item:
|
85
|
-
@i = ::JSON::Item.from_attributes(:article_id => "666-S", :amount => 1)
|
86
|
-
@i.post!(@o.links[:items], "application/item+json")
|
87
|
-
@o.get!(@o.links[:self], "application/order+json")
|
34
|
+
|
35
|
+
list = Beers.new
|
36
|
+
list.items = beers
|
37
|
+
|
38
|
+
assert_equal "{\"beers\":{\"items\":[{\"name\":\"Jever\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/jever\"}]},{\"name\":\"Becks\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/becks\"}]},{\"name\":\"Eisenbahn\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/eisenbahn\"}]},{\"name\":\"Colorado\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/colorado\"}]}]}}", list.to_json
|
39
|
+
end
|
40
|
+
|
41
|
+
it "provides a pageable beers list without details" do
|
42
|
+
class BeerCollection
|
43
|
+
include Roar::Representer::JSON
|
44
|
+
include Roar::Representer::Feature::Hypermedia
|
88
45
|
|
89
|
-
|
90
|
-
assert_equal 1, @o.items.size
|
91
|
-
assert_equal @i.to_attributes, @o.items.first.to_attributes
|
46
|
+
attr_accessor :per_page, :current_page, :all_items
|
92
47
|
|
48
|
+
collection :beers, :as => Beer
|
49
|
+
property :total
|
93
50
|
|
94
|
-
|
51
|
+
def total
|
52
|
+
all_items.size
|
53
|
+
end
|
95
54
|
|
96
|
-
|
97
|
-
|
55
|
+
def beers
|
56
|
+
all_items[(current_page-1)*per_page..current_page*per_page-1]
|
57
|
+
end
|
98
58
|
|
99
|
-
|
59
|
+
link :next do
|
60
|
+
"http://beers/all?page=#{current_page+1}" if current_page < total / per_page
|
61
|
+
end
|
100
62
|
|
63
|
+
link :prev do
|
64
|
+
"http://beers/all?page=#{current_page-1}" if current_page > 1
|
65
|
+
end
|
101
66
|
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
it "allows a POST workflow" do
|
106
|
-
# create representation with initial values:
|
107
|
-
@r = XML::Band.from_attributes(:name => "Bigwig")
|
108
|
-
assert_equal "Bigwig", @r.name
|
109
|
-
|
110
|
-
@r = @r.post("http://localhost:9999/band", "application/band+xml")
|
111
|
-
assert_equal "n/a", @r.label
|
112
|
-
|
113
|
-
# check HATEOAS:
|
114
|
-
#@r.extend Roar::Representer::Feature::Hypermedia
|
115
|
-
assert_equal "http://search", @r.links[:search]
|
116
|
-
assert_equal "http://band/strungout", @r.links[:self]
|
67
|
+
|
68
|
+
beers = ["Jever", "Becks", "Eisenbahn", "Colorado"].collect do |name|
|
69
|
+
Beer.from_attributes(name: name)
|
117
70
|
end
|
71
|
+
|
72
|
+
|
73
|
+
list = BeerCollection.new
|
74
|
+
list.all_items = beers # this would be a AR collection from a #find.
|
75
|
+
list.current_page = 1
|
76
|
+
list.per_page = 2
|
77
|
+
|
78
|
+
assert_equal "{\"beer_collection\":{\"beers\":[{\"name\":\"Jever\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/jever\"}]},{\"name\":\"Becks\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/becks\"}]}],\"total\":4,\"links\":[{\"rel\":\"next\",\"href\":\"http://beers/all?page=2\"},{\"rel\":\"prev\"}]}}", list.to_json
|
79
|
+
|
80
|
+
|
81
|
+
list.current_page = 2
|
82
|
+
assert_equal "{\"beers\":[{\"name\":\"Eisenbahn\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/eisenbahn\"}]},{\"name\":\"Colorado\",\"links\":[{\"rel\":\"self\",\"href\":\"http://beers/colorado\"}]}],\"total\":4,\"links\":[{\"rel\":\"next\"},{\"rel\":\"prev\",\"href\":\"http://beers/all?page=1\"}]}", list.to_json(wrap: false)
|
118
83
|
end
|
119
|
-
|
120
|
-
|
121
84
|
end
|
122
85
|
end
|
@@ -19,24 +19,24 @@ class JsonRepresenterTest < MiniTest::Spec
|
|
19
19
|
describe "#to_json" do
|
20
20
|
it "#serialize returns the serialized model" do
|
21
21
|
@r.id = 1
|
22
|
-
assert_equal '{"
|
22
|
+
assert_equal '{"id":1}', @r.to_json
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
describe ".from_json" do
|
27
27
|
it "returns the deserialized model" do
|
28
|
-
@m = Order.from_json('{"
|
28
|
+
@m = Order.from_json('{"id":1}')
|
29
29
|
assert_equal 1, @m.id
|
30
30
|
end
|
31
31
|
|
32
32
|
it "accepts :except option" do
|
33
|
-
order = Order.from_json({
|
33
|
+
order = Order.from_json({id: 1, pending: 1}.to_json, :except => [:id])
|
34
34
|
assert_equal nil, order.id
|
35
35
|
assert_equal 1, order.pending
|
36
36
|
end
|
37
37
|
|
38
38
|
it "accepts :include option" do
|
39
|
-
order = Order.from_json({
|
39
|
+
order = Order.from_json({id: 1, pending: 1}.to_json, :include => [:id])
|
40
40
|
assert_equal 1, order.id
|
41
41
|
assert_equal nil, order.pending
|
42
42
|
end
|
@@ -51,14 +51,9 @@ end
|
|
51
51
|
class JsonHyperlinkRepresenterTest
|
52
52
|
describe "API" do
|
53
53
|
before do
|
54
|
-
@l = Roar::Representer::JSON::Hyperlink.from_json({:
|
54
|
+
@l = Roar::Representer::JSON::Hyperlink.from_json({:rel => :self, :href => "http://roar.apotomo.de"}.to_json)
|
55
55
|
end
|
56
56
|
|
57
|
-
it "responds to #representation_name" do
|
58
|
-
assert_equal :link, @l.class.representation_name
|
59
|
-
end
|
60
|
-
|
61
|
-
|
62
57
|
it "responds to #rel" do
|
63
58
|
assert_equal "self", @l.rel
|
64
59
|
end
|
@@ -76,8 +71,6 @@ class JsonHypermediaTest
|
|
76
71
|
include Roar::Representer::JSON
|
77
72
|
include Roar::Representer::Feature::Hypermedia
|
78
73
|
|
79
|
-
self.representation_name= :order
|
80
|
-
|
81
74
|
property :id
|
82
75
|
|
83
76
|
link :self do "http://self" end
|
@@ -92,14 +85,14 @@ class JsonHypermediaTest
|
|
92
85
|
end
|
93
86
|
|
94
87
|
it "extracts links from JSON" do
|
95
|
-
@r = @c.from_json({:
|
88
|
+
@r = @c.from_json({:links => [{:rel => "self", :href => "http://self"}]}.to_json)
|
96
89
|
|
97
90
|
assert_equal 1, @r.links.size
|
98
91
|
assert_equal({"rel"=>"self", "href"=>"http://self"}, @r.links.first.to_attributes)
|
99
92
|
end
|
100
93
|
|
101
94
|
it "renders link: correctly in JSON" do
|
102
|
-
assert_equal "{\"
|
95
|
+
assert_equal "{\"id\":1,\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"},{\"rel\":\"next\",\"href\":\"http://next/1\"}]}", @c.from_attributes(:id => 1).to_json
|
103
96
|
end
|
104
97
|
end
|
105
98
|
end
|
@@ -6,14 +6,14 @@ class ModelRepresentingTest < MiniTest::Spec
|
|
6
6
|
class ItemRepresenter
|
7
7
|
include Roar::Representer::XML
|
8
8
|
include Roar::Representer::Feature::ModelRepresenting
|
9
|
-
self.
|
9
|
+
self.representation_wrap= :item
|
10
10
|
property :value
|
11
11
|
end
|
12
12
|
|
13
13
|
class PositionRepresenter
|
14
14
|
include Roar::Representer::XML
|
15
15
|
include Roar::Representer::Feature::ModelRepresenting
|
16
|
-
self.
|
16
|
+
self.representation_wrap= :position
|
17
17
|
property :id
|
18
18
|
property :item, :as => ItemRepresenter
|
19
19
|
end
|
@@ -21,7 +21,7 @@ class ModelRepresentingTest < MiniTest::Spec
|
|
21
21
|
class OrderRepresenter
|
22
22
|
include Roar::Representer::XML
|
23
23
|
include Roar::Representer::Feature::ModelRepresenting
|
24
|
-
self.
|
24
|
+
self.representation_wrap= :order
|
25
25
|
property :id
|
26
26
|
collection :items, :as => ItemRepresenter
|
27
27
|
end
|
data/test/representer_test.rb
CHANGED
@@ -41,14 +41,18 @@ class RepresenterTest < MiniTest::Spec
|
|
41
41
|
end
|
42
42
|
|
43
43
|
describe "Inheritance" do
|
44
|
-
it "properly inherits properties" do
|
45
|
-
|
44
|
+
it "properly inherits properties from modules" do
|
45
|
+
module PersonRepresentation
|
46
46
|
include Roar::Representer::JSON
|
47
|
-
self.representation_name= "collection"
|
48
47
|
property :name
|
49
48
|
end
|
50
49
|
|
51
|
-
|
50
|
+
class Person
|
51
|
+
include Roar::Representer::JSON
|
52
|
+
include PersonRepresentation
|
53
|
+
end
|
54
|
+
|
55
|
+
assert_equal "{\"name\":\"Paulo\"}", Person.from_attributes(:name => "Paulo").to_json
|
52
56
|
end
|
53
57
|
|
54
58
|
end
|
data/test/test_helper.rb
CHANGED
@@ -8,9 +8,6 @@ require 'roar/representer/base'
|
|
8
8
|
require 'roar/representer/feature/hypermedia'
|
9
9
|
require 'roar/representer/feature/http_verbs'
|
10
10
|
|
11
|
-
require 'stringio' # FIXME. remove for 3.0.4.
|
12
|
-
require 'builder'
|
13
|
-
|
14
11
|
module TestModel
|
15
12
|
def self.included(base)
|
16
13
|
base.extend ClassMethods
|
@@ -2,13 +2,13 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
class ItemRepresenter
|
4
4
|
include Roar::Representer::XML
|
5
|
-
self.
|
5
|
+
self.representation_wrap= :item
|
6
6
|
property :value
|
7
7
|
end
|
8
8
|
|
9
9
|
class PositionRepresenter
|
10
10
|
include Roar::Representer::XML
|
11
|
-
self.
|
11
|
+
self.representation_wrap= :position
|
12
12
|
property :id
|
13
13
|
property :item, :as => ItemRepresenter
|
14
14
|
end
|
@@ -48,7 +48,7 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
48
48
|
|
49
49
|
class TestXmlRepresenter
|
50
50
|
include Roar::Representer::XML
|
51
|
-
self.
|
51
|
+
self.representation_wrap= :order # FIXME: get from represented?
|
52
52
|
property :id
|
53
53
|
end
|
54
54
|
|
@@ -120,9 +120,9 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
120
120
|
assert_equal "1", @m.id
|
121
121
|
end
|
122
122
|
|
123
|
-
it ".from_xml still works with nil" do
|
124
|
-
|
125
|
-
end
|
123
|
+
#it ".from_xml still works with nil" do
|
124
|
+
# assert TestXmlRepresenter.from_xml(nil)
|
125
|
+
#end
|
126
126
|
|
127
127
|
end
|
128
128
|
|
@@ -155,7 +155,7 @@ class XMLRepresenterFunctionalTest < MiniTest::Spec
|
|
155
155
|
@c = Class.new do
|
156
156
|
include Roar::Representer::XML
|
157
157
|
|
158
|
-
self.
|
158
|
+
self.representation_wrap= :order
|
159
159
|
property :id
|
160
160
|
collection :items, :as => ItemRepresenter, :from => :item
|
161
161
|
end
|
@@ -193,7 +193,7 @@ class XmlHyperlinkRepresenterTest < MiniTest::Spec
|
|
193
193
|
end
|
194
194
|
|
195
195
|
it "responds to #representation_name" do
|
196
|
-
assert_equal :link, @l.class.
|
196
|
+
assert_equal :link, @l.class.representation_wrap
|
197
197
|
end
|
198
198
|
|
199
199
|
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 8
|
8
|
-
-
|
9
|
-
version: 0.8.
|
8
|
+
- 3
|
9
|
+
version: 0.8.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Nick Sutterer
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-
|
17
|
+
date: 2011-12-08 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -27,9 +27,9 @@ dependencies:
|
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
29
|
- 0
|
30
|
-
-
|
31
|
-
-
|
32
|
-
version: 0.
|
30
|
+
- 10
|
31
|
+
- 3
|
32
|
+
version: 0.10.3
|
33
33
|
type: :runtime
|
34
34
|
version_requirements: *id001
|
35
35
|
- !ruby/object:Gem::Dependency
|