ripple 0.5.0
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/.document +5 -0
- data/.gitignore +26 -0
- data/LICENSE +13 -0
- data/README.textile +126 -0
- data/RELEASE_NOTES.textile +24 -0
- data/Rakefile +61 -0
- data/VERSION +1 -0
- data/lib/riak.rb +45 -0
- data/lib/riak/bucket.rb +105 -0
- data/lib/riak/client.rb +138 -0
- data/lib/riak/client/curb_backend.rb +63 -0
- data/lib/riak/client/http_backend.rb +209 -0
- data/lib/riak/client/net_http_backend.rb +49 -0
- data/lib/riak/failed_request.rb +37 -0
- data/lib/riak/i18n.rb +15 -0
- data/lib/riak/invalid_response.rb +25 -0
- data/lib/riak/link.rb +54 -0
- data/lib/riak/locale/en.yml +37 -0
- data/lib/riak/map_reduce.rb +240 -0
- data/lib/riak/map_reduce_error.rb +20 -0
- data/lib/riak/robject.rb +234 -0
- data/lib/riak/util/headers.rb +44 -0
- data/lib/riak/util/multipart.rb +52 -0
- data/lib/riak/util/translation.rb +29 -0
- data/lib/riak/walk_spec.rb +113 -0
- data/lib/ripple.rb +48 -0
- data/lib/ripple/core_ext/casting.rb +96 -0
- data/lib/ripple/document.rb +60 -0
- data/lib/ripple/document/attribute_methods.rb +111 -0
- data/lib/ripple/document/attribute_methods/dirty.rb +52 -0
- data/lib/ripple/document/attribute_methods/query.rb +49 -0
- data/lib/ripple/document/attribute_methods/read.rb +38 -0
- data/lib/ripple/document/attribute_methods/write.rb +36 -0
- data/lib/ripple/document/bucket_access.rb +38 -0
- data/lib/ripple/document/finders.rb +84 -0
- data/lib/ripple/document/persistence.rb +93 -0
- data/lib/ripple/document/persistence/callbacks.rb +48 -0
- data/lib/ripple/document/properties.rb +85 -0
- data/lib/ripple/document/validations.rb +44 -0
- data/lib/ripple/embedded_document.rb +38 -0
- data/lib/ripple/embedded_document/persistence.rb +46 -0
- data/lib/ripple/i18n.rb +15 -0
- data/lib/ripple/locale/en.yml +16 -0
- data/lib/ripple/property_type_mismatch.rb +23 -0
- data/lib/ripple/translation.rb +24 -0
- data/ripple.gemspec +159 -0
- data/spec/fixtures/cat.jpg +0 -0
- data/spec/fixtures/multipart-blank.txt +7 -0
- data/spec/fixtures/multipart-with-body.txt +16 -0
- data/spec/riak/bucket_spec.rb +141 -0
- data/spec/riak/client_spec.rb +169 -0
- data/spec/riak/curb_backend_spec.rb +50 -0
- data/spec/riak/headers_spec.rb +34 -0
- data/spec/riak/http_backend_spec.rb +136 -0
- data/spec/riak/link_spec.rb +50 -0
- data/spec/riak/map_reduce_spec.rb +347 -0
- data/spec/riak/multipart_spec.rb +36 -0
- data/spec/riak/net_http_backend_spec.rb +28 -0
- data/spec/riak/object_spec.rb +444 -0
- data/spec/riak/walk_spec_spec.rb +208 -0
- data/spec/ripple/attribute_methods_spec.rb +149 -0
- data/spec/ripple/bucket_access_spec.rb +48 -0
- data/spec/ripple/callbacks_spec.rb +86 -0
- data/spec/ripple/document_spec.rb +35 -0
- data/spec/ripple/embedded_document_spec.rb +52 -0
- data/spec/ripple/finders_spec.rb +146 -0
- data/spec/ripple/persistence_spec.rb +89 -0
- data/spec/ripple/properties_spec.rb +195 -0
- data/spec/ripple/ripple_spec.rb +43 -0
- data/spec/ripple/validations_spec.rb +64 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +32 -0
- data/spec/support/http_backend_implementation_examples.rb +215 -0
- data/spec/support/mock_server.rb +58 -0
- metadata +221 -0
@@ -0,0 +1,63 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
class Client
|
18
|
+
# An HTTP backend for Riak::Client that uses the 'curb' library/gem.
|
19
|
+
# If the 'curb' library is present, this backend will be preferred to
|
20
|
+
# the backend based on Net::HTTP.
|
21
|
+
# Conforms to the Riak::Client::HTTPBackend interface.
|
22
|
+
class CurbBackend < HTTPBackend
|
23
|
+
# @private
|
24
|
+
def initialize(client)
|
25
|
+
super
|
26
|
+
@curl = Curl::Easy.new
|
27
|
+
@curl.follow_location = false
|
28
|
+
@curl.on_header do |header_line|
|
29
|
+
@response_headers.parse(header_line)
|
30
|
+
header_line.size
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
def perform(method, uri, headers, expect, data=nil)
|
36
|
+
# Setup
|
37
|
+
@curl.headers = headers
|
38
|
+
@curl.url = uri.to_s
|
39
|
+
@response_headers = Riak::Util::Headers.new
|
40
|
+
@curl.on_body {|chunk| yield chunk; chunk.size } if block_given?
|
41
|
+
|
42
|
+
# Perform
|
43
|
+
case method
|
44
|
+
when :put, :post
|
45
|
+
@curl.send("http_#{method}", data)
|
46
|
+
else
|
47
|
+
@curl.send("http_#{method}")
|
48
|
+
end
|
49
|
+
|
50
|
+
# Verify
|
51
|
+
if valid_response?(expect, @curl.response_code)
|
52
|
+
result = { :headers => @response_headers.to_hash, :code => @curl.response_code.to_i }
|
53
|
+
if return_body?(method, @curl.response_code, block_given?)
|
54
|
+
result[:body] = @curl.body_str
|
55
|
+
end
|
56
|
+
result
|
57
|
+
else
|
58
|
+
raise FailedRequest.new(method, expect, @curl.response_code, @response_headers.to_hash, @curl.body_str)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,209 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
class Client
|
18
|
+
class HTTPBackend
|
19
|
+
include Util::Translation
|
20
|
+
# The Riak::Client that uses this backend
|
21
|
+
attr_reader :client
|
22
|
+
|
23
|
+
# Create an HTTPBackend for the Riak::Client.
|
24
|
+
# @param [Client] client the client
|
25
|
+
def initialize(client)
|
26
|
+
raise ArgumentError, t("client_type", :client => client) unless Client === client
|
27
|
+
@client = client
|
28
|
+
end
|
29
|
+
|
30
|
+
# Default header hash sent with every request, based on settings in the client
|
31
|
+
# @return [Hash] headers that will be merged with user-specified headers on every request
|
32
|
+
def default_headers
|
33
|
+
{
|
34
|
+
"Accept" => "multipart/mixed, application/json;q=0.7, */*;q=0.5",
|
35
|
+
"X-Riak-ClientId" => @client.client_id
|
36
|
+
}
|
37
|
+
end
|
38
|
+
|
39
|
+
# Performs a HEAD request to the specified resource on the Riak server.
|
40
|
+
# @param [Fixnum, Array] expect the expected HTTP response code(s) from Riak
|
41
|
+
# @param [String, Array<String,Hash>] resource a relative path or array of path segments and optional query params Hash that will be joined to the root URI
|
42
|
+
# @overload head(expect, *resource)
|
43
|
+
# @overload head(expect, *resource, headers)
|
44
|
+
# Send the request with custom headers
|
45
|
+
# @param [Hash] headers custom headers to send with the request
|
46
|
+
# @return [Hash] response data, containing only the :headers and :code keys
|
47
|
+
# @raise [FailedRequest] if the response code doesn't match the expected response
|
48
|
+
def head(expect, *resource)
|
49
|
+
headers = default_headers.merge(resource.extract_options!)
|
50
|
+
verify_path!(resource)
|
51
|
+
perform(:head, path(*resource), headers, expect)
|
52
|
+
end
|
53
|
+
|
54
|
+
# Performs a GET request to the specified resource on the Riak server.
|
55
|
+
# @param [Fixnum, Array] expect the expected HTTP response code(s) from Riak
|
56
|
+
# @param [String, Array<String,Hash>] resource a relative path or array of path segments and optional query params Hash that will be joined to the root URI
|
57
|
+
# @overload get(expect, *resource)
|
58
|
+
# @overload get(expect, *resource, headers)
|
59
|
+
# Send the request with custom headers
|
60
|
+
# @param [Hash] headers custom headers to send with the request
|
61
|
+
# @overload get(expect, *resource, headers={})
|
62
|
+
# Stream the response body through the supplied block
|
63
|
+
# @param [Hash] headers custom headers to send with the request
|
64
|
+
# @yield [chunk] yields successive chunks of the response body as strings
|
65
|
+
# @return [Hash] response data, containing only the :headers and :code keys
|
66
|
+
# @return [Hash] response data, containing :headers, :body, and :code keys
|
67
|
+
# @raise [FailedRequest] if the response code doesn't match the expected response
|
68
|
+
def get(expect, *resource, &block)
|
69
|
+
headers = default_headers.merge(resource.extract_options!)
|
70
|
+
verify_path!(resource)
|
71
|
+
perform(:get, path(*resource), headers, expect, &block)
|
72
|
+
end
|
73
|
+
|
74
|
+
# Performs a PUT request to the specified resource on the Riak server.
|
75
|
+
# @param [Fixnum, Array] expect the expected HTTP response code(s) from Riak
|
76
|
+
# @param [String, Array<String,Hash>] resource a relative path or array of path segments and optional query params Hash that will be joined to the root URI
|
77
|
+
# @param [String] body the request body to send to the server
|
78
|
+
# @overload put(expect, *resource, body)
|
79
|
+
# @overload put(expect, *resource, body, headers)
|
80
|
+
# Send the request with custom headers
|
81
|
+
# @param [Hash] headers custom headers to send with the request
|
82
|
+
# @overload put(expect, *resource, body, headers={})
|
83
|
+
# Stream the response body through the supplied block
|
84
|
+
# @param [Hash] headers custom headers to send with the request
|
85
|
+
# @yield [chunk] yields successive chunks of the response body as strings
|
86
|
+
# @return [Hash] response data, containing only the :headers and :code keys
|
87
|
+
# @return [Hash] response data, containing :headers, :code, and :body keys
|
88
|
+
# @raise [FailedRequest] if the response code doesn't match the expected response
|
89
|
+
def put(expect, *resource, &block)
|
90
|
+
headers = default_headers.merge(resource.extract_options!)
|
91
|
+
uri, data = verify_path_and_body!(resource)
|
92
|
+
perform(:put, path(*uri), headers, expect, data, &block)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Performs a POST request to the specified resource on the Riak server.
|
96
|
+
# @param [Fixnum, Array] expect the expected HTTP response code(s) from Riak
|
97
|
+
# @param [String, Array<String>] resource a relative path or array of path segments that will be joined to the root URI
|
98
|
+
# @param [String] body the request body to send to the server
|
99
|
+
# @overload post(expect, *resource, body)
|
100
|
+
# @overload post(expect, *resource, body, headers)
|
101
|
+
# Send the request with custom headers
|
102
|
+
# @param [Hash] headers custom headers to send with the request
|
103
|
+
# @overload post(expect, *resource, body, headers={})
|
104
|
+
# Stream the response body through the supplied block
|
105
|
+
# @param [Hash] headers custom headers to send with the request
|
106
|
+
# @yield [chunk] yields successive chunks of the response body as strings
|
107
|
+
# @return [Hash] response data, containing only the :headers and :code keys
|
108
|
+
# @return [Hash] response data, containing :headers, :code and :body keys
|
109
|
+
# @raise [FailedRequest] if the response code doesn't match the expected response
|
110
|
+
def post(expect, *resource, &block)
|
111
|
+
headers = default_headers.merge(resource.extract_options!)
|
112
|
+
uri, data = verify_path_and_body!(resource)
|
113
|
+
perform(:post, path(*uri), headers, expect, data, &block)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Performs a DELETE request to the specified resource on the Riak server.
|
117
|
+
# @param [Fixnum, Array] expect the expected HTTP response code(s) from Riak
|
118
|
+
# @param [String, Array<String,Hash>] resource a relative path or array of path segments and optional query params Hash that will be joined to the root URI
|
119
|
+
# @overload delete(expect, *resource)
|
120
|
+
# @overload delete(expect, *resource, headers)
|
121
|
+
# Send the request with custom headers
|
122
|
+
# @param [Hash] headers custom headers to send with the request
|
123
|
+
# @overload delete(expect, *resource, headers={})
|
124
|
+
# Stream the response body through the supplied block
|
125
|
+
# @param [Hash] headers custom headers to send with the request
|
126
|
+
# @yield [chunk] yields successive chunks of the response body as strings
|
127
|
+
# @return [Hash] response data, containing only the :headers and :code keys
|
128
|
+
# @return [Hash] response data, containing :headers, :code and :body keys
|
129
|
+
# @raise [FailedRequest] if the response code doesn't match the expected response
|
130
|
+
def delete(expect, *resource, &block)
|
131
|
+
headers = default_headers.merge(resource.extract_options!)
|
132
|
+
verify_path!(resource)
|
133
|
+
perform(:delete, path(*resource), headers, expect, &block)
|
134
|
+
end
|
135
|
+
|
136
|
+
# @return [URI] The calculated root URI for the Riak HTTP endpoint
|
137
|
+
def root_uri
|
138
|
+
URI.parse("http://#{@client.host}:#{@client.port}")
|
139
|
+
end
|
140
|
+
|
141
|
+
# Calculates an absolute URI from a relative path specification
|
142
|
+
# @param [Array<String,Hash>] segments a relative path or sequence of path segments and optional query params Hash that will be joined to the root URI
|
143
|
+
# @return [URI] an absolute URI for the resource
|
144
|
+
def path(*segments)
|
145
|
+
query = segments.extract_options!.to_param
|
146
|
+
root_uri.merge(URI.escape(segments.join("/").gsub(/\/+/, "/").sub(/^\//, ''))).tap do |uri|
|
147
|
+
uri.query = query if query.present?
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
# Verifies that both a resource path and body are present in the arguments
|
152
|
+
# @param [Array] args the arguments to verify
|
153
|
+
# @raise [ArgumentError] if the body or resource is missing, or if the body is not a String
|
154
|
+
def verify_path_and_body!(args)
|
155
|
+
body = args.pop
|
156
|
+
begin
|
157
|
+
verify_path!(args)
|
158
|
+
rescue ArgumentError
|
159
|
+
raise ArgumentError, t("path_and_body_required")
|
160
|
+
end
|
161
|
+
|
162
|
+
raise ArgumentError, t("request_body_type") unless String === body || IO === body
|
163
|
+
[args, body]
|
164
|
+
end
|
165
|
+
|
166
|
+
# Verifies that the specified resource is valid
|
167
|
+
# @param [String, Array] resource the resource specification
|
168
|
+
# @raise [ArgumentError] if the resource path is too short
|
169
|
+
def verify_path!(resource)
|
170
|
+
resource = Array(resource).flatten
|
171
|
+
raise ArgumentError, t("resource_path_short") unless resource.length > 1 || resource.include?(@client.mapred)
|
172
|
+
end
|
173
|
+
|
174
|
+
# Checks the expected response codes against the actual response code. Use internally when
|
175
|
+
# implementing {#perform}.
|
176
|
+
# @param [String, Fixnum, Array<String,Fixnum>] expected the expected response code(s)
|
177
|
+
# @param [String, Fixnum] actual the received response code
|
178
|
+
# @return [Boolean] whether the actual response code is acceptable given the expectations
|
179
|
+
def valid_response?(expected, actual)
|
180
|
+
Array(expected).map(&:to_i).include?(actual.to_i)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Checks whether a combination of the HTTP method, response code, and block should
|
184
|
+
# result in returning the :body in the response hash. Use internally when implementing {#perform}.
|
185
|
+
# @param [Symbol] method the HTTP method
|
186
|
+
# @param [String, Fixnum] code the received response code
|
187
|
+
# @param [Boolean] has_block whether a streaming block was passed to {#perform}. Pass block_given? to this parameter.
|
188
|
+
# @return [Boolean] whether to return the body in the response hash
|
189
|
+
def return_body?(method, code, has_block)
|
190
|
+
method != :head && !valid_response?([204,205,304], code) && !has_block
|
191
|
+
end
|
192
|
+
|
193
|
+
# Executes requests according to the underlying HTTP client library semantics.
|
194
|
+
# @abstract Subclasses must implement this internal method to perform HTTP requests
|
195
|
+
# according to the API of their HTTP libraries.
|
196
|
+
# @param [Symbol] method one of :head, :get, :post, :put, :delete
|
197
|
+
# @param [URI] uri the HTTP URI to request
|
198
|
+
# @param [Hash] headers headers to send along with the request
|
199
|
+
# @param [Fixnum, Array] expect the expected response code(s)
|
200
|
+
# @param [String, IO] body the PUT or POST request body
|
201
|
+
# @return [Hash] response data, containing :headers, :code and :body keys. Only :headers and :code should be present when the body is streamed or the method is :head.
|
202
|
+
# @yield [chunk] if the method is not :head, successive chunks of the response body will be yielded as strings
|
203
|
+
# @raise [NotImplementedError] if a subclass does not implement this method
|
204
|
+
def perform(method, uri, headers, expect, body=nil)
|
205
|
+
raise NotImplementedError
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
class Client
|
18
|
+
# Uses the Ruby standard library Net::HTTP to connect to Riak.
|
19
|
+
# We recommend using the CurbBackend, which will
|
20
|
+
# be preferred when the 'curb' library is available.
|
21
|
+
# Conforms to the Riak::Client::HTTPBackend interface.
|
22
|
+
class NetHTTPBackend < HTTPBackend
|
23
|
+
private
|
24
|
+
def perform(method, uri, headers, expect, data=nil) #:nodoc:
|
25
|
+
Net::HTTP.start(uri.host, uri.port) do |http|
|
26
|
+
request = Net::HTTP.const_get(method.to_s.camelize).new(uri.request_uri, headers)
|
27
|
+
case data
|
28
|
+
when String
|
29
|
+
request.body = data
|
30
|
+
when IO
|
31
|
+
request.body_stream = data
|
32
|
+
end
|
33
|
+
response = http.request(request)
|
34
|
+
|
35
|
+
if valid_response?(expect, response.code)
|
36
|
+
result = {:headers => response.to_hash, :code => response.code.to_i}
|
37
|
+
response.read_body {|chunk| yield chunk } if block_given?
|
38
|
+
if return_body?(method, response.code, block_given?)
|
39
|
+
result[:body] = response.body
|
40
|
+
end
|
41
|
+
result
|
42
|
+
else
|
43
|
+
raise FailedRequest.new(method, expect, response.code, response.to_hash, response.body)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
# Exception raised when the expected response code from Riak
|
18
|
+
# fails to match the actual response code.
|
19
|
+
class FailedRequest < StandardError
|
20
|
+
include Util::Translation
|
21
|
+
# @return [Symbol] the HTTP method, one of :head, :get, :post, :put, :delete
|
22
|
+
attr_reader :method
|
23
|
+
# @return [Fixnum] the expected response code
|
24
|
+
attr_reader :expected
|
25
|
+
# @return [Fixnum] the received response code
|
26
|
+
attr_reader :code
|
27
|
+
# @return [Hash] the response headers
|
28
|
+
attr_reader :headers
|
29
|
+
# @return [String] the response body, if present
|
30
|
+
attr_reader :body
|
31
|
+
|
32
|
+
def initialize(method, expected_code, received_code, headers, body)
|
33
|
+
@method, @expected, @code, @headers, @body = method, expected_code, received_code, headers, body
|
34
|
+
super t("failed_request", :expected => @expected.inspect, :code => @code, :body => @body)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/lib/riak/i18n.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'active_support/i18n'
|
15
|
+
I18n.load_path << File.expand_path("../locale/en.yml", __FILE__)
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
# Raised when Riak returns a response that is in an unexpected format
|
18
|
+
class InvalidResponse < StandardError
|
19
|
+
def initialize(expected, received, extra="")
|
20
|
+
expected = expected.inspect if Hash === expected
|
21
|
+
received = received.inspect if Hash === received
|
22
|
+
super "Expected #{expected} but received #{received} from Riak #{extra}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/riak/link.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
require 'riak'
|
15
|
+
|
16
|
+
module Riak
|
17
|
+
# Represents a link from one object to another in Riak
|
18
|
+
class Link
|
19
|
+
include Util::Translation
|
20
|
+
# @return [String] the URL (relative or absolute) of the related resource
|
21
|
+
attr_accessor :url
|
22
|
+
|
23
|
+
# @return [String] the relationship ("rel") of the other resource to this one
|
24
|
+
attr_accessor :rel
|
25
|
+
|
26
|
+
# @param [String] header_string the string value of the Link: HTTP header from a Riak response
|
27
|
+
# @return [Array<Link>] an array of Riak::Link structs parsed from the header
|
28
|
+
def self.parse(header_string)
|
29
|
+
header_string.scan(%r{<([^>]+)>\s*;\s*(?:rel|riaktag)=\"([^\"]+)\"}).map do |match|
|
30
|
+
new(match[0], match[1])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(url, rel)
|
35
|
+
@url, @rel = url, rel
|
36
|
+
end
|
37
|
+
|
38
|
+
def inspect; to_s; end
|
39
|
+
|
40
|
+
def to_s
|
41
|
+
%Q[<#{@url}>; riaktag="#{@rel}"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def ==(other)
|
45
|
+
other.is_a?(Link) && url == other.url && rel == other.rel
|
46
|
+
end
|
47
|
+
|
48
|
+
def to_walk_spec
|
49
|
+
bucket, object = $1, $2 if @url =~ %r{/raw/([^/]+)/([^/]+)/?}
|
50
|
+
raise t("bucket_link_conversion") if @rel == "up" || object.nil?
|
51
|
+
WalkSpec.new(:bucket => bucket, :tag => @rel)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|