restful_mapper 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 77221199e858bff0473e341caeb476fab4a9f20f
4
+ data.tar.gz: 012a9f9893e7fed2f917715ee605f08e7e3f5840
5
+ SHA512:
6
+ metadata.gz: 4c351450ae1850ba7a5c87aa7c0cc4b3af691dc6756aa62ae1ef0276fd14b9cf7b28de5486130f54b395d581c8aa28f8c1e7bf4b6ec9b50e0bcb83c05ce866d6
7
+ data.tar.gz: 4cb445bb1cd7f9c60b9cfb5131a8ae9f50d083a5e38290351721403c0bebefa852b6c3572d9e0cc225bcd1cb7e9a3de98313528fa46c31e0ba6ea81561216fd7
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in restful_mapper.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Dragan Milic
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,121 @@
1
+ # RestfulMapper
2
+
3
+ Provides DSL for describing RESTFul services using JSON transport.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'restful_mapper'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install restful_mapper
18
+
19
+ ## Usage
20
+
21
+ RestfulMapper provides a way to integrate calls to RESTful services into your code without much fuss. It gives you control over the format of the outgoing messages, request parameters and request paths. It also maps response codes to Ruby objects using structure_mapper gem.
22
+
23
+ The best way to learn about the DSL is to try combining features demonstrated by examples:
24
+
25
+ ### Get request
26
+ In order to invoke a simple get request without any parameters, one can use following mapping:
27
+
28
+ class SimpleService < RestfulMapper::Service
29
+ base_url "http://localhost:8765"
30
+
31
+ get :simple_endpoint do
32
+ path "/simple"
33
+ responses 200 => true, 0 => false
34
+ end
35
+ end
36
+
37
+ Invoking SimpleService.simple_endpoint will return 'true' value if the response code of the service http://localhost:8765/simple is 200 and false for any other response code.
38
+
39
+ ### Get request with request parameters
40
+ In order to add parameter to a simple service definition, one has to add 'query_parameters' array:
41
+
42
+ class SimpleService < RestfulMapper::Service
43
+ base_url "http://localhost:8765"
44
+
45
+ get :simple_endpoint do
46
+ path "/simple"
47
+ query_parameters [:name]
48
+ responses 200 => true, 0=>false
49
+ end
50
+
51
+ end
52
+
53
+ When invoked with 'SimpleService.simple_endpoint name: "test"' RestfulMapper will perform a GET request to http://localhost:8765/simple?name=test.
54
+
55
+ ### Get request with path parameters
56
+ Path of the service can be parametrized using Mustache syntax:
57
+
58
+ class SimpleService < RestfulMapper::Service
59
+ base_url "http://localhost:8765"
60
+
61
+ get :simple_endpoint do
62
+ path "/simple/{{name}}"
63
+ responses 200 => true, 0=>false
64
+ end
65
+ end
66
+
67
+ Calling 'SimpleService.simple_endpoint name: "test"' will perform GET request to http://localhost:8765/simple/test.
68
+
69
+
70
+ ### Post request with JSON body
71
+ In order to use parameter as JSON body, one has to declare it using 'body_parameter' directive
72
+
73
+ class SimpleService < RestfulMapper::Service
74
+ base_url "http://localhost:8765"
75
+
76
+ post :simple_endpoint do
77
+ path "/simple/{{name}}"
78
+ body_parameter :body
79
+ responses 200 => true, 0=>false
80
+ end
81
+ end
82
+
83
+ Calling 'SimpleService.simple_endpoint name: "test", body: {'a' => 'b'}' will perform POST request to http://localhost:8765/simple/test with body '{"a":"b"}'.
84
+
85
+ ### Mapping JSON response to Ruby objects
86
+ Thanks to structure_mapper, one can easily transform JSON returned by the service into Ruby object. First we
87
+ need definition of the object:
88
+
89
+ class SimpleResponse
90
+ include StructureMapper::Hash
91
+
92
+ attribute a: String
93
+ end
94
+
95
+ And then we need to use the defined object as response mapping:
96
+
97
+ class SimpleService < RestfulMapper::Service
98
+ base_url "http://localhost:8765"
99
+
100
+ get :simple_endpoint do
101
+ path "/simple"
102
+ responses 200 => SimpleResponse, 0 => false
103
+ end
104
+ end
105
+
106
+ If http://localhost:8765/simple returns 200 and a JSON body '{"a":"b"}' then calling 'SimpleService.simple_endpoint'
107
+ will return instance of SimpleResponse with property 'a' set to 'b'.
108
+
109
+ ### Basic Authentication
110
+ TBD
111
+
112
+ ### Raising Exception
113
+ TBD
114
+
115
+ ## Contributing
116
+
117
+ 1. Fork it ( http://github.com/<my-github-username>/restful_mapper/fork )
118
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
119
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
120
+ 4. Push to the branch (`git push origin my-new-feature`)
121
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,42 @@
1
+ require 'restful_mapper'
2
+ require 'pp'
3
+
4
+ class Dependency
5
+ include StructureMapper::Hash
6
+ attribute name: String
7
+ attribute requirements: String
8
+ end
9
+
10
+ class RubyGemInfo
11
+ include StructureMapper::Hash
12
+ attribute name: String
13
+ attribute downloads: Fixnum
14
+ attribute version: String
15
+ attribute version_downloads: Fixnum
16
+ attribute platform: String
17
+ attribute authors: String
18
+ attribute info: String
19
+ attribute licenses: []
20
+ attribute project_uri: String
21
+ attribute gem_uri: String
22
+ attribute homepage_uri: String
23
+ attribute wiki_uri: String
24
+ attribute documentation_uri: String
25
+ attribute mailing_list_uri: String
26
+ attribute source_code_uri: String
27
+ attribute bug_tracker_uri: String
28
+ attribute dependencies: {String => [Dependency]}
29
+ end
30
+
31
+ class RubyGemsService < RestfulMapper::Service
32
+
33
+ base_url 'https://rubygems.org/api/v1'
34
+
35
+ get :gems do
36
+ path 'gems/rails.json', {}
37
+ responses 200 => RubyGemInfo
38
+ end
39
+ end
40
+
41
+
42
+ pp RubyGemsService.gems({})
@@ -0,0 +1,49 @@
1
+ Feature: basic authentication
2
+
3
+ Scenario: basic authentication of a GET request
4
+ Given following service definition
5
+ """
6
+ class SimpleService < RestfulMapper::Service
7
+ base_url "http://localhost:8765"
8
+
9
+ default_parameters name: 'test'
10
+
11
+ basic_authentication 'username', 'password'
12
+
13
+ get :simple_endpoint do
14
+ path "/simple"
15
+
16
+ query_parameters [:name]
17
+
18
+ responses 302 => true
19
+ end
20
+
21
+ end
22
+ """
23
+ And the service endpoint at port 8765 is running
24
+ When I call service "SimpleService.simple_endpoint"
25
+ And the endpoint should receive request header "Authorization" with value "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
26
+
27
+ Scenario: basic authentication using parameters for username and password
28
+ Given following service definition
29
+ """
30
+ class SimpleService < RestfulMapper::Service
31
+ base_url "http://localhost:8765"
32
+
33
+ default_parameters name: 'test'
34
+
35
+ basic_authentication :user, :password
36
+
37
+ get :simple_endpoint do
38
+ path "/simple"
39
+
40
+ query_parameters [:name]
41
+
42
+ responses 302 => true
43
+ end
44
+
45
+ end
46
+ """
47
+ And the service endpoint at port 8765 is running
48
+ When I call service "SimpleService.simple_endpoint user: 'username', password: 'password' "
49
+ And the endpoint should receive request header "Authorization" with value "Basic dXNlcm5hbWU6cGFzc3dvcmQ="
@@ -0,0 +1,55 @@
1
+ Feature: default parameters
2
+
3
+ Scenario: simple get request with default request parameters
4
+ Given following service definition
5
+ """
6
+ class SimpleService < RestfulMapper::Service
7
+ base_url "http://localhost:8765"
8
+
9
+ default_parameters name: 'test'
10
+
11
+ get :simple_endpoint do
12
+ path "/simple"
13
+
14
+ query_parameters [:name]
15
+
16
+ responses 302 => true
17
+ end
18
+
19
+ end
20
+ """
21
+ And the service endpoint at port 8765 is running
22
+ When I call service "SimpleService.simple_endpoint"
23
+ Then the endpoint should receive request
24
+ """
25
+ GET /simple?name=test HTTP/1.1
26
+
27
+ """
28
+
29
+
30
+
31
+ Scenario: overriding default parameters with method parameters
32
+ Given following service definition
33
+ """
34
+ class SimpleService < RestfulMapper::Service
35
+ base_url "http://localhost:8765"
36
+
37
+ default_parameters name: 'test'
38
+
39
+ get :simple_endpoint do
40
+ path "/simple"
41
+
42
+ query_parameters [:name]
43
+
44
+ responses 302 => true
45
+ end
46
+
47
+ end
48
+ """
49
+ And the service endpoint at port 8765 is running
50
+ When I call service "SimpleService.simple_endpoint name: 'test2'"
51
+ Then the endpoint should receive request
52
+ """
53
+ GET /simple?name=test2 HTTP/1.1
54
+
55
+ """
@@ -0,0 +1,25 @@
1
+ Feature: delete request
2
+
3
+ Scenario: simple get request with a body and no other parameters that returns 200
4
+ Given following service definition
5
+ """
6
+ class SimpleService < RestfulMapper::Service
7
+ base_url "http://localhost:8765"
8
+
9
+ delete :simple_endpoint do
10
+ path "/simple"
11
+
12
+ responses 201 => true
13
+ end
14
+
15
+ end
16
+ """
17
+ And the service endpoint at port 8765 is running
18
+ When I call service "SimpleService.simple_endpoint"
19
+ And the endpoint should receive request
20
+ """
21
+ DELETE /simple HTTP/1.1
22
+ """
23
+
24
+
25
+
@@ -0,0 +1,124 @@
1
+ Feature: get request
2
+
3
+ Scenario: simple get request without any parameters that returns 200
4
+ Given following service definition
5
+ """
6
+ class SimpleService < RestfulMapper::Service
7
+ base_url "http://localhost:8765"
8
+
9
+ get :simple_endpoint do
10
+ path "/simple"
11
+
12
+ responses 200 => {String => String}
13
+ end
14
+
15
+ end
16
+ """
17
+ And the service endpoint at port 8765 responds with following http response:
18
+ """
19
+ HTTP/1.1 200 OK
20
+ Connection: close
21
+ Content-Type: application/json
22
+
23
+ {"a": "b"}
24
+ """
25
+ When I call service "SimpleService.simple_endpoint"
26
+ Then the result should be equal to:
27
+ """
28
+ {"a" => "b"}
29
+ """
30
+
31
+ Scenario: simple get request without any parameters that returns 302
32
+ Given following service definition
33
+ """
34
+ class SimpleService < RestfulMapper::Service
35
+ base_url "http://localhost:8765"
36
+
37
+ get :simple_endpoint do
38
+ path "/simple"
39
+
40
+ responses 302 => true
41
+ end
42
+
43
+ end
44
+ """
45
+ And the service endpoint at port 8765 responds with following http response:
46
+ """
47
+ HTTP/1.1 302 OK
48
+ Connection: close
49
+ Content-Type: application/json
50
+
51
+ """
52
+ When I call service "SimpleService.simple_endpoint"
53
+ Then the result should be equal to:
54
+ """
55
+ true
56
+ """
57
+
58
+ Scenario: simple get request with request parameters
59
+ Given following service definition
60
+ """
61
+ class SimpleService < RestfulMapper::Service
62
+ base_url "http://localhost:8765"
63
+
64
+ get :simple_endpoint do
65
+ path "/simple"
66
+
67
+ query_parameters [:name]
68
+
69
+ responses 302 => true
70
+ end
71
+
72
+ end
73
+ """
74
+ And the service endpoint at port 8765 is running
75
+ When I call service "SimpleService.simple_endpoint name: 'test'"
76
+ Then the endpoint should receive request
77
+ """
78
+ GET /simple?name=test HTTP/1.1
79
+
80
+ """
81
+
82
+ Scenario: simple get request with path parameters
83
+ Given following service definition
84
+ """
85
+ class SimpleService < RestfulMapper::Service
86
+ base_url "http://localhost:8765"
87
+
88
+ get :simple_endpoint do
89
+ path "/simple/{{name}}"
90
+
91
+ responses 302 => true
92
+ end
93
+
94
+ end
95
+ """
96
+ And the service endpoint at port 8765 is running
97
+ When I call service "SimpleService.simple_endpoint name: 'test'"
98
+ Then the endpoint should receive request
99
+ """
100
+ GET /simple/test HTTP/1.1
101
+
102
+ """
103
+
104
+ Scenario: simple get request with path and query parameters
105
+ Given following service definition
106
+ """
107
+ class SimpleService < RestfulMapper::Service
108
+ base_url "http://localhost:8765"
109
+
110
+ get :simple_endpoint do
111
+ path "/simple/{{name}}"
112
+ query_parameters [:name]
113
+ responses 302 => true
114
+ end
115
+
116
+ end
117
+ """
118
+ And the service endpoint at port 8765 is running
119
+ When I call service "SimpleService.simple_endpoint name: 'test'"
120
+ Then the endpoint should receive request
121
+ """
122
+ GET /simple/test?name=test HTTP/1.1
123
+
124
+ """
@@ -0,0 +1,31 @@
1
+ Feature: post request
2
+
3
+ Scenario: simple get request with a body and no other parameters that returns 200
4
+ Given following service definition
5
+ """
6
+ class SimpleService < RestfulMapper::Service
7
+ base_url "http://localhost:8765"
8
+
9
+ post :simple_endpoint do
10
+ path "/simple"
11
+
12
+ body_parameter :body
13
+
14
+ responses 201 => true
15
+ end
16
+
17
+ end
18
+ """
19
+ And the service endpoint at port 8765 is running
20
+ When I call service "SimpleService.simple_endpoint body: {'p1' => 'v1'}"
21
+ And the endpoint should receive request
22
+ """
23
+ POST /simple HTTP/1.1
24
+ """
25
+ And request body should be
26
+ """
27
+ {"p1":"v1"}
28
+ """
29
+
30
+
31
+
@@ -0,0 +1,31 @@
1
+ Feature: put request
2
+
3
+ Scenario: simple get request with a body and no other parameters that returns 200
4
+ Given following service definition
5
+ """
6
+ class SimpleService < RestfulMapper::Service
7
+ base_url "http://localhost:8765"
8
+
9
+ put :simple_endpoint do
10
+ path "/simple"
11
+
12
+ body_parameter :body
13
+
14
+ responses 201 => true
15
+ end
16
+
17
+ end
18
+ """
19
+ And the service endpoint at port 8765 is running
20
+ When I call service "SimpleService.simple_endpoint body: {'p1' => 'v1'}"
21
+ And the endpoint should receive request
22
+ """
23
+ PUT /simple HTTP/1.1
24
+ """
25
+ And request body should be
26
+ """
27
+ {"p1":"v1"}
28
+ """
29
+
30
+
31
+
@@ -0,0 +1,30 @@
1
+ Feature: raising exception when return structure is an instance of exception
2
+
3
+
4
+ Scenario: raising exception when structure is exception
5
+ Given following service definition
6
+ """
7
+ class ExceptionResponse < Exception
8
+ include StructureMapper::Hash
9
+ attribute a: String
10
+ end
11
+ class SimpleService < RestfulMapper::Service
12
+ base_url "http://localhost:8765"
13
+
14
+ put :simple_endpoint do
15
+ path "/simple"
16
+
17
+ body_parameter :body
18
+
19
+ responses 201 => ExceptionResponse
20
+ end
21
+
22
+ end
23
+ """
24
+ And the service endpoint at port 8765 is running
25
+ When I call service "SimpleService.simple_endpoint body: {'p1' => 'v1'}" expecting exception
26
+ And exception should be raised
27
+ """
28
+ ExceptionResponse.new
29
+ """
30
+
@@ -0,0 +1,6 @@
1
+ Then(/^the endpoint should receive request header "(.*?)" with value "(.*?)"$/) do |name, value|
2
+ headers=@response_headers_channel.receive.first
3
+ # raise headers.inspect
4
+ headers.should have_key name
5
+ headers[name].should == value
6
+ end
@@ -0,0 +1,75 @@
1
+ Given(/^following service definition$/) do |code|
2
+ pretext="require 'restful_mapper'\n"
3
+ @module.module_eval "%s%s" % [pretext,code], "cucuber", 1
4
+ end
5
+
6
+ Given(/^the service endpoint at port (\d+) responds with following http response:$/) do |port, response|
7
+ server=TCPServer.new port.to_i
8
+ go! do
9
+ connection=server.accept
10
+ connection.readline
11
+ connection.write(response)
12
+ connection.close
13
+ server.close
14
+ end
15
+ end
16
+
17
+
18
+ When(/^I call service "(.*?)"$/) do |code|
19
+ @result=@module.module_eval code
20
+ end
21
+
22
+ Then(/^the result should be equal to:$/) do |expected|
23
+ @result.should == @module.module_eval(expected)
24
+ end
25
+
26
+ Given(/^the service endpoint at port (\d+) is running$/) do |port|
27
+ server=TCPServer.new port.to_i
28
+ response = "HTTP/1.1 201 OK\n\n"
29
+ channel=channel! String,1
30
+ response_channel=channel! String, 1
31
+ headers_channel=channel! Hash, 1
32
+ @server_channel=channel
33
+ @response_body_channel=response_channel
34
+ @response_headers_channel=headers_channel
35
+
36
+ go! do
37
+ connection=server.accept
38
+ channel << connection.readline()
39
+ content_length=nil
40
+ headers={}
41
+ while (line=connection.readline()) != "\r\n"
42
+ # puts "line: %s" % line
43
+ name, value=line.split(":",2)
44
+ if name == "Content-Length"
45
+ content_length=value.to_i
46
+ # puts "content length: %s" % content_length
47
+ end
48
+ headers[name]=value.gsub(/\n|\r/,'').strip
49
+ end
50
+
51
+ headers_channel << headers
52
+
53
+ # puts "content length: %d" % content_length
54
+
55
+ data=(content_length ? connection.read(content_length) : "")
56
+
57
+ # puts "data: %s" % data
58
+
59
+ response_channel << data
60
+
61
+ connection.write(response)
62
+ connection.close
63
+ server.close
64
+
65
+ end
66
+ end
67
+
68
+ Then(/^the endpoint should receive request$/) do |request|
69
+ @server_channel.receive.first.gsub(/\r|\n/,'').should == request.gsub(/\r|\n/,'')
70
+ end
71
+
72
+ When(/^request body should be$/) do |expected|
73
+ @response_body_channel.receive.first.should == expected
74
+ end
75
+
@@ -0,0 +1,15 @@
1
+ When(/^exception should be raised$/) do |code|
2
+ @exception.should == @module.module_eval(code)
3
+ end
4
+
5
+ When(/^I call service "(.*?)" expecting exception$/) do |code|
6
+ failed=true
7
+ begin
8
+ @result=@module.module_eval code
9
+ failed=false
10
+ rescue Exception => e
11
+ @exception=e
12
+ end
13
+
14
+ raise "expected to raise exception" unless failed
15
+ end
@@ -0,0 +1,6 @@
1
+ require 'agent'
2
+
3
+
4
+ Before do
5
+ @module=Module.new
6
+ end
@@ -0,0 +1,3 @@
1
+ module RestfulMapper
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,156 @@
1
+ require 'faraday'
2
+ require 'json'
3
+ require "restful_mapper/version"
4
+ require 'structure_mapper'
5
+ require 'multi_json'
6
+ require 'mustache'
7
+
8
+
9
+ class Object # http://whytheluckystiff.net/articles/seeingMetaclassesClearly.html
10
+ def meta_def name, &blk
11
+ (class << self; self; end).instance_eval { define_method name, &blk }
12
+ end
13
+ end
14
+
15
+
16
+ module RestfulMapper
17
+
18
+ class EndpointDefinition
19
+
20
+ def initialize base_url, method, basic_authentication
21
+ @base_url=base_url
22
+ @query_parameters=[]
23
+ @method=method
24
+ @basic_authentication=basic_authentication
25
+ end
26
+
27
+ def path path, options={}
28
+ @path=path
29
+ end
30
+
31
+ def responses response_mapping={}
32
+ @response_mapping=response_mapping
33
+ end
34
+
35
+ def body_parameter body_parameter
36
+ @body_parameter=body_parameter
37
+ end
38
+
39
+
40
+ def query_parameters parameters
41
+ @query_parameters=parameters.dup
42
+ end
43
+
44
+
45
+ def filter_parameters hash
46
+ hash.dup.delete_if do |k,v|
47
+ not (@query_parameters.include?(k.to_sym) || @query_parameters.include?(k.to_s))
48
+ end
49
+ end
50
+
51
+ def call_service params
52
+ conn = Faraday.new(:url => @base_url) do |faraday|
53
+ # faraday.response :logger # log requests to STDOUT
54
+ faraday.adapter Faraday.default_adapter # make requests with Net::HTTP
55
+ end
56
+
57
+ if has_basic_authentication?
58
+ conn.basic_auth(*basic_authentication_data(params))
59
+ end
60
+
61
+ response=conn.run_request(@method, Mustache.render(@path, params), nil, {'Content-Type' => 'application/json'}) { |request|
62
+ request.params.update(filter_parameters(params)) if filter_parameters(params)
63
+ if @body_parameter
64
+ request.body=MultiJson.dump(params[@body_parameter].to_structure)
65
+ end
66
+
67
+
68
+ }
69
+
70
+
71
+ status=response.status
72
+ status_class=@response_mapping[status]
73
+ status_class||=@response_mapping[0]
74
+ body=response.body
75
+ result=deserialize body, status_class
76
+ if Exception === result
77
+ raise result
78
+ end
79
+ result
80
+ end
81
+
82
+ def has_basic_authentication?
83
+ @basic_authentication
84
+ end
85
+
86
+ def basic_authentication_data params
87
+ @basic_authentication.map{|name| Symbol === name ? params[name] : name}
88
+ end
89
+
90
+
91
+ def deserialize json, mapping
92
+ if json && !json.empty?
93
+ mapping.from_structure(MultiJson.load(json))
94
+ else
95
+ if Hash == mapping || Array == mapping || mapping.is_a?(Class)
96
+ mapping.new
97
+ else
98
+ mapping
99
+ end
100
+ end
101
+ end
102
+
103
+
104
+ end
105
+
106
+
107
+
108
+
109
+ class Service
110
+
111
+ def self.base_url base_url
112
+ @base_url=base_url
113
+ end
114
+
115
+ attr_reader :base_url
116
+
117
+
118
+ def self.get name, &definition
119
+ service_method name, definition, :get
120
+ end
121
+
122
+ def self.post name, &definition
123
+ service_method name, definition, :post
124
+ end
125
+
126
+ def self.put name, &definition
127
+ service_method name, definition, :put
128
+ end
129
+
130
+ def self.delete name, &definition
131
+ service_method name, definition, :delete
132
+ end
133
+
134
+ def self.default_parameters parameters
135
+ @default_parameters=parameters
136
+ end
137
+
138
+ def self.basic_authentication username, password
139
+ @basic_authentication=[username,password]
140
+ end
141
+
142
+ private
143
+
144
+ def self.service_method name, definition, method
145
+ endpoint_definition=EndpointDefinition.new @base_url, method, @basic_authentication
146
+ endpoint_definition.instance_exec(&definition)
147
+ self.meta_def(name.to_sym) do |params={}|
148
+ copy=(@default_parameters || {}).merge(params)
149
+ endpoint_definition.call_service copy
150
+ end
151
+
152
+ end
153
+
154
+ end
155
+
156
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'restful_mapper/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "restful_mapper"
8
+ spec.version = RestfulMapper::VERSION
9
+ spec.authors = ["Dragan Milic"]
10
+ spec.email = ["dragan@netice9.com"]
11
+ spec.summary = %q{Mapper of RESTful services to ruby objects. Makes calling RESTful services and parsing responses a breeze.}
12
+ spec.description = %q{Mapper of RESTful services to ruby objects. Makes calling RESTful services and parsing responses a breeze.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.5"
22
+ spec.add_development_dependency "rake"
23
+ spec.add_development_dependency "rspec"
24
+ spec.add_development_dependency "autotest"
25
+ spec.add_development_dependency "cucumber"
26
+ spec.add_development_dependency "puma"
27
+ spec.add_development_dependency "sinatra"
28
+ spec.add_development_dependency "agent"
29
+ spec.add_dependency "faraday"
30
+ spec.add_dependency "multi_json"
31
+ spec.add_dependency "structure_mapper"
32
+ spec.add_dependency "mustache"
33
+ end
metadata ADDED
@@ -0,0 +1,245 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: restful_mapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dragan Milic
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-03-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.5'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.5'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: autotest
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: cucumber
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: puma
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sinatra
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: agent
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: faraday
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: multi_json
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: structure_mapper
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: mustache
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - ">="
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ description: Mapper of RESTful services to ruby objects. Makes calling RESTful services
182
+ and parsing responses a breeze.
183
+ email:
184
+ - dragan@netice9.com
185
+ executables: []
186
+ extensions: []
187
+ extra_rdoc_files: []
188
+ files:
189
+ - ".gitignore"
190
+ - Gemfile
191
+ - LICENSE.txt
192
+ - README.md
193
+ - Rakefile
194
+ - examples/rubygems.rb
195
+ - features/basic_authentication.feature
196
+ - features/default_parameters.feature
197
+ - features/delete_request.feature
198
+ - features/get_request.feature
199
+ - features/post_request.feature
200
+ - features/put_request.feature
201
+ - features/raising_exceptions.feature
202
+ - features/step_definitions/basic_authentication_steps.rb
203
+ - features/step_definitions/get_request_steps.rb
204
+ - features/step_definitions/raising_exceptions_steps.rb
205
+ - features/support/env.rb
206
+ - lib/restful_mapper.rb
207
+ - lib/restful_mapper/version.rb
208
+ - restful_mapper.gemspec
209
+ homepage: ''
210
+ licenses:
211
+ - MIT
212
+ metadata: {}
213
+ post_install_message:
214
+ rdoc_options: []
215
+ require_paths:
216
+ - lib
217
+ required_ruby_version: !ruby/object:Gem::Requirement
218
+ requirements:
219
+ - - ">="
220
+ - !ruby/object:Gem::Version
221
+ version: '0'
222
+ required_rubygems_version: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - ">="
225
+ - !ruby/object:Gem::Version
226
+ version: '0'
227
+ requirements: []
228
+ rubyforge_project:
229
+ rubygems_version: 2.2.2
230
+ signing_key:
231
+ specification_version: 4
232
+ summary: Mapper of RESTful services to ruby objects. Makes calling RESTful services
233
+ and parsing responses a breeze.
234
+ test_files:
235
+ - features/basic_authentication.feature
236
+ - features/default_parameters.feature
237
+ - features/delete_request.feature
238
+ - features/get_request.feature
239
+ - features/post_request.feature
240
+ - features/put_request.feature
241
+ - features/raising_exceptions.feature
242
+ - features/step_definitions/basic_authentication_steps.rb
243
+ - features/step_definitions/get_request_steps.rb
244
+ - features/step_definitions/raising_exceptions_steps.rb
245
+ - features/support/env.rb