roar 0.8.2 → 0.8.3
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.
- 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
|