riakrest 0.0.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/History.txt +4 -0
- data/Manifest.txt +41 -0
- data/PostInstall.txt +2 -0
- data/README.rdoc +51 -0
- data/Rakefile +24 -0
- data/examples/auto_update_data.rb +50 -0
- data/examples/auto_update_links.rb +48 -0
- data/examples/basic_client.rb +33 -0
- data/examples/basic_resource.rb +34 -0
- data/examples/json_data_resource.rb +32 -0
- data/examples/linked_resource.rb +113 -0
- data/examples/multiple_resources.rb +43 -0
- data/lib/riakrest/core/exceptions.rb +73 -0
- data/lib/riakrest/core/jiak_bucket.rb +146 -0
- data/lib/riakrest/core/jiak_client.rb +316 -0
- data/lib/riakrest/core/jiak_data.rb +265 -0
- data/lib/riakrest/core/jiak_link.rb +131 -0
- data/lib/riakrest/core/jiak_object.rb +233 -0
- data/lib/riakrest/core/jiak_schema.rb +242 -0
- data/lib/riakrest/core/query_link.rb +156 -0
- data/lib/riakrest/data/jiak_data_hash.rb +182 -0
- data/lib/riakrest/resource/jiak_resource.rb +628 -0
- data/lib/riakrest/version.rb +7 -0
- data/lib/riakrest.rb +164 -0
- data/riakrest.gemspec +38 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/core/exceptions_spec.rb +18 -0
- data/spec/core/jiak_bucket_spec.rb +103 -0
- data/spec/core/jiak_client_spec.rb +358 -0
- data/spec/core/jiak_link_spec.rb +77 -0
- data/spec/core/jiak_object_spec.rb +210 -0
- data/spec/core/jiak_schema_spec.rb +184 -0
- data/spec/core/query_link_spec.rb +128 -0
- data/spec/data/jiak_data_hash_spec.rb +14 -0
- data/spec/resource/jiak_resource_spec.rb +128 -0
- data/spec/riakrest_spec.rb +17 -0
- data/spec/spec.opts +5 -0
- data/spec/spec_helper.rb +12 -0
- data/tasks/rspec.rake +21 -0
- metadata +113 -0
@@ -0,0 +1,146 @@
|
|
1
|
+
module RiakRest
|
2
|
+
|
3
|
+
# Data is stored on the Jiak server by key under a bucket. During Jiak
|
4
|
+
# interaction, the bucket on the server has an associated schema which
|
5
|
+
# determines permissible data interaction. See JiakSchema for a discussion of
|
6
|
+
# schemas in Jiak. Since the bucket schema can be changed dynamically,
|
7
|
+
# schemas can be viewed more as a loose type system rather than an onerous
|
8
|
+
# restriction.
|
9
|
+
#
|
10
|
+
# In RiakRest buckets have an associated JiakData class, and each JiakData
|
11
|
+
# class has an associated JiakSchema. These associations facility setting and
|
12
|
+
# maintaining the current schema in use for a Jiak bucket. Dynamically
|
13
|
+
# changing the bucket schema means you can have either homogeneous (simplest)
|
14
|
+
# or heterogenous data in a single Jiak server bucket. It also means you can
|
15
|
+
# define multiple JiakData classes that effectively present different "views"
|
16
|
+
# (via schemas) into the same data stored on the Jiak server. These classes
|
17
|
+
# act like types that can determine which fields are accessible for reading
|
18
|
+
# and writing data. The JiakData class associated with a bucket is also used
|
19
|
+
# to marshal user-defined data going to and from the Jiak server.
|
20
|
+
#
|
21
|
+
# JiakResource greatly eases the bookkeeping necessary for heterogenous, as
|
22
|
+
# well as homogenous, data interaction with the Jiak server.
|
23
|
+
class JiakBucket
|
24
|
+
|
25
|
+
attr_reader :schema
|
26
|
+
attr_accessor :name, :data_class, :params
|
27
|
+
|
28
|
+
# :call-seq:
|
29
|
+
# JiakBucket.new(name,data_class,params={}) -> JiakBucket
|
30
|
+
#
|
31
|
+
# Create a bucket for use in Jiak interaction.
|
32
|
+
#
|
33
|
+
# Valid optional parameters are <code>params</code> hash are <code>:reads,
|
34
|
+
# :writes, :durable_writes, :waits</code>. See JiakClient#store,
|
35
|
+
# JiakClient#get, and JiakClient#delete for discriptions of these
|
36
|
+
# parameters.
|
37
|
+
#
|
38
|
+
# Raise JiakBucketException if the bucket name is not a non-empty string or
|
39
|
+
# the data class has not included JiakData.
|
40
|
+
def initialize(name,data_class,params={})
|
41
|
+
@name = transform_name(name)
|
42
|
+
@data_class = check_data_class(data_class)
|
43
|
+
@params = check_params(params)
|
44
|
+
end
|
45
|
+
|
46
|
+
# :call-seq:
|
47
|
+
# name = gname
|
48
|
+
#
|
49
|
+
# Set the name of the Jiak bucket.
|
50
|
+
#
|
51
|
+
# Raise JiakBucketException if not a non-empty string.
|
52
|
+
def name=(gname)
|
53
|
+
@name = transform_name(gname)
|
54
|
+
end
|
55
|
+
|
56
|
+
# :call-seq:
|
57
|
+
# data_class = klass
|
58
|
+
#
|
59
|
+
# Set the class for the data to be stored or retrieved from the bucket.
|
60
|
+
#
|
61
|
+
# Raise JiakBucketException if the data class has not included JiakData.
|
62
|
+
def data_class=(data_class)
|
63
|
+
@data_class = check_data_class(data_class)
|
64
|
+
end
|
65
|
+
|
66
|
+
# :call-seq:
|
67
|
+
# bucket.params = params
|
68
|
+
#
|
69
|
+
# Set default params for Jiak client requests. See JiakBucket#new for
|
70
|
+
# valid parameters.
|
71
|
+
#
|
72
|
+
def params=(params)
|
73
|
+
@params = check_params(params)
|
74
|
+
end
|
75
|
+
|
76
|
+
# :call-seq:
|
77
|
+
# bucket.schema -> JiakSchema
|
78
|
+
#
|
79
|
+
# Gets the data schema for this bucket. This call does not access the
|
80
|
+
# server, but rather returns the schema of the current data class
|
81
|
+
# associated with the bucket. This association is required to establish the
|
82
|
+
# Jiak server schema in the first place, so as long as the Jiak server
|
83
|
+
# schema has not be altered by another call to JiakClient#set_schema the
|
84
|
+
# information returned via this call will be current.
|
85
|
+
def schema
|
86
|
+
data_class.schema
|
87
|
+
end
|
88
|
+
|
89
|
+
# :call-seq:
|
90
|
+
# bucket == other -> true or false
|
91
|
+
#
|
92
|
+
# Equality -- JiakBuckets are equal if they contain the same attribute
|
93
|
+
# values.
|
94
|
+
def ==(other)
|
95
|
+
(@name == other.name &&
|
96
|
+
@data_class == other.data_class &&
|
97
|
+
@params == other.params) rescue false
|
98
|
+
end
|
99
|
+
|
100
|
+
# :call-seq:
|
101
|
+
# jiak_bucket.eql?(other) -> true or false
|
102
|
+
#
|
103
|
+
# Returns <code>true</code> if <i>jiak_bucket</i> and <i>other</i> contain
|
104
|
+
# the same attribute values.
|
105
|
+
def eql?(other)
|
106
|
+
(@name.eql?(other.name) &&
|
107
|
+
@data_class.eql?(other.data_class) &&
|
108
|
+
@params.eql?(other.params)) rescue false
|
109
|
+
end
|
110
|
+
|
111
|
+
def hash # :nodoc:
|
112
|
+
@name.hash + @data_class.hash + @params.hash
|
113
|
+
end
|
114
|
+
|
115
|
+
def transform_name(name)
|
116
|
+
unless name.is_a?(String)
|
117
|
+
raise JiakBucketException, "Name must be a string"
|
118
|
+
end
|
119
|
+
b_name = name.dup
|
120
|
+
b_name.strip!
|
121
|
+
raise JiakBucketException, "Name cannot be empty" if b_name.empty?
|
122
|
+
b_name
|
123
|
+
end
|
124
|
+
private :transform_name
|
125
|
+
|
126
|
+
def check_data_class(data_class)
|
127
|
+
unless data_class.include?(JiakData)
|
128
|
+
raise JiakBucketException, "Data class must be type of JiakData."
|
129
|
+
end
|
130
|
+
data_class
|
131
|
+
end
|
132
|
+
private :check_data_class
|
133
|
+
|
134
|
+
def check_params(params)
|
135
|
+
valid = [:reads,:writes,:durable_writes,:waits]
|
136
|
+
err = params.select {|k,v| !valid.include?(k)}
|
137
|
+
unless err.empty?
|
138
|
+
raise JiakBucketException, "unrecognized request params: #{err.keys}"
|
139
|
+
end
|
140
|
+
params
|
141
|
+
end
|
142
|
+
private :check_params
|
143
|
+
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
@@ -0,0 +1,316 @@
|
|
1
|
+
module RiakRest
|
2
|
+
|
3
|
+
# Restful client interaction with a Riak document store via a JSON
|
4
|
+
# interface. See RiakRest for a basic example usage.
|
5
|
+
class JiakClient
|
6
|
+
|
7
|
+
# :stopdoc:
|
8
|
+
APP_JSON = 'application/json'
|
9
|
+
JSON_DATA = 'json'
|
10
|
+
|
11
|
+
RETURN_BODY = 'returnbody'
|
12
|
+
READS = 'r'
|
13
|
+
WRITES = 'w'
|
14
|
+
DURABLE_WRITES = 'dw'
|
15
|
+
RESPONSE_WAITS = 'rw'
|
16
|
+
|
17
|
+
KEYS='keys'
|
18
|
+
SCHEMA='schema'
|
19
|
+
# :startdoc:
|
20
|
+
|
21
|
+
# :call-seq:
|
22
|
+
# JiakClient.new(uri) -> uri
|
23
|
+
#
|
24
|
+
# Create a new client for Riak RESTful (Jiak) interaction with the server at
|
25
|
+
# the specified URI.
|
26
|
+
#
|
27
|
+
# Raise JiakClientException if the server URI is not a string.
|
28
|
+
#
|
29
|
+
def initialize(uri='http://127.0.0.1:8002/jiak/')
|
30
|
+
unless uri.is_a?(String)
|
31
|
+
raise JiakClientException, "Jiak server URI shoud be a String."
|
32
|
+
end
|
33
|
+
@uri = uri
|
34
|
+
@uri += '/' unless @uri.end_with?('/')
|
35
|
+
@uri
|
36
|
+
end
|
37
|
+
|
38
|
+
# :call-seq:
|
39
|
+
# set_schema(bucket) -> nil
|
40
|
+
#
|
41
|
+
# Set the Jiak server schema for a bucket. The schema is determined by the
|
42
|
+
# JiakData associated with the JiakBucket.
|
43
|
+
#
|
44
|
+
# Raise JiakClientException if the bucket is not a JiakBucket.
|
45
|
+
#
|
46
|
+
def set_schema(bucket)
|
47
|
+
unless bucket.is_a?(JiakBucket)
|
48
|
+
raise JiakClientException, "Bucket must be a JiakBucket."
|
49
|
+
end
|
50
|
+
resp = RestClient.put(jiak_uri(bucket),
|
51
|
+
bucket.schema.to_jiak,
|
52
|
+
:content_type => APP_JSON,
|
53
|
+
:data_type => JSON_DATA,
|
54
|
+
:accept => APP_JSON)
|
55
|
+
end
|
56
|
+
|
57
|
+
# :call-seq:
|
58
|
+
# schema(bucket) -> JiakSchema
|
59
|
+
#
|
60
|
+
# Get the data schema for a bucket on a Jiak server. This involves a call
|
61
|
+
# to the Jiak server. See JiakBucket#schema for a way to get this
|
62
|
+
# information without server access.
|
63
|
+
def schema(bucket)
|
64
|
+
JiakSchema.from_jiak(bucket_info(bucket,SCHEMA))
|
65
|
+
end
|
66
|
+
|
67
|
+
# :call-seq:
|
68
|
+
# client.keys(bucket) -> array
|
69
|
+
#
|
70
|
+
# Get an Array of all known keys for the specified bucket. Since key lists
|
71
|
+
# are updated asynchronously the returned array can be out of date
|
72
|
+
# immediately after a put or delete.
|
73
|
+
def keys(bucket)
|
74
|
+
bucket_info(bucket,KEYS)
|
75
|
+
end
|
76
|
+
|
77
|
+
# :call-seq:
|
78
|
+
# store(object,opts={}) -> JiakObject or key
|
79
|
+
#
|
80
|
+
# Stores user-defined data (wrapped in a JiakObject) on the Jiak
|
81
|
+
# server. JiakData#to_jiak is used to prepare user-defined data for JSON
|
82
|
+
# transport to Jiak. That call is expected to return a Ruby hash
|
83
|
+
# representation of the writable JiakData fields that are JSONized for HTTP
|
84
|
+
# transport. Successful server writes return either the storage key or the
|
85
|
+
# stored JiakObject depending on the option <code>key</code>. The object
|
86
|
+
# for storage must be JiakObject. Valid options are:
|
87
|
+
#
|
88
|
+
# <code>:object</code> :: If <code>true</code>, on success return the stored JiakObject (which includes Jiak metadata); otherwise return just the key. Default is <code>false</code>, which returns the key.
|
89
|
+
# <code>:writes</code> :: The number of Riak nodes that must successfully store the data.
|
90
|
+
# <code>:durable_writes</code> :: The number of Riak nodes (<code>< writes</code>) that must successfully store the data in a durable manner.
|
91
|
+
# <code>:reads</code> :: The number of Riak nodes that must successfully read data if a JiakObject is being returned.
|
92
|
+
#
|
93
|
+
# If any of the request parameters <code>:writes, :durable_writes,
|
94
|
+
# :reads</code> are not set, each first defaults to the value set for the
|
95
|
+
# JiakBucket in the JiakObject, then to the value set on the Riak
|
96
|
+
# cluster. In general the values set on the Riak cluster should suffice.
|
97
|
+
#
|
98
|
+
# Raise JiakClientException if object not a JiakObject or illegal options
|
99
|
+
# are passed.<br/>
|
100
|
+
# Raise JiakResourceException on RESTful HTTP errors.
|
101
|
+
#
|
102
|
+
def store(jobj,opts={})
|
103
|
+
params = jobj.bucket.params
|
104
|
+
req_params = {
|
105
|
+
WRITES => opts[:writes] || params[:writes],
|
106
|
+
DURABLE_WRITES => opts[:durable_writes] || params[:durable_writes],
|
107
|
+
READS => opts[:reads] || params[:reads]
|
108
|
+
}
|
109
|
+
req_params[RETURN_BODY] = opts[:object] if opts[:object]
|
110
|
+
|
111
|
+
begin
|
112
|
+
uri = jiak_uri(jobj.bucket,jobj.key,req_params)
|
113
|
+
payload = jobj.to_jiak
|
114
|
+
headers = {
|
115
|
+
:content_type => APP_JSON,
|
116
|
+
:data_type => JSON_DATA,
|
117
|
+
:accept => APP_JSON }
|
118
|
+
# Decision tree:
|
119
|
+
# If key empty POST
|
120
|
+
# Else PUT
|
121
|
+
# If object true, return JiakObject
|
122
|
+
# Else
|
123
|
+
# POST - parse key from location header
|
124
|
+
# PUT - return the given key
|
125
|
+
key_empty = jobj.key.empty?
|
126
|
+
if(key_empty)
|
127
|
+
resp = RestClient.post(uri,payload,headers)
|
128
|
+
else
|
129
|
+
resp = RestClient.put(uri,payload,headers)
|
130
|
+
end
|
131
|
+
|
132
|
+
if(req_params[RETURN_BODY])
|
133
|
+
JiakObject.from_jiak(JSON.parse(resp),jobj.bucket.data_class)
|
134
|
+
elsif(key_empty)
|
135
|
+
resp.headers[:location].split('/').last
|
136
|
+
else
|
137
|
+
jobj.key
|
138
|
+
end
|
139
|
+
rescue RestClient::ExceptionWithResponse => err
|
140
|
+
fail_with_response("put", err)
|
141
|
+
rescue RestClient::Exception => err
|
142
|
+
fail_with_message("put", err)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
# :call-seq:
|
147
|
+
# get(bucket,key,opts={}) -> JiakObject
|
148
|
+
#
|
149
|
+
# Get data stored on a Jiak server at a bucket/key. The user-defined data
|
150
|
+
# stored on the Jiak server is inflated inside a JiakObject that also
|
151
|
+
# includes Riak storage information. Data inflation is controlled by the
|
152
|
+
# data class associated with the bucket of this call.
|
153
|
+
#
|
154
|
+
# Since the data schema validation that occurs on the Jiak server validates
|
155
|
+
# to the last schema set for that Jiak server bucket, it is imperative that
|
156
|
+
# schema be the same (or at least consistent) with the schema associated
|
157
|
+
# with this bucket at retrieval time. If you only store homogeneous objects
|
158
|
+
# in a bucket this will not be an issue.
|
159
|
+
#
|
160
|
+
# The bucket must be a JiakBucket and the key must be a non-empty
|
161
|
+
# String. Valid options are:
|
162
|
+
#
|
163
|
+
# <code>:reads</code> --- The number of Riak nodes that must successfully
|
164
|
+
# reply with the data. If not set, defaults first to the value set for the
|
165
|
+
# JiakBucket, then to the value set on the Riak cluster. In general the
|
166
|
+
# values set on the Riak cluster should suffice.
|
167
|
+
#
|
168
|
+
# Raise JiakClientException if bucket not a JiakBucket.<br/>
|
169
|
+
# Raise JiakResourceNotFound if resource not found on Jiak server.<br/>
|
170
|
+
# Raise JiakResourceException on other HTTP RESTful errors.
|
171
|
+
#
|
172
|
+
def get(bucket,key,opts={})
|
173
|
+
unless bucket.is_a?(JiakBucket)
|
174
|
+
raise JiakClientException, "Bucket must be a JiakBucket."
|
175
|
+
end
|
176
|
+
req_params = {READS => opts[:reads] || bucket.params[:reads]}
|
177
|
+
|
178
|
+
begin
|
179
|
+
uri = jiak_uri(bucket,key,req_params)
|
180
|
+
resp = RestClient.get(uri, :accept => APP_JSON)
|
181
|
+
JiakObject.from_jiak(JSON.parse(resp),bucket.data_class)
|
182
|
+
rescue RestClient::ResourceNotFound => err
|
183
|
+
raise JiakResourceNotFound, "failed get: #{err.message}"
|
184
|
+
rescue RestClient::ExceptionWithResponse => err
|
185
|
+
fail_with_response("get", err)
|
186
|
+
rescue RestClient::Exception => err
|
187
|
+
fail_with_message("get",err)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
# :call-seq:
|
192
|
+
# delete(bucket,key,opts={}) -> true or false
|
193
|
+
#
|
194
|
+
# Delete the JiakObject stored at the bucket/key. Valid options are:
|
195
|
+
#
|
196
|
+
# <code>:waits</code> --- The number of Riak nodes that must reply the
|
197
|
+
# delete has occurred before success. If not set, defaults first to the
|
198
|
+
# value set for the JiakBucket, then to the value set on the Riak
|
199
|
+
# cluster. In general the values set on the Riak cluster should suffice.
|
200
|
+
#
|
201
|
+
# Raise JiakResourceException on RESTful HTTP errors.
|
202
|
+
#
|
203
|
+
def delete(bucket,key,opts={})
|
204
|
+
begin
|
205
|
+
req_params = {RESPONSE_WAITS => opts[:waits] || bucket.params[:waits]}
|
206
|
+
uri = jiak_uri(bucket,key,req_params)
|
207
|
+
RestClient.delete(uri, :accept => APP_JSON)
|
208
|
+
true
|
209
|
+
rescue RestClient::ExceptionWithResponse => err
|
210
|
+
fail_with_response("delete", err)
|
211
|
+
rescue RestClient::Exception => err
|
212
|
+
fail_with_message("delete", err)
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
# :call-seq:
|
217
|
+
# walk(bucket,key,query,data_class) -> array
|
218
|
+
#
|
219
|
+
# Return an array of JiakObjects retrieved by walking a query links
|
220
|
+
# array starting with the links for the object at bucket/key. The
|
221
|
+
# data_class is used to inflate the data objects returned in the
|
222
|
+
# JiakObject array.
|
223
|
+
#
|
224
|
+
# See QueryLink for a description of the <code>query</code> structure.
|
225
|
+
def walk(bucket,key,query,data_class)
|
226
|
+
begin
|
227
|
+
start = jiak_uri(bucket,key)
|
228
|
+
case query
|
229
|
+
when QueryLink
|
230
|
+
uri = start+'/'+query.for_uri
|
231
|
+
when Array
|
232
|
+
uri = query.inject(start) {|build,link| build+'/'+link.for_uri}
|
233
|
+
else
|
234
|
+
raise QueryLinkException, 'failed: query must be '+
|
235
|
+
'a QueryLink or an Array of QueryLink objects'
|
236
|
+
end
|
237
|
+
resp = RestClient.get(uri, :accept => APP_JSON)
|
238
|
+
# JSON.parse(resp)['results'][0]
|
239
|
+
JSON.parse(resp)['results'][0].map do |jiak|
|
240
|
+
JiakObject.from_jiak(jiak,data_class)
|
241
|
+
end
|
242
|
+
rescue RestClient::ExceptionWithResponse => err
|
243
|
+
fail_with_response("put", err)
|
244
|
+
rescue RestClient::Exception => err
|
245
|
+
fail_with_message("put", err)
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
# :call-seq:
|
250
|
+
# client.uri -> string
|
251
|
+
#
|
252
|
+
# String representation of the base URI of the Jiak server.
|
253
|
+
def uri
|
254
|
+
@uri
|
255
|
+
end
|
256
|
+
|
257
|
+
# :call-seq:
|
258
|
+
# client == other -> true or false
|
259
|
+
#
|
260
|
+
# Equality -- JiakClients are equal if they have the same URI
|
261
|
+
def ==(other)
|
262
|
+
(@uri == other.uri) rescue false
|
263
|
+
end
|
264
|
+
|
265
|
+
# :call-seq:
|
266
|
+
# eql?(other) -> true or false
|
267
|
+
#
|
268
|
+
# Returns <code>true</code> if <code>other</code> is a JiakClint with the
|
269
|
+
# same URI.
|
270
|
+
def eql?(other)
|
271
|
+
other.is_a?(JiakClient) &&
|
272
|
+
@uri.eql?(other.uri)
|
273
|
+
end
|
274
|
+
|
275
|
+
def hash # :nodoc:
|
276
|
+
@uri.hash
|
277
|
+
end
|
278
|
+
|
279
|
+
# Build the URI for accessing the Jiak server.
|
280
|
+
def jiak_uri(bucket,key="",params={})
|
281
|
+
uri = "#{@uri}#{URI.encode(bucket.name)}"
|
282
|
+
uri += "/#{URI.encode(key)}" unless key.empty?
|
283
|
+
qstring = params.reject {|k,v| v.nil?}.map{|k,v| "#{k}=#{v}"}.join('&')
|
284
|
+
uri += "?#{URI.encode(qstring)}" unless qstring.empty?
|
285
|
+
uri
|
286
|
+
end
|
287
|
+
private :jiak_uri
|
288
|
+
|
289
|
+
# Get either the schema or keys for the bucket.
|
290
|
+
def bucket_info(bucket,info)
|
291
|
+
ignore = (info == SCHEMA) ? KEYS : SCHEMA
|
292
|
+
begin
|
293
|
+
uri = jiak_uri(bucket,"",{ignore => false})
|
294
|
+
JSON.parse(RestClient.get(uri, :accept => APP_JSON))[info]
|
295
|
+
rescue RestClient::ExceptionWithResponse => err
|
296
|
+
fail_with_response("get", err)
|
297
|
+
rescue RestClient::Exception => err
|
298
|
+
fail_with_message("get", err)
|
299
|
+
end
|
300
|
+
end
|
301
|
+
private :bucket_info
|
302
|
+
|
303
|
+
def fail_with_response(action,err)
|
304
|
+
raise( JiakResourceException,
|
305
|
+
"failed #{action}: HTTP code #{err.http_code}: #{err.http_body}")
|
306
|
+
end
|
307
|
+
private :fail_with_response
|
308
|
+
|
309
|
+
def fail_with_message(action,err)
|
310
|
+
raise JiakResourceException, "failed #{action}: #{err.message}"
|
311
|
+
end
|
312
|
+
private :fail_with_message
|
313
|
+
|
314
|
+
end
|
315
|
+
|
316
|
+
end
|