roar 0.8.0 → 0.8.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +2 -2
- data/README.textile +8 -2
- data/Rakefile +1 -1
- data/lib/roar/rails/representer_methods.rb +2 -1
- data/lib/roar/representer/base.rb +65 -0
- data/lib/roar/representer/feature/http_verbs.rb +6 -7
- data/lib/roar/representer/feature/hypermedia.rb +53 -13
- data/lib/roar/representer/feature/model_representing.rb +19 -27
- data/lib/roar/representer/json.rb +44 -14
- data/lib/roar/representer/xml.rb +48 -24
- data/lib/roar/version.rb +1 -1
- data/roar.gemspec +3 -3
- data/test/{http_verbs_test.rb → http_verbs_feature_test.rb} +3 -3
- data/test/hypermedia_feature_test.rb +132 -0
- data/test/integration_test.rb +8 -8
- data/test/json_representer_test.rb +31 -26
- data/test/model_representing_test.rb +21 -23
- data/test/order_representers.rb +5 -2
- data/test/representer_test.rb +35 -5
- data/test/test_helper.rb +28 -7
- data/test/xml_representer_test.rb +60 -90
- metadata +11 -17
- data/lib/roar/model.rb +0 -36
- data/lib/roar/model/representable.rb +0 -31
- data/lib/roar/representer.rb +0 -72
- data/test/hypermedia_test.rb +0 -35
- data/test/model_test.rb +0 -50
- data/test/proxy_test.rb +0 -89
- data/test/representable_test.rb +0 -49
- data/test/ruby_representation_test.rb +0 -144
- data/test/test_helper_test.rb +0 -59
- data/test/xml_hypermedia_test.rb +0 -47
data/lib/roar/version.rb
CHANGED
data/roar.gemspec
CHANGED
@@ -19,11 +19,11 @@ 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"
|
22
|
+
s.add_runtime_dependency "representable", "~> 0.9.2"
|
23
23
|
s.add_runtime_dependency "restfulie", "~> 1.0.0"
|
24
24
|
s.add_runtime_dependency "hooks", "~> 0.1.4"
|
25
|
-
|
26
|
-
|
25
|
+
|
26
|
+
s.add_development_dependency "test_xml"
|
27
27
|
s.add_development_dependency "minitest", "~> 1.6.0"
|
28
28
|
s.add_development_dependency "sinatra", "~> 1.2.6"
|
29
29
|
s.add_development_dependency "sinatra-reloader", "~> 0.5.0"
|
@@ -2,8 +2,8 @@ require 'test_helper'
|
|
2
2
|
require 'roar/representer/feature/http_verbs'
|
3
3
|
|
4
4
|
class HttpVerbsTest < MiniTest::Spec
|
5
|
-
class
|
6
|
-
|
5
|
+
class Band
|
6
|
+
include Roar::Representer::XML
|
7
7
|
|
8
8
|
property :name
|
9
9
|
property :label
|
@@ -13,7 +13,7 @@ class HttpVerbsTest < MiniTest::Spec
|
|
13
13
|
|
14
14
|
describe "HttpVerbs" do
|
15
15
|
before do
|
16
|
-
@r =
|
16
|
+
@r = Band.new
|
17
17
|
end
|
18
18
|
|
19
19
|
# TODO: assert that Restfulie#post receives the correct document.
|
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/representer/feature/hypermedia'
|
3
|
+
|
4
|
+
class HypermediaTest
|
5
|
+
describe "Hypermedia Feature" do
|
6
|
+
before do
|
7
|
+
@bookmarks = Class.new do
|
8
|
+
include Roar::Representer::XML
|
9
|
+
include Roar::Representer::Feature::Hypermedia
|
10
|
+
|
11
|
+
self.representation_name = "bookmarks"
|
12
|
+
end
|
13
|
+
|
14
|
+
@bookmarks_with_links = Class.new(@bookmarks)
|
15
|
+
@bookmarks_with_links.class_eval do
|
16
|
+
property :id
|
17
|
+
link :self do "http://bookmarks" end
|
18
|
+
link :all do "http://bookmarks/all" end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
describe "#to_xml" do
|
24
|
+
it "sets up links and renders <link> correctly in XML" do
|
25
|
+
assert_xml_equal '<bookmarks>
|
26
|
+
<id>1</id>
|
27
|
+
<link rel="self" href="http://bookmarks"/>
|
28
|
+
<link rel="all" href="http://bookmarks/all"/>
|
29
|
+
</bookmarks>', @bookmarks_with_links.from_attributes(:id => 1).to_xml
|
30
|
+
end
|
31
|
+
|
32
|
+
it "still works even if there are no links defined" do
|
33
|
+
assert_xml_equal '<bookmarks/>', @bookmarks.new.to_xml
|
34
|
+
end
|
35
|
+
|
36
|
+
it "doesn't render links with :links => false" do
|
37
|
+
assert_xml_equal '<bookmarks>
|
38
|
+
<id>1</id>
|
39
|
+
</bookmarks>',
|
40
|
+
@bookmarks_with_links.from_attributes(:id => 1).to_xml(:links => false)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
describe "#from_xml" do
|
47
|
+
it "extracts links from document" do
|
48
|
+
doc = @bookmarks_with_links.from_xml(%{
|
49
|
+
<bookmarks>
|
50
|
+
<link rel="self" href="http://bookmarks">
|
51
|
+
</bookmarks>
|
52
|
+
})
|
53
|
+
|
54
|
+
assert_kind_of Roar::Representer::Feature::Hypermedia::LinkCollection, doc.links
|
55
|
+
assert_equal 1, doc.links.size
|
56
|
+
assert_equal({"rel"=>"self", "href"=>"http://bookmarks"}, doc.links.first.to_attributes)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "sets up an empty link list if no links found in the document" do
|
60
|
+
assert_equal [], @bookmarks_with_links.from_xml(%{<bookmarks/>}).links
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
|
65
|
+
describe "#links" do
|
66
|
+
before do
|
67
|
+
@set = @bookmarks.new
|
68
|
+
hyper = Roar::Representer::XML::Hyperlink
|
69
|
+
|
70
|
+
@set.links = [hyper.from_attributes({"rel" => "self", "href" => "http://self"}),
|
71
|
+
hyper.from_attributes({"rel" => "next", "href" => "http://next"})]
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "#links=" do
|
75
|
+
it "wraps links in a LinkCollection" do
|
76
|
+
assert_kind_of Roar::Representer::Feature::Hypermedia::LinkCollection, @set.links
|
77
|
+
assert_equal 2, @set.links.size
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#link[]" do
|
82
|
+
it "provides shorthand accessor for rels" do
|
83
|
+
assert_equal "http://self", @set.links["self"]
|
84
|
+
assert_equal "http://self", @set.links[:self]
|
85
|
+
assert_equal "http://next", @set.links[:next]
|
86
|
+
assert_equal nil, @set.links[:prev]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
it "returns an empty list when no links present" do
|
91
|
+
assert_equal Roar::Representer::Feature::Hypermedia::LinkCollection.new, @bookmarks.new.links
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
|
96
|
+
describe "#find_links_definition" do
|
97
|
+
it "returns Definition if links are present" do
|
98
|
+
@bookmarks.class_eval do
|
99
|
+
property :id
|
100
|
+
link :self
|
101
|
+
end
|
102
|
+
|
103
|
+
assert_equal "links", @bookmarks.find_links_definition.name
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns nil if no links defined" do
|
107
|
+
assert_equal nil, @bookmarks.find_links_definition
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
class LinksDefinitionTest < MiniTest::Spec
|
114
|
+
describe "LinksDefinition" do
|
115
|
+
before do
|
116
|
+
@d = Roar::Representer::Feature::Hypermedia::LinksDefinition.new(:links)
|
117
|
+
end
|
118
|
+
|
119
|
+
it "accepts options in constructor" do
|
120
|
+
assert_equal [], @d.rel2block
|
121
|
+
end
|
122
|
+
|
123
|
+
it "accepts configuration" do
|
124
|
+
@d.rel2block << {:rel => :self}
|
125
|
+
assert_equal [{:rel=>:self}], @d.rel2block
|
126
|
+
end
|
127
|
+
|
128
|
+
it "responds to #each to iterate rel2block" do
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
data/test/integration_test.rb
CHANGED
@@ -8,8 +8,8 @@ require 'roar/representer/feature/hypermedia'
|
|
8
8
|
|
9
9
|
class RepresenterIntegrationTest < MiniTest::Spec
|
10
10
|
module XML
|
11
|
-
class
|
12
|
-
|
11
|
+
class Band
|
12
|
+
include Roar::Representer::XML
|
13
13
|
|
14
14
|
property :name
|
15
15
|
property :label
|
@@ -29,8 +29,8 @@ class RepresenterIntegrationTest < MiniTest::Spec
|
|
29
29
|
|
30
30
|
# TODO: inherit properly.
|
31
31
|
module JSON
|
32
|
-
class
|
33
|
-
|
32
|
+
class Band
|
33
|
+
include Roar::Representer::JSON
|
34
34
|
|
35
35
|
property :name
|
36
36
|
property :label
|
@@ -55,7 +55,7 @@ class RepresenterIntegrationTest < MiniTest::Spec
|
|
55
55
|
describe "JSON" do
|
56
56
|
it "allows a POST workflow" do
|
57
57
|
# create representation with initial values:
|
58
|
-
@r = JSON::
|
58
|
+
@r = JSON::Band.from_attributes(:name => "Bigwig")
|
59
59
|
assert_equal "Bigwig", @r.name
|
60
60
|
|
61
61
|
@r = @r.post("http://localhost:9999/band", "application/band+json")
|
@@ -70,7 +70,7 @@ class RepresenterIntegrationTest < MiniTest::Spec
|
|
70
70
|
# TODO: implement me.
|
71
71
|
it "allows an ordering workflow" do
|
72
72
|
# create representation with initial values:
|
73
|
-
@o = ::JSON::Order.
|
73
|
+
@o = ::JSON::Order.from_attributes(:client_id => 1)
|
74
74
|
assert_equal 1, @o.client_id
|
75
75
|
|
76
76
|
@o.post!("http://localhost:9999/orders", "application/order+json")
|
@@ -82,7 +82,7 @@ class RepresenterIntegrationTest < MiniTest::Spec
|
|
82
82
|
|
83
83
|
|
84
84
|
# manually POST item:
|
85
|
-
@i = ::JSON::Item.
|
85
|
+
@i = ::JSON::Item.from_attributes(:article_id => "666-S", :amount => 1)
|
86
86
|
@i.post!(@o.links[:items], "application/item+json")
|
87
87
|
@o.get!(@o.links[:self], "application/order+json")
|
88
88
|
|
@@ -104,7 +104,7 @@ class RepresenterIntegrationTest < MiniTest::Spec
|
|
104
104
|
describe "XML" do
|
105
105
|
it "allows a POST workflow" do
|
106
106
|
# create representation with initial values:
|
107
|
-
@r = XML::
|
107
|
+
@r = XML::Band.from_attributes(:name => "Bigwig")
|
108
108
|
assert_equal "Bigwig", @r.name
|
109
109
|
|
110
110
|
@r = @r.post("http://localhost:9999/band", "application/band+xml")
|
@@ -3,37 +3,49 @@ require 'test_helper'
|
|
3
3
|
require "test_xml/mini_test"
|
4
4
|
require "roar/representer/json"
|
5
5
|
|
6
|
-
class
|
7
|
-
class
|
8
|
-
|
9
|
-
|
6
|
+
class JsonRepresenterTest < MiniTest::Spec
|
7
|
+
class Order
|
8
|
+
include Roar::Representer::JSON
|
9
|
+
property :id
|
10
|
+
property :pending
|
10
11
|
end
|
11
12
|
|
12
13
|
|
13
14
|
describe "JsonRepresenter" do
|
14
15
|
before do
|
15
|
-
@r =
|
16
|
+
@r = Order.new
|
16
17
|
end
|
17
18
|
|
18
19
|
describe "#to_json" do
|
19
20
|
it "#serialize returns the serialized model" do
|
20
21
|
@r.id = 1
|
21
|
-
assert_equal '{"order":{"id":1}}', @r.
|
22
|
+
assert_equal '{"order":{"id":1}}', @r.to_json
|
22
23
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
end
|
25
|
+
|
26
|
+
describe ".from_json" do
|
27
|
+
it "returns the deserialized model" do
|
28
|
+
@m = Order.from_json('{"order": {"id":1}}')
|
27
29
|
assert_equal 1, @m.id
|
28
30
|
end
|
29
31
|
|
30
|
-
it "
|
31
|
-
|
32
|
+
it "accepts :except option" do
|
33
|
+
order = Order.from_json({order: {id: 1, pending: 1}}.to_json, :except => [:id])
|
34
|
+
assert_equal nil, order.id
|
35
|
+
assert_equal 1, order.pending
|
36
|
+
end
|
37
|
+
|
38
|
+
it "accepts :include option" do
|
39
|
+
order = Order.from_json({order: {id: 1, pending: 1}}.to_json, :include => [:id])
|
40
|
+
assert_equal 1, order.id
|
41
|
+
assert_equal nil, order.pending
|
32
42
|
end
|
33
43
|
|
44
|
+
it "works with a nil document" do
|
45
|
+
assert Order.from_json(nil)
|
46
|
+
end
|
34
47
|
end
|
35
48
|
end
|
36
|
-
|
37
49
|
end
|
38
50
|
|
39
51
|
class JsonHyperlinkRepresenterTest
|
@@ -60,12 +72,13 @@ end
|
|
60
72
|
class JsonHypermediaTest
|
61
73
|
describe "Hypermedia API" do
|
62
74
|
before do
|
63
|
-
@c = Class.new
|
75
|
+
@c = Class.new do
|
76
|
+
include Roar::Representer::JSON
|
64
77
|
include Roar::Representer::Feature::Hypermedia
|
65
78
|
|
66
79
|
self.representation_name= :order
|
67
80
|
|
68
|
-
|
81
|
+
property :id
|
69
82
|
|
70
83
|
link :self do "http://self" end
|
71
84
|
link :next do "http://next/#{id}" end
|
@@ -75,27 +88,19 @@ class JsonHypermediaTest
|
|
75
88
|
end
|
76
89
|
|
77
90
|
it "responds to #links" do
|
78
|
-
assert_equal
|
79
|
-
end
|
80
|
-
|
81
|
-
it "computes links in #from_attributes" do
|
82
|
-
@r = @c.from_attributes({"id" => 1})
|
83
|
-
assert_equal 2, @r.links.size
|
84
|
-
assert_equal({"rel"=>:self, "href"=>"http://self"}, @r.links.first.to_attributes)
|
85
|
-
assert_equal({"rel"=>:next, "href"=>"http://next/1"}, @r.links.last.to_attributes)
|
91
|
+
assert_equal [], @r.links
|
86
92
|
end
|
87
93
|
|
88
94
|
it "extracts links from JSON" do
|
89
|
-
@r = @c.
|
95
|
+
@r = @c.from_json({:order => {:links => [{:rel => "self", :href => "http://self"}]}}.to_json)
|
90
96
|
|
91
97
|
assert_equal 1, @r.links.size
|
92
98
|
assert_equal({"rel"=>"self", "href"=>"http://self"}, @r.links.first.to_attributes)
|
93
99
|
end
|
94
100
|
|
95
101
|
it "renders link: correctly in JSON" do
|
96
|
-
assert_equal "{\"order\":{\"id\":1,\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"},{\"rel\":\"next\",\"href\":\"http://next/1\"}]}}", @c.from_attributes(
|
102
|
+
assert_equal "{\"order\":{\"id\":1,\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"},{\"rel\":\"next\",\"href\":\"http://next/1\"}]}}", @c.from_attributes(:id => 1).to_json
|
97
103
|
end
|
98
|
-
|
99
104
|
end
|
100
105
|
end
|
101
106
|
|
@@ -3,24 +3,27 @@ require 'roar/representer/feature/model_representing'
|
|
3
3
|
|
4
4
|
class ModelRepresentingTest < MiniTest::Spec
|
5
5
|
describe "ModelRepresenting" do
|
6
|
-
class ItemRepresenter
|
7
|
-
include Roar::Representer::
|
6
|
+
class ItemRepresenter
|
7
|
+
include Roar::Representer::XML
|
8
|
+
include Roar::Representer::Feature::ModelRepresenting
|
8
9
|
self.representation_name= :item
|
9
|
-
|
10
|
+
property :value
|
10
11
|
end
|
11
12
|
|
12
|
-
class PositionRepresenter
|
13
|
-
include Roar::Representer::
|
13
|
+
class PositionRepresenter
|
14
|
+
include Roar::Representer::XML
|
15
|
+
include Roar::Representer::Feature::ModelRepresenting
|
14
16
|
self.representation_name= :position
|
15
|
-
|
16
|
-
|
17
|
+
property :id
|
18
|
+
property :item, :as => ItemRepresenter
|
17
19
|
end
|
18
20
|
|
19
|
-
class OrderRepresenter
|
20
|
-
include Roar::Representer::
|
21
|
+
class OrderRepresenter
|
22
|
+
include Roar::Representer::XML
|
23
|
+
include Roar::Representer::Feature::ModelRepresenting
|
21
24
|
self.representation_name= :order
|
22
|
-
|
23
|
-
|
25
|
+
property :id
|
26
|
+
collection :items, :as => ItemRepresenter
|
24
27
|
end
|
25
28
|
|
26
29
|
describe "#definition_class" do
|
@@ -33,7 +36,6 @@ class ModelRepresentingTest < MiniTest::Spec
|
|
33
36
|
describe "#for_model" do
|
34
37
|
it "copies represented model attributes, nothing more" do
|
35
38
|
@o = Position.new("id" => 1, "item" => Item.new("value" => "Beer"))
|
36
|
-
|
37
39
|
@r = PositionRepresenter.for_model(@o)
|
38
40
|
assert_kind_of PositionRepresenter, @r
|
39
41
|
assert_equal 1, @r.id
|
@@ -43,23 +45,13 @@ class ModelRepresentingTest < MiniTest::Spec
|
|
43
45
|
assert_equal "Beer", @i.value
|
44
46
|
end
|
45
47
|
|
46
|
-
it "
|
48
|
+
it "references the model in @represented" do
|
47
49
|
@o = Position.new("id" => 1, "item" => @i = Item.new("value" => "Beer"))
|
48
50
|
|
49
51
|
@r = PositionRepresenter.for_model(@o)
|
50
52
|
assert_equal @o, @r.represented
|
51
53
|
assert_equal @i, @r.item.represented
|
52
54
|
end
|
53
|
-
|
54
|
-
|
55
|
-
it "works with Hyperlink attributes" do
|
56
|
-
@c = Class.new(ItemRepresenter) do
|
57
|
-
link :self do "http://self" end
|
58
|
-
end
|
59
|
-
|
60
|
-
assert_equal({"value"=>"Beer", "links"=>[{"rel"=>:self, "href"=>"http://self"}]}, @c.for_model(Item.new("value" => "Beer")).to_attributes)
|
61
|
-
end
|
62
|
-
|
63
55
|
end
|
64
56
|
|
65
57
|
describe "#serialize_model" do
|
@@ -93,6 +85,9 @@ class ModelRepresentingTest < MiniTest::Spec
|
|
93
85
|
OrderRepresenter.class_eval do
|
94
86
|
include Roar::Representer::Feature::ActiveRecordMethods
|
95
87
|
end
|
88
|
+
ItemRepresenter.class_eval do
|
89
|
+
include Roar::Representer::Feature::ActiveRecordMethods
|
90
|
+
end
|
96
91
|
assert_equal({"id" => 1, "items_attributes" => [{"value" => "Beer"}]}, @r.to_nested_attributes) # DISCUSS: overwrite #to_attributes.
|
97
92
|
end
|
98
93
|
|
@@ -103,11 +98,14 @@ class ModelRepresentingTest < MiniTest::Spec
|
|
103
98
|
|
104
99
|
OrderRepresenter.class_eval do
|
105
100
|
include Roar::Representer::Feature::ActiveRecordMethods
|
101
|
+
include Roar::Representer::Feature::Hypermedia
|
106
102
|
link :self do
|
107
103
|
# "bla"
|
108
104
|
end
|
109
105
|
end
|
110
106
|
ItemRepresenter.class_eval do
|
107
|
+
include Roar::Representer::Feature::ActiveRecordMethods
|
108
|
+
include Roar::Representer::Feature::Hypermedia
|
111
109
|
link :self do
|
112
110
|
|
113
111
|
end
|
data/test/order_representers.rb
CHANGED
@@ -4,7 +4,9 @@ require 'roar/representer/feature/hypermedia'
|
|
4
4
|
|
5
5
|
module JSON
|
6
6
|
|
7
|
-
class Item
|
7
|
+
class Item
|
8
|
+
include Roar::Representer::JSON
|
9
|
+
|
8
10
|
property :article_id
|
9
11
|
property :amount
|
10
12
|
|
@@ -13,7 +15,8 @@ module JSON
|
|
13
15
|
end
|
14
16
|
|
15
17
|
|
16
|
-
class Order
|
18
|
+
class Order
|
19
|
+
include Roar::Representer::JSON
|
17
20
|
property :client_id
|
18
21
|
collection :items, :as => Item
|
19
22
|
|