restfulie 0.1.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +28 -0
- data/Gemfile.lock +128 -0
- data/LICENSE +17 -0
- data/README.textile +138 -0
- data/Rakefile +146 -0
- data/lib/restfulie/client/base.rb +36 -0
- data/lib/restfulie/client/cache/basic.rb +76 -0
- data/lib/restfulie/client/cache/fake.rb +15 -0
- data/lib/restfulie/client/cache/http_ext.rb +123 -0
- data/lib/restfulie/client/cache/restrictions.rb +13 -0
- data/lib/restfulie/client/cache.rb +11 -0
- data/lib/restfulie/client/configuration.rb +67 -0
- data/lib/restfulie/client/dsl.rb +66 -0
- data/lib/restfulie/client/entry_point.rb +61 -0
- data/lib/restfulie/client/ext/atom_ext.rb +14 -0
- data/lib/restfulie/client/ext/http_ext.rb +22 -0
- data/lib/restfulie/client/ext/json_ext.rb +16 -0
- data/lib/restfulie/client/feature/base.rb +75 -0
- data/lib/restfulie/client/feature/base_request.rb +35 -0
- data/lib/restfulie/client/feature/cache.rb +16 -0
- data/lib/restfulie/client/feature/enhance_response.rb +12 -0
- data/lib/restfulie/client/feature/follow_request.rb +41 -0
- data/lib/restfulie/client/feature/history.rb +26 -0
- data/lib/restfulie/client/feature/history_request.rb +19 -0
- data/lib/restfulie/client/feature/open_search/pattern_matcher.rb +25 -0
- data/lib/restfulie/client/feature/open_search.rb +21 -0
- data/lib/restfulie/client/feature/serialize_body.rb +32 -0
- data/lib/restfulie/client/feature/setup_header.rb +22 -0
- data/lib/restfulie/client/feature/throw_error.rb +41 -0
- data/lib/restfulie/client/feature/verb.rb +119 -0
- data/lib/restfulie/client/feature.rb +5 -0
- data/lib/restfulie/client/http/cache.rb +28 -0
- data/lib/restfulie/client/http/error.rb +77 -0
- data/lib/restfulie/client/http/response_holder.rb +29 -0
- data/lib/restfulie/client/http.rb +7 -0
- data/lib/restfulie/client/master_delegator.rb +31 -0
- data/lib/restfulie/client/mikyung/concatenator.rb +18 -0
- data/lib/restfulie/client/mikyung/core.rb +70 -0
- data/lib/restfulie/client/mikyung/languages/german.rb +24 -0
- data/lib/restfulie/client/mikyung/languages/portuguese.rb +23 -0
- data/lib/restfulie/client/mikyung/languages.rb +11 -0
- data/lib/restfulie/client/mikyung/rest_process_model.rb +191 -0
- data/lib/restfulie/client/mikyung/steady_state_walker.rb +38 -0
- data/lib/restfulie/client/mikyung/then_condition.rb +39 -0
- data/lib/restfulie/client/mikyung/when_condition.rb +57 -0
- data/lib/restfulie/client/mikyung.rb +15 -0
- data/lib/restfulie/client.rb +26 -0
- data/lib/restfulie/common/converter/atom/base.rb +91 -0
- data/lib/restfulie/common/converter/atom/builder.rb +111 -0
- data/lib/restfulie/common/converter/atom/helpers.rb +17 -0
- data/lib/restfulie/common/converter/atom.rb +12 -0
- data/lib/restfulie/common/converter/json/base.rb +87 -0
- data/lib/restfulie/common/converter/json/builder.rb +102 -0
- data/lib/restfulie/common/converter/json/helpers.rb +17 -0
- data/lib/restfulie/common/converter/json.rb +12 -0
- data/lib/restfulie/common/converter/open_search/descriptor.rb +32 -0
- data/lib/restfulie/common/converter/open_search.rb +16 -0
- data/lib/restfulie/common/converter/values.rb +33 -0
- data/lib/restfulie/common/converter/xml/base.rb +63 -0
- data/lib/restfulie/common/converter/xml/builder.rb +113 -0
- data/lib/restfulie/common/converter/xml/helpers.rb +17 -0
- data/lib/restfulie/common/converter/xml/link.rb +30 -0
- data/lib/restfulie/common/converter/xml/links.rb +21 -0
- data/lib/restfulie/common/converter/xml.rb +14 -0
- data/lib/restfulie/common/converter.rb +43 -0
- data/lib/restfulie/common/core_ext/hash.rb +18 -0
- data/lib/restfulie/common/core_ext.rb +1 -0
- data/lib/restfulie/common/error.rb +19 -0
- data/lib/restfulie/common/links.rb +9 -0
- data/lib/restfulie/common/logger.rb +19 -0
- data/lib/restfulie/common/representation/atom/atom.rng +597 -0
- data/lib/restfulie/common/representation/atom/base.rb +142 -0
- data/lib/restfulie/common/representation/atom/category.rb +41 -0
- data/lib/restfulie/common/representation/atom/entry.rb +59 -0
- data/lib/restfulie/common/representation/atom/factory.rb +43 -0
- data/lib/restfulie/common/representation/atom/feed.rb +110 -0
- data/lib/restfulie/common/representation/atom/link.rb +68 -0
- data/lib/restfulie/common/representation/atom/person.rb +48 -0
- data/lib/restfulie/common/representation/atom/source.rb +59 -0
- data/lib/restfulie/common/representation/atom/tag_collection.rb +38 -0
- data/lib/restfulie/common/representation/atom/xml.rb +90 -0
- data/lib/restfulie/common/representation/atom.rb +20 -0
- data/lib/restfulie/common/representation/generic.rb +22 -0
- data/lib/restfulie/common/representation/json/base.rb +27 -0
- data/lib/restfulie/common/representation/json/keys_as_methods.rb +74 -0
- data/lib/restfulie/common/representation/json/link.rb +29 -0
- data/lib/restfulie/common/representation/json/link_collection.rb +23 -0
- data/lib/restfulie/common/representation/json.rb +13 -0
- data/lib/restfulie/common/representation/links.rb +11 -0
- data/lib/restfulie/common/representation.rb +3 -0
- data/lib/restfulie/common.rb +18 -0
- data/lib/restfulie/server/action_controller/base.rb +48 -0
- data/lib/restfulie/server/action_controller/params_parser.rb +100 -0
- data/lib/restfulie/server/action_controller/patch.rb +6 -0
- data/lib/restfulie/server/action_controller/restful_responder.rb +12 -0
- data/lib/restfulie/server/action_controller/trait/cacheable.rb +81 -0
- data/lib/restfulie/server/action_controller/trait/created.rb +17 -0
- data/lib/restfulie/server/action_controller/trait.rb +9 -0
- data/lib/restfulie/server/action_controller.rb +11 -0
- data/lib/restfulie/server/action_view/helpers.rb +50 -0
- data/lib/restfulie/server/action_view/template_handlers/tokamak.rb +21 -0
- data/lib/restfulie/server/action_view/template_handlers.rb +30 -0
- data/lib/restfulie/server/action_view.rb +10 -0
- data/lib/restfulie/server/configuration.rb +24 -0
- data/lib/restfulie/server/controller.rb +74 -0
- data/lib/restfulie/server/core_ext/array.rb +61 -0
- data/lib/restfulie/server/core_ext.rb +1 -0
- data/lib/restfulie/server.rb +25 -0
- data/lib/restfulie/version.rb +14 -0
- data/lib/restfulie.rb +34 -0
- metadata +242 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
class Restfulie::Client::Feature::SerializeBody
|
2
|
+
|
3
|
+
def execute(flow, request, response, env)
|
4
|
+
|
5
|
+
if should_have_payload?(request.verb)
|
6
|
+
|
7
|
+
payload = env[:body]
|
8
|
+
if payload && !(payload.kind_of?(String) && payload.empty?)
|
9
|
+
type = request.headers['Content-Type']
|
10
|
+
raise Restfulie::Common::Error::RestfulieError, "Missing content type related to the data to be submitted" unless type
|
11
|
+
|
12
|
+
marshaller = Restfulie::Common::Converter.content_type_for(type)
|
13
|
+
raise Restfulie::Common::Error::RestfulieError, "Missing content type for #{type} related to the data to be submitted" unless marshaller
|
14
|
+
|
15
|
+
rel = request.respond_to?(:rel) ? request.rel : ""
|
16
|
+
env[:body] = marshaller.marshal(payload, { :rel => rel, :recipe => env[:recipe] })
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
flow.continue(request, response, env)
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
PAYLOAD_METHODS = {:put=>true,:post=>true,:patch=>true}
|
27
|
+
|
28
|
+
def should_have_payload?(method)
|
29
|
+
PAYLOAD_METHODS[method]
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Restfulie::Client::Feature
|
2
|
+
|
3
|
+
class SetupHeader
|
4
|
+
|
5
|
+
def execute(flow, request, response, env)
|
6
|
+
headers = request.default_headers.dup.merge(request.headers)
|
7
|
+
host = request.host
|
8
|
+
if host.user || host.password
|
9
|
+
headers["Authorization"] = "Basic " + ["#{host.user}:#{host.password}"].pack("m").delete("\r\n")
|
10
|
+
end
|
11
|
+
headers.delete :recipe
|
12
|
+
headers['cookie'] = request.cookies if request.cookies
|
13
|
+
|
14
|
+
# gs: this should not be overriden, do it in some other way
|
15
|
+
request.headers = headers
|
16
|
+
|
17
|
+
flow.continue(request, response, env)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
class Restfulie::Client::Feature::ThrowError
|
2
|
+
def execute(flow, request, result_so_far, env)
|
3
|
+
result = flow.continue(request, result_so_far, env)
|
4
|
+
if result.kind_of? Exception
|
5
|
+
Restfulie::Common::Logger.logger.error(result)
|
6
|
+
raise Restfulie::Client::HTTP::Error::ServerNotAvailableError.new(request, Restfulie::Client::HTTP::Response.new(request.verb, request.path, 503, nil, {}), result )
|
7
|
+
end
|
8
|
+
case result.response.code.to_i
|
9
|
+
when 100..299
|
10
|
+
result
|
11
|
+
when 300..399
|
12
|
+
raise Restfulie::Client::HTTP::Error::Redirection.new(request, result)
|
13
|
+
when 400
|
14
|
+
raise Restfulie::Client::HTTP::Error::BadRequest.new(request, result)
|
15
|
+
when 401
|
16
|
+
raise Restfulie::Client::HTTP::Error::Unauthorized.new(request, result)
|
17
|
+
when 403
|
18
|
+
raise Restfulie::Client::HTTP::Error::Forbidden.new(request, result)
|
19
|
+
when 404
|
20
|
+
raise Restfulie::Client::HTTP::Error::NotFound.new(request, result)
|
21
|
+
when 405
|
22
|
+
raise Restfulie::Client::HTTP::Error::MethodNotAllowed.new(request, result)
|
23
|
+
when 407
|
24
|
+
raise Restfulie::Client::HTTP::Error::ProxyAuthenticationRequired.new(request, result)
|
25
|
+
when 409
|
26
|
+
raise Restfulie::Client::HTTP::Error::Conflict.new(request, result)
|
27
|
+
when 410
|
28
|
+
raise Restfulie::Client::HTTP::Error::Gone.new(request, result)
|
29
|
+
when 412
|
30
|
+
raise Restfulie::Client::HTTP::Error::PreconditionFailed.new(request, result)
|
31
|
+
when 402, 406, 408, 411, 413..499
|
32
|
+
raise Restfulie::Client::HTTP::Error::ClientError.new(request, result)
|
33
|
+
when 501
|
34
|
+
raise Restfulie::Client::HTTP::Error::NotImplemented.new(request, result)
|
35
|
+
when 500, 502..599
|
36
|
+
raise Restfulie::Client::HTTP::Error::ServerError.new(request, result)
|
37
|
+
else
|
38
|
+
raise Restfulie::Client::HTTP::Error::UnknownError.new(request, result)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,119 @@
|
|
1
|
+
module Restfulie::Client::Feature::Verb
|
2
|
+
|
3
|
+
# GET HTTP verb without {Error}
|
4
|
+
# * <tt>path: '/posts'</tt>
|
5
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
6
|
+
def get(params = {})
|
7
|
+
@verb = :get
|
8
|
+
at query_string(params)
|
9
|
+
request_flow
|
10
|
+
end
|
11
|
+
|
12
|
+
# HEAD HTTP verb without {Error}
|
13
|
+
# * <tt>path: '/posts'</tt>
|
14
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
15
|
+
def head
|
16
|
+
@verb = :head
|
17
|
+
request_flow
|
18
|
+
end
|
19
|
+
|
20
|
+
# POST HTTP verb without {Error}
|
21
|
+
# * <tt>path: '/posts'</tt>
|
22
|
+
# * <tt>payload: 'some text'</tt>
|
23
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
24
|
+
def post(payload, options = {:recipe => nil})
|
25
|
+
@verb = :post
|
26
|
+
request_flow :body => payload
|
27
|
+
end
|
28
|
+
|
29
|
+
# PATCH HTTP verb without {Error}
|
30
|
+
# * <tt>path: '/posts'</tt>
|
31
|
+
# * <tt>payload: 'some text'</tt>
|
32
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
33
|
+
def patch(payload)
|
34
|
+
@verb = :patch
|
35
|
+
request_flow :body => payload
|
36
|
+
end
|
37
|
+
|
38
|
+
# PUT HTTP verb without {Error}
|
39
|
+
# * <tt>path: '/posts'</tt>
|
40
|
+
# * <tt>payload: 'some text'</tt>
|
41
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
42
|
+
def put(payload)
|
43
|
+
@verb = :put
|
44
|
+
request_flow :body => payload
|
45
|
+
end
|
46
|
+
|
47
|
+
# DELETE HTTP verb without {Error}
|
48
|
+
# * <tt>path: '/posts'</tt>
|
49
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
50
|
+
def delete
|
51
|
+
@verb = :delete
|
52
|
+
request_flow
|
53
|
+
end
|
54
|
+
|
55
|
+
# GET HTTP verb {Error}
|
56
|
+
# * <tt>path: '/posts'</tt>
|
57
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
58
|
+
def get!(params = {})
|
59
|
+
@verb = :get
|
60
|
+
at query_string(params)
|
61
|
+
request :throw_error
|
62
|
+
request_flow
|
63
|
+
end
|
64
|
+
|
65
|
+
# HEAD HTTP verb {Error}
|
66
|
+
# * <tt>path: '/posts'</tt>
|
67
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
68
|
+
def head!
|
69
|
+
@verb = :head
|
70
|
+
request :throw_error
|
71
|
+
request_flow
|
72
|
+
end
|
73
|
+
|
74
|
+
# POST HTTP verb {Error}
|
75
|
+
# * <tt>path: '/posts'</tt>
|
76
|
+
# * <tt>payload: 'some text'</tt>
|
77
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
78
|
+
def post!(payload, options = {:recipe => nil})
|
79
|
+
@verb = :post
|
80
|
+
request :throw_error
|
81
|
+
request_flow :body => payload
|
82
|
+
end
|
83
|
+
|
84
|
+
# PATCH HTTP verb {Error}
|
85
|
+
# * <tt>path: '/posts'</tt>
|
86
|
+
# * <tt>payload: 'some text'</tt>
|
87
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
88
|
+
def patch!(payload)
|
89
|
+
@verb = :patch
|
90
|
+
request :throw_error
|
91
|
+
request_flow :body => payload
|
92
|
+
end
|
93
|
+
|
94
|
+
# PUT HTTP verb {Error}
|
95
|
+
# * <tt>path: '/posts'</tt>
|
96
|
+
# * <tt>payload: 'some text'</tt>
|
97
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
98
|
+
def put!(payload)
|
99
|
+
@verb = :put
|
100
|
+
request :throw_error
|
101
|
+
request_flow :body => payload
|
102
|
+
end
|
103
|
+
|
104
|
+
# DELETE HTTP verb {Error}
|
105
|
+
# * <tt>path: '/posts'</tt>
|
106
|
+
# * <tt>headers: {'Accept' => '*/*', 'Content-Type' => 'application/atom+xml'}</tt>
|
107
|
+
def delete!
|
108
|
+
@verb = :delete
|
109
|
+
request :throw_error
|
110
|
+
request_flow
|
111
|
+
end
|
112
|
+
|
113
|
+
protected
|
114
|
+
|
115
|
+
def query_string(params)
|
116
|
+
params = params.map { |param, value| "#{param}=#{value}"}.join("&")
|
117
|
+
params.blank? ? "" : URI.escape("?#{params}")
|
118
|
+
end
|
119
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Client
|
3
|
+
module HTTP
|
4
|
+
module Cache
|
5
|
+
def store
|
6
|
+
@store || @store = ::ActiveSupport::Cache::MemoryStore.new
|
7
|
+
end
|
8
|
+
|
9
|
+
def get
|
10
|
+
store.fetch(@uri) do
|
11
|
+
request(:get, @uri, @headers)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def head
|
16
|
+
store.fetch(@uri) do
|
17
|
+
request(:head, @uri, @headers)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class RequestBuilderExecutorWithCache < RequestBuilderExecutor
|
23
|
+
include Cache
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Client
|
3
|
+
module HTTP#:nodoc:
|
4
|
+
#Client errors
|
5
|
+
module Error
|
6
|
+
# Standard error thrown on major client exceptions
|
7
|
+
class RESTError < StandardError
|
8
|
+
attr_reader :response
|
9
|
+
attr_reader :request
|
10
|
+
|
11
|
+
def initialize(request, response)
|
12
|
+
@request = request
|
13
|
+
@response = response
|
14
|
+
end
|
15
|
+
|
16
|
+
def to_s
|
17
|
+
"HTTP error #{@response.code} when invoking #{@request.host} via #{@response.method}. " +
|
18
|
+
((@response.body.blank?) ? "No additional data was sent." : "The complete response was:\n" + @response.body)
|
19
|
+
rescue
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class AutoFollowWithoutLocationError < RESTError; end
|
25
|
+
|
26
|
+
# Represents the HTTP code 503
|
27
|
+
class ServerNotAvailableError < RESTError
|
28
|
+
def initialize(request, response, exception)
|
29
|
+
super(request, response)
|
30
|
+
set_backtrace(exception.backtrace)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class UnknownError < RESTError; end
|
35
|
+
|
36
|
+
# Represents the HTTP code 300 range
|
37
|
+
class Redirection < RESTError; end
|
38
|
+
|
39
|
+
class ClientError < RESTError; end
|
40
|
+
|
41
|
+
# Represents the HTTP code 400
|
42
|
+
class BadRequest < ClientError; end
|
43
|
+
|
44
|
+
# Represents the HTTP code 401
|
45
|
+
class Unauthorized < ClientError; end
|
46
|
+
|
47
|
+
# Represents the HTTP code 403
|
48
|
+
class Forbidden < ClientError; end
|
49
|
+
|
50
|
+
# Represents the HTTP code 404
|
51
|
+
class NotFound < ClientError; end
|
52
|
+
|
53
|
+
# Represents the HTTP code 405
|
54
|
+
class MethodNotAllowed < ClientError; end
|
55
|
+
|
56
|
+
# Represents the HTTP code 412
|
57
|
+
class PreconditionFailed < ClientError; end
|
58
|
+
|
59
|
+
# Represents the HTTP code 407
|
60
|
+
class ProxyAuthenticationRequired < ClientError; end
|
61
|
+
|
62
|
+
# Represents the HTTP code 409
|
63
|
+
class Conflict < ClientError; end
|
64
|
+
|
65
|
+
# Represents the HTTP code 410
|
66
|
+
class Gone < ClientError; end
|
67
|
+
|
68
|
+
# Represents the HTTP code 500
|
69
|
+
class ServerError < RESTError; end
|
70
|
+
|
71
|
+
# Represents the HTTP code 501
|
72
|
+
class NotImplemented < ServerError; end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Restfulie::Client::HTTP
|
2
|
+
module ResponseHolder
|
3
|
+
attr_reader :response, :request
|
4
|
+
|
5
|
+
def resource
|
6
|
+
type = headers['content-type'] || response['Content-Type']
|
7
|
+
representation = Restfulie::Common::Converter.content_type_for(type[0]) || Restfulie::Common::Representation::Generic.new
|
8
|
+
representation.unmarshal(response.body)
|
9
|
+
end
|
10
|
+
|
11
|
+
def at(uri)
|
12
|
+
request.clone.at(uri)
|
13
|
+
end
|
14
|
+
|
15
|
+
def headers
|
16
|
+
response.to_hash
|
17
|
+
end
|
18
|
+
|
19
|
+
def results_from(request, response)
|
20
|
+
@request = request
|
21
|
+
@response = response
|
22
|
+
end
|
23
|
+
|
24
|
+
def verb
|
25
|
+
@request.verb
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class MasterDelegator
|
2
|
+
|
3
|
+
alias_method :original_respond_to?, :respond_to?
|
4
|
+
|
5
|
+
def respond_to?(sym)
|
6
|
+
original_respond_to?(sym) || @requester.respond_to?(sym)
|
7
|
+
end
|
8
|
+
|
9
|
+
def method_missing(sym, *args, &block)
|
10
|
+
if original_respond_to?(sym)
|
11
|
+
result = super(sym, *args, &block)
|
12
|
+
elsif @requester.respond_to?(sym)
|
13
|
+
result = @requester.send(sym, *args, &block)
|
14
|
+
else
|
15
|
+
# let it go
|
16
|
+
return super(sym, *args, &block)
|
17
|
+
end
|
18
|
+
delegate_parse result
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def delegate(what, *args, &block)
|
24
|
+
delegate_parse @requester.send(what, *args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
def delegate_parse(result)
|
28
|
+
(result == @requester) ? self : result
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Client
|
3
|
+
module Mikyung
|
4
|
+
# Concatenates pure text in order to build messages
|
5
|
+
# that are used as patterns.
|
6
|
+
# Usage:
|
7
|
+
# When there is a machine
|
8
|
+
#
|
9
|
+
# Will invoke concatenate 'machine' with 'a' with 'is' with 'there'
|
10
|
+
class Concatenator
|
11
|
+
attr_reader :content
|
12
|
+
def initialize(content, *args)
|
13
|
+
@content = args.inject(content) { |buf, arg| buf << " " << arg.content }
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Client
|
3
|
+
module Mikyung
|
4
|
+
# iterates following a series of steps provided a goal and a starting uri.
|
5
|
+
#
|
6
|
+
# Restfulie::Client::Mikyung.achieve(objective).at(uri).run
|
7
|
+
#
|
8
|
+
# In order to implement your own walker, supply an object that respond to the move method.
|
9
|
+
# Check the run method code.
|
10
|
+
class Core
|
11
|
+
attr_reader :start, :goal, :walker, :accepts, :follow
|
12
|
+
|
13
|
+
def initialize
|
14
|
+
@walker = Restfulie::Client::Mikyung::SteadyStateWalker.new
|
15
|
+
end
|
16
|
+
|
17
|
+
def walks_with(walker)
|
18
|
+
@walker = walker
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
# initializes with a goal in mind
|
23
|
+
def achieve(goal)
|
24
|
+
@goal = goal
|
25
|
+
self
|
26
|
+
end
|
27
|
+
|
28
|
+
def at(start)
|
29
|
+
@start = start
|
30
|
+
self
|
31
|
+
end
|
32
|
+
|
33
|
+
def follow
|
34
|
+
@follow = true
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
def accepts(accepts)
|
39
|
+
@accepts = accepts
|
40
|
+
self
|
41
|
+
end
|
42
|
+
|
43
|
+
# keeps changing from a steady state to another until its goal has been achieved
|
44
|
+
def run
|
45
|
+
if @start.kind_of? String
|
46
|
+
client = Restfulie.at(@start)
|
47
|
+
client = client.follow if @follow
|
48
|
+
client = client.accepts(@accepts) if @accepts
|
49
|
+
@start = current = client.get
|
50
|
+
else
|
51
|
+
# probably configured thru the Rest Process Model class
|
52
|
+
@start = current = @goal.class.get_restfulie.get
|
53
|
+
end
|
54
|
+
|
55
|
+
# load the steps and scenario
|
56
|
+
@goal.steps
|
57
|
+
@goal.scenario
|
58
|
+
|
59
|
+
while(!@goal.completed?(current))
|
60
|
+
current = @walker.move(@goal, current, self)
|
61
|
+
end
|
62
|
+
current
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class UnableToAchieveGoalError < Restfulie::Common::Error::RestfulieError
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Client
|
3
|
+
module Mikyung
|
4
|
+
module Languages
|
5
|
+
module German
|
6
|
+
def Wenn(concat, &block)
|
7
|
+
When(concat, &block)
|
8
|
+
end
|
9
|
+
def Und(concat, &block)
|
10
|
+
And(concat, &block)
|
11
|
+
end
|
12
|
+
def Aber(concat, &block)
|
13
|
+
But(concat, &block)
|
14
|
+
end
|
15
|
+
def Dann(concat, &block)
|
16
|
+
Then(concat, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Restfulie
|
2
|
+
module Client
|
3
|
+
module Mikyung
|
4
|
+
module Languages
|
5
|
+
module Portuguese
|
6
|
+
def Quando(concat, &block)
|
7
|
+
When(concat, &block)
|
8
|
+
end
|
9
|
+
def E(concat, &block)
|
10
|
+
And(concat, &block)
|
11
|
+
end
|
12
|
+
def Mas(concat, &block)
|
13
|
+
But(concat, &block)
|
14
|
+
end
|
15
|
+
def Entao(concat, &block)
|
16
|
+
Then(concat, &block)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|