roar 0.10.0 → 0.10.1
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 -0
- data/Gemfile +6 -0
- data/README.textile +5 -4
- data/lib/roar/representer/feature/coercion.rb +20 -0
- data/lib/roar/representer/feature/http_verbs.rb +43 -21
- data/lib/roar/representer/feature/hypermedia.rb +6 -0
- data/lib/roar/representer/json/hal.rb +2 -1
- data/lib/roar/representer/transport/faraday.rb +56 -0
- data/lib/roar/representer/transport/net_http.rb +44 -0
- data/lib/roar/version.rb +1 -1
- data/roar.gemspec +4 -2
- data/test/coercion_feature_test.rb +18 -0
- data/test/fake_server.rb +41 -22
- data/test/faraday_http_transport_test.rb +69 -0
- data/test/hal_json_test.rb +7 -0
- data/test/http_verbs_feature_test.rb +52 -15
- data/test/hypermedia_feature_test.rb +87 -45
- data/test/{transport_test.rb → net_http_transport_test.rb} +6 -7
- data/test/representer_test.rb +0 -1
- data/test/test_helper.rb +9 -0
- metadata +44 -18
- data/lib/roar/representer/feature/transport.rb +0 -45
data/CHANGES.markdown
CHANGED
data/Gemfile
CHANGED
data/README.textile
CHANGED
@@ -134,7 +134,7 @@ module OrderRepresenter
|
|
134
134
|
property :id
|
135
135
|
property :client_id
|
136
136
|
|
137
|
-
collection :articles, :
|
137
|
+
collection :articles, :class => Article
|
138
138
|
|
139
139
|
link :self do
|
140
140
|
order_url(represented)
|
@@ -279,11 +279,11 @@ order.post(order.links[:self])
|
|
279
279
|
|
280
280
|
This was dead simple since representations can be composed of different documents in Roar.
|
281
281
|
|
282
|
+
h2. More Features
|
282
283
|
|
283
|
-
|
284
|
+
Be sure to check out the bundled features.
|
284
285
|
|
285
|
-
|
286
|
-
|
286
|
+
# *Coercion* transforms values to typed objects when parsing a document. Uses virtus.
|
287
287
|
|
288
288
|
h2. What is REST about?
|
289
289
|
|
@@ -296,3 +296,4 @@ Making that system RESTful basically means
|
|
296
296
|
h2. Support
|
297
297
|
|
298
298
|
Questions? Need help? Free 1st Level Support on irc.freenode.org#roar !
|
299
|
+
We also have a "mailing list":https://groups.google.com/forum/?fromgroups#!forum/roar-talk, yiha!
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'virtus'
|
2
|
+
require 'representable/coercion'
|
3
|
+
|
4
|
+
module Roar::Representer::Feature
|
5
|
+
# Use the +:type+ option to specify the conversion type.
|
6
|
+
# class ImmigrantSong
|
7
|
+
# include Roar::Representer::JSON
|
8
|
+
# include Roar::Representer::Feature::Coercion
|
9
|
+
#
|
10
|
+
# property :composed_at, :type => DateTime, :default => "May 12th, 2012"
|
11
|
+
# end
|
12
|
+
module Coercion
|
13
|
+
def self.included(base)
|
14
|
+
base.class_eval do
|
15
|
+
include Virtus
|
16
|
+
extend Representable::Coercion::ClassMethods
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,53 +1,75 @@
|
|
1
|
-
require 'roar/representer/
|
1
|
+
require 'roar/representer/transport/net_http'
|
2
|
+
require 'roar/representer/transport/faraday' # Do not require here
|
2
3
|
|
3
4
|
module Roar
|
4
5
|
# Gives HTTP-power to representers. They can serialize, send, process and deserialize HTTP-requests.
|
5
6
|
module Representer
|
6
7
|
module Feature
|
7
8
|
module HttpVerbs
|
8
|
-
|
9
|
-
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :transport_engine
|
12
|
+
|
13
|
+
def included(base)
|
14
|
+
base.extend ClassMethods
|
15
|
+
end
|
10
16
|
end
|
17
|
+
self.transport_engine = ::Roar::Representer::Transport::NetHTTP
|
11
18
|
|
12
|
-
|
19
|
+
|
13
20
|
module ClassMethods
|
14
|
-
# GETs +url+ with +format+ and returns deserialized
|
15
|
-
def get(
|
16
|
-
|
17
|
-
deserialize(document)
|
18
|
-
end
|
19
|
-
|
20
|
-
def http
|
21
|
-
Transport
|
21
|
+
# GETs +url+ with +format+ and returns deserialized represented object.
|
22
|
+
def get(*args)
|
23
|
+
new.get(*args)
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|
25
27
|
|
28
|
+
attr_writer :transport_engine
|
29
|
+
def transport_engine
|
30
|
+
@transport_engine || HttpVerbs.transport_engine
|
31
|
+
end
|
32
|
+
|
26
33
|
# Serializes the object, POSTs it to +url+ with +format+, deserializes the returned document
|
27
34
|
# and updates properties accordingly.
|
28
35
|
def post(url, format)
|
29
|
-
|
30
|
-
|
31
|
-
deserialize(document)
|
36
|
+
response = http.post_uri(url, serialize, format)
|
37
|
+
handle_response(response)
|
32
38
|
end
|
33
39
|
|
34
40
|
# GETs +url+ with +format+, deserializes the returned document and updates properties accordingly.
|
35
41
|
def get(url, format)
|
36
|
-
|
37
|
-
|
42
|
+
response = http.get_uri(url, format)
|
43
|
+
handle_response(response)
|
38
44
|
end
|
39
45
|
|
40
46
|
# Serializes the object, PUTs it to +url+ with +format+, deserializes the returned document
|
41
47
|
# and updates properties accordingly.
|
42
48
|
def put(url, format)
|
43
|
-
|
44
|
-
|
49
|
+
response = http.put_uri(url, serialize, format)
|
50
|
+
handle_response(response)
|
51
|
+
self
|
45
52
|
end
|
46
53
|
|
47
|
-
|
54
|
+
def patch(url, format)
|
55
|
+
response = http.patch_uri(url, serialize, format)
|
56
|
+
handle_response(response)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
def delete(url, format)
|
61
|
+
http.delete_uri(url, format)
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
48
65
|
private
|
66
|
+
def handle_response(response)
|
67
|
+
document = response.body
|
68
|
+
deserialize(document)
|
69
|
+
end
|
70
|
+
|
49
71
|
def http
|
50
|
-
|
72
|
+
transport_engine.new
|
51
73
|
end
|
52
74
|
end
|
53
75
|
end
|
@@ -108,9 +108,15 @@ module Roar
|
|
108
108
|
|
109
109
|
class LinksDefinition < Representable::Definition
|
110
110
|
# TODO: hide rel2block in interface.
|
111
|
+
attr_writer :rel2block
|
112
|
+
|
111
113
|
def rel2block
|
112
114
|
@rel2block ||= []
|
113
115
|
end
|
116
|
+
|
117
|
+
def clone
|
118
|
+
super.tap { |d| d.rel2block = rel2block.clone }
|
119
|
+
end
|
114
120
|
end
|
115
121
|
|
116
122
|
|
@@ -42,7 +42,7 @@ module Roar::Representer
|
|
42
42
|
|
43
43
|
def uncompile_fragment(bin, doc)
|
44
44
|
return super unless bin.definition.options[:embedded]
|
45
|
-
super(bin, doc["_embedded"])
|
45
|
+
super(bin, doc["_embedded"] || {})
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
@@ -90,6 +90,7 @@ module Roar::Representer
|
|
90
90
|
end
|
91
91
|
|
92
92
|
def from_hash(json, *)
|
93
|
+
json ||= {} # since we override #from_hash we're responsible for this.
|
93
94
|
json.each do |k, v|
|
94
95
|
self << Feature::Hypermedia::Hyperlink.new(v.merge :rel => k)
|
95
96
|
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
begin
|
2
|
+
require 'faraday'
|
3
|
+
rescue LoadError
|
4
|
+
puts 'You must add faraday as a dependency to use the FaradayTransport'
|
5
|
+
end
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
module Roar
|
9
|
+
module Representer
|
10
|
+
module Transport
|
11
|
+
# Advanced implementation of the HTTP verbs with the Faraday HTTP library
|
12
|
+
# (which can, in turn, use adapters based on Net::HTTP or libcurl)
|
13
|
+
#
|
14
|
+
# Depending on how the Faraday middleware stack is configured, this
|
15
|
+
# Transport can support features such as HTTP error code handling,
|
16
|
+
# redirects, etc.
|
17
|
+
#
|
18
|
+
# @see http://rubydoc.info/gems/faraday/file/README.md Faraday README
|
19
|
+
class Faraday
|
20
|
+
|
21
|
+
def get_uri(uri, as)
|
22
|
+
build_connection(uri, as).get
|
23
|
+
end
|
24
|
+
|
25
|
+
def post_uri(uri, body, as)
|
26
|
+
build_connection(uri, as).post
|
27
|
+
end
|
28
|
+
|
29
|
+
def put_uri(uri, body, as)
|
30
|
+
build_connection(uri, as).put
|
31
|
+
end
|
32
|
+
|
33
|
+
def patch_uri(uri, body, as)
|
34
|
+
build_connection(uri, as).patch
|
35
|
+
end
|
36
|
+
|
37
|
+
def delete_uri(uri, as)
|
38
|
+
build_connection(uri, as).delete
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def build_connection(uri, as)
|
44
|
+
::Faraday::Connection.new(
|
45
|
+
:url => uri,
|
46
|
+
:headers => { :accept => as }
|
47
|
+
) do |builder|
|
48
|
+
# builder.use Faraday::Response::Logger, Logger.new('faraday.log')
|
49
|
+
builder.use ::Faraday::Response::RaiseError
|
50
|
+
builder.adapter ::Faraday.default_adapter
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "uri"
|
3
|
+
|
4
|
+
module Roar
|
5
|
+
module Representer
|
6
|
+
# Implements the (HTTP) transport interface with Net::HTTP.
|
7
|
+
module Transport
|
8
|
+
# Definitions: every call returns a Response object responding to #body.
|
9
|
+
class NetHTTP
|
10
|
+
# TODO: generically handle return codes.
|
11
|
+
def get_uri(uri, as)
|
12
|
+
do_request(Net::HTTP::Get, uri, as)
|
13
|
+
end
|
14
|
+
|
15
|
+
def post_uri(uri, body, as)
|
16
|
+
do_request(Net::HTTP::Post, uri, as)
|
17
|
+
end
|
18
|
+
|
19
|
+
def put_uri(uri, body, as)
|
20
|
+
do_request(Net::HTTP::Put, uri, as)
|
21
|
+
end
|
22
|
+
|
23
|
+
def patch_uri(uri, body, as)
|
24
|
+
do_request(Net::HTTP::Patch, uri, as)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete_uri(uri, as)
|
28
|
+
do_request(Net::HTTP::Delete, uri, as)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def do_request(what, uri, as, body="")
|
33
|
+
# DISCUSS: can this be made easier?
|
34
|
+
uri = URI.parse(uri)
|
35
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
+
req = what.new(uri.request_uri)
|
37
|
+
req.content_type = as
|
38
|
+
req.body = body if body
|
39
|
+
http.request(req)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/roar/version.rb
CHANGED
data/roar.gemspec
CHANGED
@@ -19,11 +19,13 @@ 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", ">= 1.1.
|
22
|
+
s.add_runtime_dependency "representable", ">= 1.1.7"
|
23
23
|
|
24
24
|
s.add_development_dependency "rake"
|
25
25
|
s.add_development_dependency "test_xml"
|
26
26
|
s.add_development_dependency "minitest", ">= 2.8.1"
|
27
|
-
s.add_development_dependency "sinatra", "~> 1.2
|
27
|
+
s.add_development_dependency "sinatra", "~> 1.3.2"
|
28
28
|
s.add_development_dependency "sham_rack", "~> 1.3.0"
|
29
|
+
s.add_development_dependency "turn"
|
30
|
+
s.add_development_dependency "virtus"
|
29
31
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/representer/feature/coercion'
|
3
|
+
|
4
|
+
class CoercionFeatureTest < MiniTest::Spec
|
5
|
+
describe "Coercion" do
|
6
|
+
class ImmigrantSong
|
7
|
+
include Roar::Representer::JSON
|
8
|
+
include Roar::Representer::Feature::Coercion
|
9
|
+
|
10
|
+
property :composed_at, :type => DateTime, :default => "May 12th, 2012"
|
11
|
+
end
|
12
|
+
|
13
|
+
it "coerces into the provided type" do
|
14
|
+
song = ImmigrantSong.new.from_json("{\"composed_at\":\"November 18th, 1983\"}")
|
15
|
+
assert_equal DateTime.parse("Fri, 18 Nov 1983 00:00:00 +0000"), song.composed_at
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/test/fake_server.rb
CHANGED
@@ -1,41 +1,60 @@
|
|
1
1
|
require "bundler/setup"
|
2
2
|
require 'sinatra/base'
|
3
|
-
|
4
|
-
class FakeServer < Sinatra::Base
|
5
|
-
|
6
|
-
|
3
|
+
|
4
|
+
class FakeServer < Sinatra::Base
|
5
|
+
|
6
|
+
set :raise_errors, false
|
7
|
+
|
8
|
+
get "/method" do
|
9
|
+
"<method>get</method>"
|
7
10
|
end
|
8
|
-
|
9
|
-
post "/method" do
|
10
|
-
"<method>post</method>"
|
11
|
+
|
12
|
+
post "/method" do
|
13
|
+
"<method>post</method>"
|
11
14
|
end
|
12
15
|
|
13
|
-
put "/method" do
|
14
|
-
"<method>put</method>"
|
16
|
+
put "/method" do
|
17
|
+
"<method>put</method>"
|
15
18
|
end
|
16
19
|
|
17
|
-
delete "/method" do
|
18
|
-
"<method>delete</method>"
|
20
|
+
delete "/method" do
|
21
|
+
"<method>delete</method>"
|
19
22
|
end
|
20
23
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
24
|
+
patch "/method" do
|
25
|
+
"<method>patch</method>"
|
26
|
+
end
|
27
|
+
|
28
|
+
get '/deliberate-error' do
|
29
|
+
raise 'this error was deliberate'
|
30
|
+
end
|
31
|
+
|
25
32
|
post "/bands" do
|
26
33
|
#if request.content_type =~ /xml/
|
27
|
-
|
34
|
+
body '{"label": "n/a", "name": "Strung Out", "links": [{"href":"http://search", "rel": "search"}, {"href":"http://band/strungout", "rel": "self"}]}'
|
35
|
+
status 201
|
28
36
|
end
|
29
37
|
|
30
38
|
put "/bands/strungout" do
|
39
|
+
# DISCUSS: as long as we don't agree on what to return in PUT/PATCH, let's return an updated document.
|
31
40
|
{:name => "Strung Out", :label => "Fat Wreck"}.to_json
|
41
|
+
#status 204
|
32
42
|
end
|
33
|
-
|
43
|
+
|
44
|
+
patch '/bands/strungout' do
|
45
|
+
# DISCUSS: as long as we don't agree on what to return in PUT/PATCH, let's return an updated document.
|
46
|
+
{:name => 'Strung Out', :label => 'Fat Mike'}.to_json
|
47
|
+
#status 204
|
48
|
+
end
|
49
|
+
|
34
50
|
get "/bands/slayer" do
|
35
51
|
{:name => "Slayer", :label => "Canadian Maple"}.to_json
|
36
52
|
end
|
37
|
-
|
38
|
-
|
53
|
+
|
54
|
+
delete '/banks/metallica' do
|
55
|
+
status 204
|
56
|
+
end
|
57
|
+
|
39
58
|
require './test/order_representers'
|
40
59
|
JSON::Order.class_eval do
|
41
60
|
def items_url
|
@@ -69,6 +88,6 @@ class FakeServer < Sinatra::Base
|
|
69
88
|
get "/orders/1" do
|
70
89
|
JSON::Order.new(:client_id => 1, :items => [JSON::Item.new(:article_id => "666-S", :amount => 1)]).serialize
|
71
90
|
end
|
72
|
-
|
73
|
-
end
|
74
|
-
|
91
|
+
|
92
|
+
end
|
93
|
+
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'roar/representer/transport/faraday'
|
3
|
+
|
4
|
+
class FaradayHttpTransportTest < MiniTest::Spec
|
5
|
+
describe 'FaradayHttpTransport' do
|
6
|
+
before do
|
7
|
+
@transport = Roar::Representer::Transport::Faraday.new
|
8
|
+
end
|
9
|
+
|
10
|
+
it "#get_uri returns response" do
|
11
|
+
assert_equal "<method>get</method>", @transport.get_uri("http://roar.example.com/method", "application/xml").body
|
12
|
+
end
|
13
|
+
|
14
|
+
it "#post_uri returns response" do
|
15
|
+
assert_equal "<method>post</method>", @transport.post_uri("http://roar.example.com/method", "booty", "application/xml").body
|
16
|
+
end
|
17
|
+
|
18
|
+
it "#put_uri returns response" do
|
19
|
+
assert_equal "<method>put</method>", @transport.put_uri("http://roar.example.com/method", "booty", "application/xml").body
|
20
|
+
end
|
21
|
+
|
22
|
+
it "#delete_uri returns response" do
|
23
|
+
assert_equal "<method>delete</method>", @transport.delete_uri("http://roar.example.com/method", "application/xml").body
|
24
|
+
end
|
25
|
+
|
26
|
+
it "#patch_uri returns response" do
|
27
|
+
assert_equal "<method>patch</method>", @transport.patch_uri("http://roar.example.com/method", "booty", "application/xml").body
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'non-existent resource' do
|
31
|
+
before do
|
32
|
+
@not_found_url = 'http://roar.example.com/missing-resource'
|
33
|
+
end
|
34
|
+
|
35
|
+
it '#get_uri raises a ResourceNotFound error' do
|
36
|
+
assert_raises(Faraday::Error::ResourceNotFound) do
|
37
|
+
@transport.get_uri(@not_found_url, "application/xml").body
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
it '#post_uri raises a ResourceNotFound error' do
|
42
|
+
assert_raises(Faraday::Error::ResourceNotFound) do
|
43
|
+
@transport.post_uri(@not_found_url, 'crisis', "application/xml").body
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it '#post_uri raises a ResourceNotFound error' do
|
48
|
+
assert_raises(Faraday::Error::ResourceNotFound) do
|
49
|
+
@transport.post_uri(@not_found_url, 'crisis', "application/xml").body
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
it '#delete_uri raises a ResourceNotFound error' do
|
54
|
+
assert_raises(Faraday::Error::ResourceNotFound) do
|
55
|
+
@transport.delete_uri(@not_found_url, "application/xml").body
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe 'server errors (500 Internal Server Error)' do
|
61
|
+
it '#get_uri raises a ClientError' do
|
62
|
+
assert_raises(Faraday::Error::ClientError) do
|
63
|
+
@transport.get_uri('http://roar.example.com/deliberate-error', "application/xml").body
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
end
|
data/test/hal_json_test.rb
CHANGED
@@ -65,5 +65,12 @@ class HalJsonTest < MiniTest::Spec
|
|
65
65
|
assert_equal "http://items/Coffee", @order.items.first.links[:self].href
|
66
66
|
assert_equal "http://orders/2", @order.links[:self].href
|
67
67
|
end
|
68
|
+
|
69
|
+
it "doesn't require _links and _embedded to be present" do
|
70
|
+
@order.from_json("{\"id\":2}")
|
71
|
+
assert_equal 2, @order.id
|
72
|
+
assert_equal [], @order.items
|
73
|
+
assert_equal [], @order.links
|
74
|
+
end
|
68
75
|
end
|
69
76
|
end
|
@@ -23,21 +23,49 @@ class HttpVerbsTest < MiniTest::Spec
|
|
23
23
|
@band.extend(Roar::Representer::Feature::HttpVerbs)
|
24
24
|
end
|
25
25
|
|
26
|
+
describe "transport_engine" do
|
27
|
+
before do
|
28
|
+
@http_verbs = Roar::Representer::Feature::HttpVerbs
|
29
|
+
@net_http = Roar::Representer::Transport::NetHTTP
|
30
|
+
end
|
31
|
+
|
32
|
+
it "has a default set in the transport module level" do
|
33
|
+
assert_equal @net_http, @band.transport_engine
|
34
|
+
end
|
35
|
+
|
36
|
+
it "allows changing on instance level" do
|
37
|
+
@band.transport_engine = :soap
|
38
|
+
assert_equal @net_http, @http_verbs.transport_engine
|
39
|
+
assert_equal :soap, @band.transport_engine
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
|
26
44
|
describe "HttpVerbs.get" do
|
27
45
|
it "returns instance from incoming representation" do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
46
|
+
band = @band.get("http://roar.example.com/bands/slayer", "application/json")
|
47
|
+
assert_equal "Slayer", band.name
|
48
|
+
assert_equal "Canadian Maple", band.label
|
49
|
+
end
|
50
|
+
|
51
|
+
# FIXME: move to faraday test.
|
52
|
+
describe 'a non-existent resource' do
|
53
|
+
it 'handles HTTP errors and raises a ResourceNotFound error with FaradayHttpTransport' do
|
54
|
+
@band.transport_engine = Roar::Representer::Transport::Faraday
|
55
|
+
assert_raises(::Faraday::Error::ResourceNotFound) do
|
56
|
+
@band.get('http://roar.example.com/bands/anthrax', "application/json")
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'performs no HTTP error handling with NetHttpTransport' do
|
61
|
+
@band.transport_engine = Roar::Representer::Transport::NetHTTP
|
62
|
+
assert_raises(JSON::ParserError) do
|
63
|
+
@band.get('http://roar.example.com/bands/anthrax', "application/json")
|
64
|
+
end
|
34
65
|
end
|
35
|
-
@band = @Band.get("http://roar.example.com/bands/slayer", "application/json")
|
36
|
-
assert_equal "Slayer", @band.name
|
37
|
-
assert_equal "Canadian Maple", @band.label
|
38
66
|
end
|
39
67
|
end
|
40
|
-
|
68
|
+
|
41
69
|
describe "#get" do
|
42
70
|
it "updates instance with incoming representation" do
|
43
71
|
@band.get("http://roar.example.com/bands/slayer", "application/json")
|
@@ -67,12 +95,21 @@ class HttpVerbsTest < MiniTest::Spec
|
|
67
95
|
end
|
68
96
|
end
|
69
97
|
|
70
|
-
describe "#delete" do
|
71
|
-
|
72
|
-
end
|
73
|
-
|
74
98
|
describe "#patch" do
|
75
|
-
|
99
|
+
it 'does something' do
|
100
|
+
@band.label = 'Fat Mike'
|
101
|
+
@band.patch("http://roar.example.com/bands/strungout", "application/xml")
|
102
|
+
assert_equal 'Fat Mike', @band.label
|
103
|
+
end
|
76
104
|
end
|
105
|
+
|
106
|
+
describe "#delete" do
|
107
|
+
it 'does something' do
|
108
|
+
@band.delete("http://roar.example.com/bands/metallica", "application/xml")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# HEAD, OPTIONs?
|
113
|
+
|
77
114
|
end
|
78
115
|
end
|
@@ -11,51 +11,51 @@ class HypermediaTest
|
|
11
11
|
include Roar::Representer::Feature::Hypermedia
|
12
12
|
end
|
13
13
|
end
|
14
|
-
|
14
|
+
|
15
15
|
it "accepts rel symbol, only" do
|
16
16
|
@mod.class_eval do
|
17
17
|
link :self do
|
18
18
|
"http://self"
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
21
|
+
|
22
22
|
assert_equal "{\"links\":[{\"rel\":\"self\",\"href\":\"http://self\"}]}", Object.new.extend(@mod).to_json
|
23
23
|
end
|
24
|
-
|
24
|
+
|
25
25
|
it "accepts any options" do
|
26
26
|
@mod.class_eval do
|
27
27
|
link :rel => :self, :title => "Hey, @myabc" do
|
28
28
|
"http://self"
|
29
29
|
end
|
30
30
|
end
|
31
|
-
|
31
|
+
|
32
32
|
assert_equal "{\"links\":[{\"rel\":\"self\",\"href\":\"http://self\",\"title\":\"Hey, @myabc\"}]}", Object.new.extend(@mod).to_json
|
33
33
|
end
|
34
34
|
end
|
35
|
-
|
36
|
-
|
35
|
+
|
36
|
+
|
37
37
|
before do
|
38
38
|
@bookmarks = Class.new do
|
39
39
|
include AttributesContructor
|
40
40
|
include Roar::Representer::XML
|
41
41
|
include Roar::Representer::Feature::Hypermedia
|
42
|
-
|
42
|
+
|
43
43
|
self.representation_wrap = "bookmarks"
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
@bookmarks_with_links = Class.new(@bookmarks)
|
47
47
|
@bookmarks_with_links.class_eval do
|
48
48
|
self.representation_wrap = "bookmarks"
|
49
|
-
|
49
|
+
|
50
50
|
property :id
|
51
51
|
link :self do "http://bookmarks" end
|
52
52
|
link :all do "http://bookmarks/all" end
|
53
|
-
|
53
|
+
|
54
54
|
attr_accessor :id, :self, :all
|
55
55
|
end
|
56
56
|
end
|
57
|
-
|
58
|
-
|
57
|
+
|
58
|
+
|
59
59
|
describe "#to_xml" do
|
60
60
|
it "sets up links and renders <link> correctly in XML" do
|
61
61
|
assert_xml_equal '<bookmarks>
|
@@ -64,31 +64,31 @@ class HypermediaTest
|
|
64
64
|
<link rel="all" href="http://bookmarks/all"/>
|
65
65
|
</bookmarks>', @bookmarks_with_links.new(:id => 1).to_xml
|
66
66
|
end
|
67
|
-
|
67
|
+
|
68
68
|
it "still works even if there are no links defined" do
|
69
69
|
assert_xml_equal '<bookmarks/>', @bookmarks.new.to_xml
|
70
70
|
end
|
71
|
-
|
71
|
+
|
72
72
|
it "doesn't render links with :links => false" do
|
73
73
|
assert_xml_equal '<bookmarks>
|
74
74
|
<id>1</id>
|
75
|
-
</bookmarks>',
|
75
|
+
</bookmarks>',
|
76
76
|
@bookmarks_with_links.new(:id => 1).to_xml(:links => false)
|
77
77
|
end
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
describe "#to_json" do
|
81
81
|
class Note
|
82
82
|
include Roar::Representer::JSON
|
83
83
|
include Roar::Representer::Feature::Hypermedia
|
84
84
|
link(:self) { "http://me" }
|
85
85
|
end
|
86
|
-
|
86
|
+
|
87
87
|
it "works twice" do
|
88
88
|
note = Note.new
|
89
89
|
assert_equal note.to_json, note.to_json
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
it "sets up links even when nested" do
|
93
93
|
class Page
|
94
94
|
include AttributesContructor
|
@@ -96,13 +96,13 @@ class HypermediaTest
|
|
96
96
|
property :note, :class => Note
|
97
97
|
attr_accessor :note
|
98
98
|
end
|
99
|
-
|
99
|
+
|
100
100
|
assert_equal "{\"note\":{\"links\":[{\"rel\":\"self\",\"href\":\"http://me\"}]}}", Page.new(:note => Note.new).to_json
|
101
101
|
end
|
102
102
|
end
|
103
|
-
|
104
|
-
|
105
|
-
|
103
|
+
|
104
|
+
|
105
|
+
|
106
106
|
describe "#from_xml" do
|
107
107
|
it "extracts links from document" do
|
108
108
|
doc = @bookmarks_with_links.from_xml(%{
|
@@ -110,25 +110,25 @@ class HypermediaTest
|
|
110
110
|
<link rel="self" href="http://bookmarks">
|
111
111
|
</bookmarks>
|
112
112
|
})
|
113
|
-
|
113
|
+
|
114
114
|
assert_kind_of Roar::Representer::Feature::Hypermedia::LinkCollection, doc.links
|
115
115
|
assert_equal 1, doc.links.size
|
116
|
-
assert_equal(["self", "http://bookmarks"], [doc.links.first.rel, doc.links.first.href])
|
116
|
+
assert_equal(["self", "http://bookmarks"], [doc.links.first.rel, doc.links.first.href])
|
117
117
|
end
|
118
|
-
|
118
|
+
|
119
119
|
it "sets up an empty link list if no links found in the document" do
|
120
120
|
assert_equal [], @bookmarks_with_links.from_xml(%{<bookmarks/>}).links
|
121
121
|
end
|
122
122
|
end
|
123
|
-
|
124
|
-
|
123
|
+
|
124
|
+
|
125
125
|
describe "#links" do
|
126
126
|
before do
|
127
127
|
@set = @bookmarks.new
|
128
128
|
hyper = Roar::Representer::Feature::Hypermedia::Hyperlink
|
129
|
-
|
129
|
+
|
130
130
|
@set.links = [
|
131
|
-
{:rel => "self", :href => "http://self"},
|
131
|
+
{:rel => "self", :href => "http://self"},
|
132
132
|
{:rel => "next", :href => "http://next"}].collect do |config|
|
133
133
|
link = hyper.new
|
134
134
|
link.rel = config[:rel]
|
@@ -136,14 +136,14 @@ class HypermediaTest
|
|
136
136
|
link
|
137
137
|
end
|
138
138
|
end
|
139
|
-
|
139
|
+
|
140
140
|
describe "#links=" do
|
141
141
|
it "wraps links in a LinkCollection" do
|
142
142
|
assert_kind_of Roar::Representer::Feature::Hypermedia::LinkCollection, @set.links
|
143
143
|
assert_equal 2, @set.links.size
|
144
144
|
end
|
145
145
|
end
|
146
|
-
|
146
|
+
|
147
147
|
describe "#link[]" do
|
148
148
|
it "returns link object" do
|
149
149
|
assert_equal "http://self", @set.links["self"].href
|
@@ -152,23 +152,23 @@ class HypermediaTest
|
|
152
152
|
assert_equal nil, @set.links[:prev]
|
153
153
|
end
|
154
154
|
end
|
155
|
-
|
155
|
+
|
156
156
|
it "returns an empty list when no links present" do
|
157
157
|
assert_equal Roar::Representer::Feature::Hypermedia::LinkCollection.new, @bookmarks.new.links
|
158
158
|
end
|
159
159
|
end
|
160
|
-
|
161
|
-
|
160
|
+
|
161
|
+
|
162
162
|
describe "#find_links_definition" do
|
163
163
|
it "returns Definition if links are present" do
|
164
164
|
@bookmarks.class_eval do
|
165
165
|
property :id
|
166
166
|
link :self
|
167
167
|
end
|
168
|
-
|
168
|
+
|
169
169
|
assert_equal "links", @bookmarks.find_links_definition.name
|
170
170
|
end
|
171
|
-
|
171
|
+
|
172
172
|
it "returns nil if no links defined" do
|
173
173
|
assert_equal nil, @bookmarks.find_links_definition
|
174
174
|
end
|
@@ -181,19 +181,25 @@ class LinksDefinitionTest < MiniTest::Spec
|
|
181
181
|
before do
|
182
182
|
@d = Roar::Representer::Feature::Hypermedia::LinksDefinition.new(:links)
|
183
183
|
end
|
184
|
-
|
184
|
+
|
185
185
|
it "accepts options in constructor" do
|
186
186
|
assert_equal [], @d.rel2block
|
187
187
|
end
|
188
|
-
|
188
|
+
|
189
189
|
it "accepts configuration" do
|
190
190
|
@d.rel2block << {:rel => :self}
|
191
191
|
assert_equal [{:rel=>:self}], @d.rel2block
|
192
192
|
end
|
193
193
|
|
194
|
-
it "responds to #
|
194
|
+
it "responds to #clone" do
|
195
|
+
@d.rel2block << {:rel => :self}
|
196
|
+
assert @d.clone.rel2block.object_id != @d.rel2block.object_id
|
195
197
|
end
|
196
198
|
|
199
|
+
|
200
|
+
it "responds to #each to iterate rel2block" do
|
201
|
+
end
|
202
|
+
|
197
203
|
end
|
198
204
|
end
|
199
205
|
|
@@ -204,10 +210,10 @@ class LinkCollectionTest < MiniTest::Spec
|
|
204
210
|
link = Roar::Representer::Feature::Hypermedia::Hyperlink.new
|
205
211
|
link.rel = "self"
|
206
212
|
link.href = "http://self"
|
207
|
-
|
213
|
+
|
208
214
|
collection.update_link(link)
|
209
215
|
assert_equal 1, collection.size
|
210
|
-
|
216
|
+
|
211
217
|
collection.update_link(link)
|
212
218
|
assert_equal 1, collection.size
|
213
219
|
end
|
@@ -220,21 +226,57 @@ class HyperlinkTest < MiniTest::Spec
|
|
220
226
|
before do
|
221
227
|
@link = Hyperlink.new(:rel => "self", :href => "http://self")
|
222
228
|
end
|
223
|
-
|
229
|
+
|
224
230
|
it "accepts string keys in constructor" do
|
225
231
|
assert_equal "Hey, @myabc", Hyperlink.new("title" => "Hey, @myabc").title
|
226
232
|
end
|
227
|
-
|
233
|
+
|
228
234
|
it "responds to #media" do
|
229
235
|
assert_equal nil, @link.media
|
230
236
|
end
|
231
|
-
|
237
|
+
|
232
238
|
it "responds to #rel" do
|
233
239
|
assert_equal "self", @link.rel
|
234
240
|
end
|
235
|
-
|
241
|
+
|
236
242
|
it "responds to #href" do
|
237
243
|
assert_equal "http://self", @link.href
|
238
244
|
end
|
239
245
|
end
|
240
246
|
end
|
247
|
+
|
248
|
+
class HyperlinkInheritanceTest < MiniTest::Spec
|
249
|
+
describe "when the base representer has a link" do
|
250
|
+
before do
|
251
|
+
module BaseRepresenter
|
252
|
+
include Roar::Representer::JSON
|
253
|
+
include Roar::Representer::Feature::Hypermedia
|
254
|
+
|
255
|
+
link(:base) { "http://base" }
|
256
|
+
end
|
257
|
+
|
258
|
+
module Foo
|
259
|
+
include Roar::Representer::JSON
|
260
|
+
include Roar::Representer::Feature::Hypermedia
|
261
|
+
include BaseRepresenter
|
262
|
+
|
263
|
+
link(:foo) { "http://foo" }
|
264
|
+
end
|
265
|
+
|
266
|
+
module Bar
|
267
|
+
include Roar::Representer::JSON
|
268
|
+
include Roar::Representer::Feature::Hypermedia
|
269
|
+
include BaseRepresenter
|
270
|
+
|
271
|
+
link(:bar) { "http://bar" }
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
it "should inherit parent links" do
|
276
|
+
foo = Object.new.extend(Foo)
|
277
|
+
|
278
|
+
assert_equal "{\"links\":[{\"rel\":\"base\",\"href\":\"http://base\"},{\"rel\":\"foo\",\"href\":\"http://foo\"}]}", foo.to_json
|
279
|
+
end
|
280
|
+
|
281
|
+
end
|
282
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
require 'test_helper'
|
2
|
-
require 'roar/representer/
|
2
|
+
require 'roar/representer/transport/net_http'
|
3
3
|
|
4
|
-
class
|
4
|
+
class NetHTTPTransportTest < MiniTest::Spec
|
5
5
|
describe "Transport" do
|
6
6
|
before do
|
7
|
-
@transport = Roar::Representer::
|
7
|
+
@transport = Roar::Representer::Transport::NetHTTP.new
|
8
8
|
end
|
9
9
|
|
10
10
|
it "#get_uri returns response" do
|
@@ -23,9 +23,8 @@ class TransportTest < MiniTest::Spec
|
|
23
23
|
assert_equal "<method>delete</method>", @transport.delete_uri("http://roar.example.com/method", "application/xml").body
|
24
24
|
end
|
25
25
|
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
#end
|
26
|
+
it "#patch_uri returns response" do
|
27
|
+
assert_equal "<method>patch</method>", @transport.patch_uri("http://roar.example.com/method", "booty", "application/xml").body
|
28
|
+
end
|
30
29
|
end
|
31
30
|
end
|
data/test/representer_test.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -7,6 +7,15 @@ require 'minitest/spec'
|
|
7
7
|
require 'roar/representer'
|
8
8
|
require 'roar/representer/feature/http_verbs'
|
9
9
|
|
10
|
+
begin
|
11
|
+
require 'turn'
|
12
|
+
|
13
|
+
Turn.config do |config|
|
14
|
+
config.format = :dotted
|
15
|
+
# config.trace = true
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
end
|
10
19
|
|
11
20
|
module AttributesContructor
|
12
21
|
def initialize(attrs={})
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roar
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.10.
|
4
|
+
version: 0.10.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,22 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: representable
|
16
|
-
requirement: &
|
16
|
+
requirement: &75807040 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
|
-
version: 1.1.
|
21
|
+
version: 1.1.7
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *75807040
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &75805090 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *75805090
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: test_xml
|
38
|
-
requirement: &
|
38
|
+
requirement: &75802000 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :development
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *75802000
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: minitest
|
49
|
-
requirement: &
|
49
|
+
requirement: &75801380 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,21 +54,21 @@ dependencies:
|
|
54
54
|
version: 2.8.1
|
55
55
|
type: :development
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *75801380
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: sinatra
|
60
|
-
requirement: &
|
60
|
+
requirement: &75799950 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ~>
|
64
64
|
- !ruby/object:Gem::Version
|
65
|
-
version: 1.2
|
65
|
+
version: 1.3.2
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *75799950
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: sham_rack
|
71
|
-
requirement: &
|
71
|
+
requirement: &75799310 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,7 +76,29 @@ dependencies:
|
|
76
76
|
version: 1.3.0
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *75799310
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: turn
|
82
|
+
requirement: &75798790 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *75798790
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: virtus
|
93
|
+
requirement: &75797000 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *75797000
|
80
102
|
description: Streamlines the development of RESTful, resource-oriented architectures
|
81
103
|
in Ruby.
|
82
104
|
email:
|
@@ -96,16 +118,19 @@ files:
|
|
96
118
|
- lib/roar/rails.rb
|
97
119
|
- lib/roar/representer.rb
|
98
120
|
- lib/roar/representer/feature/client.rb
|
121
|
+
- lib/roar/representer/feature/coercion.rb
|
99
122
|
- lib/roar/representer/feature/http_verbs.rb
|
100
123
|
- lib/roar/representer/feature/hypermedia.rb
|
101
|
-
- lib/roar/representer/feature/transport.rb
|
102
124
|
- lib/roar/representer/json.rb
|
103
125
|
- lib/roar/representer/json/hal.rb
|
126
|
+
- lib/roar/representer/transport/faraday.rb
|
127
|
+
- lib/roar/representer/transport/net_http.rb
|
104
128
|
- lib/roar/representer/xml.rb
|
105
129
|
- lib/roar/version.rb
|
106
130
|
- roar.gemspec
|
107
131
|
- test/Gemfile
|
108
132
|
- test/client_test.rb
|
133
|
+
- test/coercion_feature_test.rb
|
109
134
|
- test/dummy/Rakefile
|
110
135
|
- test/dummy/app/controllers/albums_controller.rb
|
111
136
|
- test/dummy/app/controllers/application_controller.rb
|
@@ -142,17 +167,18 @@ files:
|
|
142
167
|
- test/dummy/tmp/app/cells/blog/post/latest.html.erb
|
143
168
|
- test/dummy/tmp/app/cells/blog/post_cell.rb
|
144
169
|
- test/fake_server.rb
|
170
|
+
- test/faraday_http_transport_test.rb
|
145
171
|
- test/hal_json_test.rb
|
146
172
|
- test/http_verbs_feature_test.rb
|
147
173
|
- test/hypermedia_feature_test.rb
|
148
174
|
- test/integration_test.rb
|
149
175
|
- test/json_representer_test.rb
|
176
|
+
- test/net_http_transport_test.rb
|
150
177
|
- test/order_representers.rb
|
151
178
|
- test/rails/controller_methods_test.rb
|
152
179
|
- test/rails/rails_representer_methods_test.rb
|
153
180
|
- test/representer_test.rb
|
154
181
|
- test/test_helper.rb
|
155
|
-
- test/transport_test.rb
|
156
182
|
- test/xml_representer_test.rb
|
157
183
|
homepage: http://rubygems.org/gems/roar
|
158
184
|
licenses: []
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require "net/http"
|
2
|
-
require "uri"
|
3
|
-
|
4
|
-
module Roar
|
5
|
-
module Representer
|
6
|
-
module Feature
|
7
|
-
# Implements the HTTP verbs with Net::HTTP.
|
8
|
-
module Transport
|
9
|
-
class << self
|
10
|
-
# TODO: generically handle return codes/let Restfulie do it.
|
11
|
-
def get_uri(uri, as)
|
12
|
-
do_request(Net::HTTP::Get, uri, as)
|
13
|
-
end
|
14
|
-
|
15
|
-
def post_uri(uri, body, as)
|
16
|
-
do_request(Net::HTTP::Post, uri, as)
|
17
|
-
end
|
18
|
-
|
19
|
-
def put_uri(uri, body, as)
|
20
|
-
do_request(Net::HTTP::Put, uri, as)
|
21
|
-
end
|
22
|
-
|
23
|
-
def patch_uri(uri, body, as)
|
24
|
-
do_request(Net::HTTP::Patch, uri, as)
|
25
|
-
end
|
26
|
-
|
27
|
-
def delete_uri(uri, as)
|
28
|
-
do_request(Net::HTTP::Delete, uri, as)
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
def do_request(what, uri, as, body="")
|
33
|
-
# DISCUSS: can this be made easier?
|
34
|
-
uri = URI.parse(uri)
|
35
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
36
|
-
req = what.new(uri.request_uri)
|
37
|
-
req.content_type = as
|
38
|
-
req.body = body if body
|
39
|
-
http.request(req)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|