riak-client 0.7.1 → 0.8.0.beta

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/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ # A sample Gemfile
2
+ source :gemcutter
3
+
4
+ gem 'activesupport', '~>2.3.5' # '3.0.0.rc'
5
+ gem 'i18n'
6
+
7
+ gem 'rspec', "~>2.0.0.beta.18"
8
+ gem 'fakeweb', ">=1.2"
9
+ gem 'rack', '>=1.0'
10
+ gem 'curb', '>=0.6'
11
+ gem 'yajl-ruby'
12
+ gem 'rake'
13
+ gem 'bundler'
@@ -0,0 +1,33 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ activesupport (2.3.8)
5
+ curb (0.7.8)
6
+ diff-lcs (1.1.2)
7
+ fakeweb (1.3.0)
8
+ i18n (0.4.1)
9
+ rack (1.2.1)
10
+ rake (0.8.7)
11
+ rspec (2.0.0.beta.20)
12
+ rspec-core (= 2.0.0.beta.20)
13
+ rspec-expectations (= 2.0.0.beta.20)
14
+ rspec-mocks (= 2.0.0.beta.20)
15
+ rspec-core (2.0.0.beta.20)
16
+ rspec-expectations (2.0.0.beta.20)
17
+ diff-lcs (>= 1.1.2)
18
+ rspec-mocks (2.0.0.beta.20)
19
+ yajl-ruby (0.7.7)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ activesupport (~> 2.3.5)
26
+ bundler
27
+ curb (>= 0.6)
28
+ fakeweb (>= 1.2)
29
+ i18n
30
+ rack (>= 1.0)
31
+ rake
32
+ rspec (~> 2.0.0.beta.18)
33
+ yajl-ruby
data/Rakefile CHANGED
@@ -9,11 +9,12 @@ gemspec = Gem::Specification.new do |gem|
9
9
  gem.email = "seancribbs@gmail.com"
10
10
  gem.homepage = "http://seancribbs.github.com/ripple"
11
11
  gem.authors = ["Sean Cribbs"]
12
- gem.add_development_dependency "rspec", "~>2.0.0.beta.6"
12
+ gem.add_development_dependency "rspec", "~>2.0.0.beta.11"
13
13
  gem.add_development_dependency "fakeweb", ">=1.2"
14
14
  gem.add_development_dependency "rack", ">=1.0"
15
15
  gem.add_development_dependency "curb", ">=0.6"
16
16
  gem.add_dependency "activesupport", ">= 2.3.5"
17
+ gem.add_dependency "i18n", "~>0.4.0"
17
18
  gem.requirements << "`gem install curb` for better HTTP performance"
18
19
 
19
20
  files = FileList["**/*"]
@@ -48,7 +49,7 @@ end
48
49
 
49
50
  desc %{Release the gem to RubyGems.org}
50
51
  task :release => :gem do
51
- "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
52
+ system "gem push pkg/#{gemspec.name}-#{gemspec.version}.gem"
52
53
  end
53
54
 
54
55
  require 'rspec/core'
@@ -15,8 +15,10 @@ $KCODE = "UTF8" if RUBY_VERSION < "1.9"
15
15
 
16
16
  require 'active_support/all'
17
17
  require 'active_support/json'
18
+ require 'active_support/version'
18
19
  require 'base64'
19
20
  require 'uri'
21
+ require 'cgi'
20
22
  require 'net/http'
21
23
  require 'yaml'
22
24
  require 'riak/i18n'
@@ -32,8 +34,11 @@ module Riak
32
34
  autoload :RObject, "riak/robject"
33
35
  autoload :MapReduce, "riak/map_reduce"
34
36
 
35
- # Cache store
36
- autoload :CacheStore, "riak/cache_store"
37
+ # Cache store - only supports Rails 3 style
38
+ if ActiveSupport::VERSION::STRING >= "3.0.0"
39
+ autoload :CacheStore, "riak/cache_store"
40
+ ::ActiveSupport::Cache.autoload :RiakStore, "riak/cache_store"
41
+ end
37
42
 
38
43
  # Exceptions
39
44
  autoload :FailedRequest, "riak/failed_request"
@@ -26,10 +26,6 @@ module Riak
26
26
  # @return [String] the bucket name
27
27
  attr_reader :name
28
28
 
29
- # @return [Hash] Internal Riak bucket properties.
30
- attr_reader :props
31
- alias_attribute :properties, :props
32
-
33
29
  # Create a Riak bucket manually.
34
30
  # @param [Client] client the {Riak::Client} for this bucket
35
31
  # @param [String] name the name of the bucket
@@ -49,7 +45,7 @@ module Riak
49
45
  raise Riak::InvalidResponse.new({"content-type" => ["application/json"]}, response[:headers], t("loading_bucket", :name => name))
50
46
  end
51
47
  payload = ActiveSupport::JSON.decode(response[:body])
52
- @keys = payload['keys'].map {|k| URI.unescape(k) } if payload['keys']
48
+ @keys = payload['keys'].map {|k| CGI.unescape(k) } if payload['keys']
53
49
  @props = payload['props'] if payload['props']
54
50
  self
55
51
  end
@@ -66,26 +62,48 @@ module Riak
66
62
  if block_given?
67
63
  @client.http.get(200, @client.prefix, escape(name), {:props => false, :keys => 'stream'}, {}) do |chunk|
68
64
  obj = ActiveSupport::JSON.decode(chunk) rescue {}
69
- yield obj['keys'].map {|k| URI.unescape(k) } if obj['keys']
65
+ yield obj['keys'].map {|k| CGI.unescape(k) } if obj['keys']
70
66
  end
71
67
  elsif @keys.nil? || options[:reload]
72
- response = @client.http.get(200, @client.prefix, escape(name), {:props => false}, {})
68
+ response = @client.http.get(200, @client.prefix, escape(name), {:props => false, :keys => true}, {})
73
69
  load(response)
74
70
  end
75
71
  @keys
76
72
  end
77
73
 
74
+
78
75
  # Sets internal properties on the bucket
79
76
  # Note: this results in a request to the Riak server!
80
77
  # @param [Hash] properties new properties for the bucket
81
- # @return [Hash] the properties that were accepted
82
- # @raise [FailedRequest] if the new properties were not accepted by the Riak server
78
+ # @option properties [Fixnum] :n_val (3) The N value (replication factor)
79
+ # @option properties [true,false] :allow_mult (false) Whether to permit object siblings
80
+ # @option properties [true,false] :last_write_wins (false) Whether to ignore vclocks
81
+ # @option properties [Array<Hash>] :precommit ([]) precommit hooks
82
+ # @option properties [Array<Hash>] :postcommit ([])postcommit hooks
83
+ # @option properties [Fixnum,String] :r ("quorum") read quorum (numeric or
84
+ # symbolic)
85
+ # @option properties [Fixnum,String] :w ("quorum") write quorum (numeric or
86
+ # symbolic)
87
+ # @option properties [Fixnum,String] :dw ("quorum") durable write quorum
88
+ # (numeric or symbolic)
89
+ # @option properties [Fixnum,String] :rw ("quorum") delete quorum (numeric or
90
+ # symbolic)
91
+ # @return [Hash] the merged bucket properties
92
+ # @raise [FailedRequest] if the new properties were not accepted by the Riakserver
93
+ # @see #n_value, #allow_mult, #r, #w, #dw, #rw
83
94
  def props=(properties)
84
95
  raise ArgumentError, t("hash_type", :hash => properties.inspect) unless Hash === properties
85
96
  body = {'props' => properties}.to_json
86
97
  @client.http.put(204, @client.prefix, escape(name), body, {"Content-Type" => "application/json"})
87
- @props = properties
98
+ @props.merge!(properties)
99
+ end
100
+
101
+ # @return [Hash] Internal Riak bucket properties.
102
+ # @see #props=
103
+ def props
104
+ @props
88
105
  end
106
+ alias_attribute :properties, :props
89
107
 
90
108
  # Retrieve an object from within the bucket.
91
109
  # @param [String] key the key of the object to retrieve
@@ -168,9 +186,22 @@ module Riak
168
186
  value
169
187
  end
170
188
 
171
- # @return [String] a representation suitable for IRB and debugging output
172
- def inspect
173
- "#<Riak::Bucket #{client.http.path(client.prefix, escape(name)).to_s}#{" keys=[#{keys.join(',')}]" if defined?(@keys)}>"
189
+ [:r,:w,:dw,:rw].each do |q|
190
+ class_eval <<-CODE
191
+ def #{q}
192
+ props["#{q}"]
193
+ end
194
+
195
+ def #{q}=(value)
196
+ self.props = {"#{q}" => value}
197
+ value
198
+ end
199
+ CODE
200
+ end
201
+
202
+ # @return [String] a representation suitable for IRB and debugging output
203
+ def inspect
204
+ "#<Riak::Bucket #{client.http.path(client.prefix, escape(name)).to_s}#{" keys=[#{keys.join(',')}]" if defined?(@keys)}>"
205
+ end
174
206
  end
175
207
  end
176
- end
@@ -19,63 +19,61 @@ module Riak
19
19
  def initialize(options = {})
20
20
  @bucket_name = options.delete(:bucket) || '_cache'
21
21
  @n_value = options.delete(:n_value) || 2
22
- @r = [options.delete(:r) || 1, @n_value].min
23
- @w = [options.delete(:w) || 1, @n_value].min
24
- @dw = [options.delete(:dw) || 0, @n_value].min
25
- @rw = [options.delete(:rw) || 1, @n_value].min
22
+ @r = options.delete(:r) || 1
23
+ @w = options.delete(:w) || 1
24
+ @dw = options.delete(:dw) || 0
25
+ @rw = options.delete(:rw) || "quorum"
26
26
  @client = Riak::Client.new(options)
27
+ set_bucket_defaults
27
28
  end
28
29
 
29
30
  def bucket
30
- @bucket ||= @client.bucket(@bucket_name, :keys => false).tap do |b|
31
- begin
32
- b.n_value = @n_value unless b.n_value == @n_value
33
- rescue
34
- end
35
- end
36
- end
37
-
38
- def write(key, value, options={})
39
- super do
40
- object = bucket.get_or_new(key, :r => @r)
41
- object.content_type = 'application/yaml'
42
- object.data = value
43
- object.store(:r => @r, :w => @w, :dw => @dw)
44
- end
31
+ @bucket ||= @client.bucket(@bucket_name, :keys => false)
45
32
  end
46
33
 
47
- def read(key, options={})
48
- super do
49
- begin
50
- bucket.get(key, :r => @r).data
51
- rescue Riak::FailedRequest => fr
52
- raise fr unless fr.code == 404
53
- nil
34
+ def delete_matched(matcher, options={})
35
+ instrument(:delete_matched, matcher) do
36
+ bucket.keys do |keys|
37
+ keys.grep(matcher).each do |k|
38
+ bucket.delete(k)
39
+ end
54
40
  end
55
41
  end
56
42
  end
57
43
 
58
- def exist?(key)
59
- super do
60
- bucket.exists?(key, :r => @r)
44
+ protected
45
+ def set_bucket_defaults
46
+ begin
47
+ new_values = {}
48
+ new_values['n_val'] = @n_value unless bucket.n_value == @n_value
49
+ new_values['r'] = @r unless bucket.r == @r
50
+ new_values['w'] = @w unless bucket.w == @w
51
+ new_values['dw'] = @dw unless bucket.dw == @dw
52
+ new_values['rw'] = @rw unless bucket.rw == @rw
53
+ bucket.props = new_values unless new_values.empty?
54
+ rescue
61
55
  end
62
56
  end
63
57
 
64
- def delete_matched(matcher, options={})
65
- super do
66
- bucket.keys do |keys|
67
- keys.grep(matcher).each do |k|
68
- bucket.delete(k, :rw => @rw)
69
- end
70
- end
71
- end
58
+ def write_entry(key, value, options={})
59
+ object = bucket.get_or_new(key)
60
+ object.content_type = 'application/yaml'
61
+ object.data = value
62
+ object.store
72
63
  end
73
64
 
74
- def delete(key, options={})
75
- super do
76
- bucket.delete(key, :rw => @rw)
65
+ def read_entry(key, options={})
66
+ begin
67
+ bucket.get(key).data
68
+ rescue Riak::FailedRequest => fr
69
+ raise fr unless fr.code == 404
70
+ nil
77
71
  end
78
72
  end
73
+
74
+ def delete_entry(key, options={})
75
+ bucket.delete(key)
76
+ end
79
77
  end
80
78
  end
81
79
 
@@ -117,7 +117,7 @@ module Riak
117
117
  # @return [Bucket] the requested bucket
118
118
  def bucket(name, options={})
119
119
  options.assert_valid_keys(:keys, :props)
120
- response = http.get(200, prefix, escape(name), options, {})
120
+ response = http.get(200, prefix, escape(name), {:keys => false}.merge(options), {})
121
121
  Bucket.new(self, name).load(response)
122
122
  end
123
123
  alias :[] :bucket
@@ -11,9 +11,9 @@
11
11
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
- begin
14
+ if ActiveSupport::VERSION::STRING >= "3.0"
15
15
  require 'active_support/i18n'
16
- rescue LoadError
16
+ else
17
17
  require 'i18n' # support ActiveSupport < 3
18
18
  end
19
19
 
@@ -39,12 +39,12 @@ module Riak
39
39
 
40
40
  # @return [String] bucket_name, if the Link url is a known Riak link ("/riak/<bucket>/<key>")
41
41
  def bucket
42
- URI.unescape($1) if url =~ %r{^/[^/]+/([^/]+)/?}
42
+ CGI.unescape($1) if url =~ %r{^/[^/]+/([^/]+)/?}
43
43
  end
44
44
 
45
45
  # @return [String] key, if the Link url is a known Riak link ("/riak/<bucket>/<key>")
46
46
  def key
47
- URI.unescape($1) if url =~ %r{^/[^/]+/[^/]+/([^/]+)/?}
47
+ CGI.unescape($1) if url =~ %r{^/[^/]+/[^/]+/([^/]+)/?}
48
48
  end
49
49
 
50
50
  def inspect; to_s; end
@@ -13,25 +13,25 @@
13
13
  # limitations under the License.
14
14
  en:
15
15
  riak:
16
- client_type: "invalid argument {{client}} is not a Riak::Client"
17
- string_type: "invalid_argument {{string}} is not a String"
18
- loading_bucket: "while loading bucket '{{name}}'"
19
- failed_request: "Expected {{expected}} from Riak but received {{code}}. {{body}}"
20
- hash_type: "invalid argument {{hash}} is not a Hash"
21
- path_and_body_required: "You must supply both a resource path and a body."
22
- request_body_type: "Request body must be a string or IO."
23
- resource_path_short: "Resource path too short"
24
- missing_host_and_port: "You must specify a host and port, or use the defaults of 127.0.0.1:8098"
25
- invalid_client_id: "Invalid client ID, must be a string or between 0 and {{max_id}}"
16
+ bucket_link_conversion: "Can't convert a bucket link to a walk spec"
17
+ client_type: "invalid argument %{client} is not a Riak::Client"
18
+ content_type_undefined: "content_type is not defined!"
19
+ failed_request: "Expected %{expected} from Riak but received %{code}. %{body}"
20
+ hash_type: "invalid argument %{hash} is not a Hash"
26
21
  hostname_invalid: "host must be a valid hostname"
27
- port_invalid: "port must be an integer between 0 and 65535"
28
22
  install_curb: "curb library not found! Please `gem install curb` for better performance."
29
- bucket_link_conversion: "Can't convert a bucket link to a walk spec"
23
+ invalid_client_id: "Invalid client ID, must be a string or between 0 and %{max_id}"
24
+ invalid_function_value: "invalid value for function: %{value}"
30
25
  invalid_phase_type: "type must be :map, :reduce, or :link"
26
+ loading_bucket: "while loading bucket '%{name}'"
27
+ missing_host_and_port: "You must specify a host and port, or use the defaults of 127.0.0.1:8098"
31
28
  module_function_pair_required: "function must have two elements when an array"
29
+ path_and_body_required: "You must supply both a resource path and a body."
30
+ port_invalid: "port must be an integer between 0 and 65535"
31
+ request_body_type: "Request body must be a string or IO."
32
+ resource_path_short: "Resource path too short"
32
33
  stored_function_invalid: "function must have :bucket and :key when a hash"
34
+ string_type: "invalid_argument %{string} is not a String"
35
+ too_few_arguments: "too few arguments: %{params}"
33
36
  walk_spec_invalid_unless_link: "WalkSpec is only valid for a function when the type is :link"
34
- invalid_function_value: "invalid value for function: {{value}}"
35
- content_type_undefined: "content_type is not defined!"
36
- too_few_arguments: "too few arguments: {{params}}"
37
- wrong_argument_count_walk_spec: "wrong number of arguments (one Hash or bucket,tag,keep required)"
37
+ wrong_argument_count_walk_spec: "wrong number of arguments (one Hash or bucket,tag,keep required)"
@@ -17,6 +17,8 @@ module Riak
17
17
  # Class for invoking map-reduce jobs using the HTTP interface.
18
18
  class MapReduce
19
19
  include Util::Translation
20
+ include Util::Escape
21
+
20
22
  # @return [Array<[bucket,key]>,String] The bucket/keys for input to the job, or the bucket (all keys).
21
23
  # @see #add
22
24
  attr_accessor :inputs
@@ -58,16 +60,17 @@ module Riak
58
60
  p = params.first
59
61
  case p
60
62
  when Bucket
61
- @inputs = p.name
63
+ @inputs = escape(p.name)
62
64
  when RObject
63
- @inputs << [p.bucket.name, p.key]
65
+ @inputs << [escape(p.bucket.name), escape(p.key)]
64
66
  when String
65
- @inputs = p
67
+ @inputs = escape(p)
66
68
  end
67
69
  when 2..3
68
70
  bucket = params.shift
69
71
  bucket = bucket.name if Bucket === bucket
70
- @inputs << params.unshift(bucket)
72
+ key = params.shift
73
+ @inputs << params.unshift(escape(key)).unshift(escape(bucket))
71
74
  end
72
75
  self
73
76
  end
@@ -38,7 +38,7 @@ module Riak
38
38
  # @return [Object] the data stored in Riak at this object's key. Varies in format by content-type, defaulting to String from the response body.
39
39
  attr_accessor :data
40
40
 
41
- # @return [Set<Link>] an Set of {Riak::Link} objects for relationships between this object and other resources
41
+ # @return [Set<Link>] a Set of {Riak::Link} objects for relationships between this object and other resources
42
42
  attr_accessor :links
43
43
 
44
44
  # @return [String] the ETag header from the most recent HTTP response, useful for caching and reloading
@@ -50,6 +50,19 @@ module Riak
50
50
  # @return [Hash] a hash of any X-Riak-Meta-* headers that were in the HTTP response, keyed on the trailing portion
51
51
  attr_accessor :meta
52
52
 
53
+ # Loads a list of RObjects that were emitted from a MapReduce
54
+ # query.
55
+ # @param [Client] client A Riak::Client with which the results will be
56
+ # associated
57
+ # @param [Array<Hash>] response A list of results a MapReduce job. Each
58
+ # entry should contain these keys: bucket, key, vclock, values
59
+ # @return [Array<RObject>] An array of RObject instances
60
+ def self.load_from_mapreduce(client, response)
61
+ response.map do |item|
62
+ RObject.new(client[CGI.unescape(item['bucket'])], CGI.unescape(item['key'])).load_from_mapreduce(item)
63
+ end
64
+ end
65
+
53
66
  # Create a new object manually
54
67
  # @param [Bucket] bucket the bucket in which the object exists
55
68
  # @param [String] key the key at which the object resides. If nil, a key will be assigned when the object is saved.
@@ -81,6 +94,28 @@ module Riak
81
94
  self
82
95
  end
83
96
 
97
+ # Load object data from a map/reduce response item.
98
+ # This method is used by RObject::load_from_mapreduce to instantiate the necessary
99
+ # objects.
100
+ # @param [Hash] response a response from {Riak::MapReduce}
101
+ # @return [RObject] self
102
+ def load_from_mapreduce(response)
103
+ self.vclock = response['vclock']
104
+ if response['values'].size == 1
105
+ value = response['values'].first
106
+ load_map_reduce_value(value)
107
+ else
108
+ @conflict = true
109
+ @siblings = response['values'].map do |v|
110
+ RObject.new(self.bucket, self.key) do |robj|
111
+ robj.vclock = self.vclock
112
+ robj.load_map_reduce_value(v)
113
+ end
114
+ end
115
+ end
116
+ self
117
+ end
118
+
84
119
  # HTTP header hash that will be sent along when storing the object
85
120
  # @return [Hash] hash of HTTP Headers
86
121
  def store_headers
@@ -141,9 +176,9 @@ module Riak
141
176
 
142
177
  # Delete the object from Riak and freeze this instance. Will work whether or not the object actually
143
178
  # exists in the Riak database.
144
- def delete
179
+ def delete(options={})
145
180
  return if key.blank?
146
- @bucket.delete(key)
181
+ @bucket.delete(key, options)
147
182
  freeze
148
183
  end
149
184
 
@@ -179,12 +214,8 @@ module Riak
179
214
  ActiveSupport::JSON.encode(payload)
180
215
  when /yaml/
181
216
  YAML.dump(payload)
182
- when "application/octet-stream"
183
- if @meta['ruby-serialization'] == "Marshal"
184
- Marshal.dump(payload)
185
- else
186
- payload.to_s
187
- end
217
+ when "application/x-ruby-marshal"
218
+ Marshal.dump(payload)
188
219
  else
189
220
  payload.to_s
190
221
  end
@@ -203,12 +234,8 @@ module Riak
203
234
  ActiveSupport::JSON.decode(body)
204
235
  when /yaml/
205
236
  YAML.load(body)
206
- when "application/octet-stream"
207
- if @meta['ruby-serialization'] == "Marshal"
208
- Marshal.load(body)
209
- else
210
- body
211
- end
237
+ when "application/x-ruby-marshal"
238
+ Marshal.load(body)
212
239
  else
213
240
  body
214
241
  end
@@ -246,12 +273,37 @@ module Riak
246
273
  @bucket.client.http.path(*segments).to_s
247
274
  end
248
275
 
276
+ protected
277
+ def load_map_reduce_value(hash)
278
+ metadata = hash['metadata']
279
+ extract_if_present(metadata, 'X-Riak-VTag', :etag)
280
+ extract_if_present(metadata, 'content-type', :content_type)
281
+ extract_if_present(metadata, 'X-Riak-Last-Modified', :last_modified) { |v| Time.httpdate( v ) }
282
+ extract_if_present(metadata, 'Links', :links) do |links|
283
+ Set.new( links.map { |l| Link.new("#{@bucket.client.prefix}#{l[0]}/#{l[1]}", l[2]) } )
284
+ end
285
+ extract_if_present(metadata, 'X-Riak-Meta', :meta) do |meta|
286
+ Hash[
287
+ meta.map do |k,v|
288
+ [k.sub(%r{^x-riak-meta-}i, ''), [v]]
289
+ end
290
+ ]
291
+ end
292
+ extract_if_present(hash, 'data', :data) { |v| deserialize(v) }
293
+ end
294
+
249
295
  private
250
- def extract_header(response, name, attribute=nil)
251
- if response[:headers][name].present?
252
- value = response[:headers][name].try(:first)
253
- value = yield value if block_given?
254
- send("#{attribute}=", value) if attribute
296
+ def extract_if_present(hash, key, attribute=nil)
297
+ if hash[key].present?
298
+ attribute ||= key
299
+ value = block_given? ? yield(hash[key]) : hash[key]
300
+ send("#{attribute}=", value)
301
+ end
302
+ end
303
+
304
+ def extract_header(response, name, attribute=nil, &block)
305
+ extract_if_present(response[:headers], name, attribute) do |value|
306
+ block ? block.call(value[0]) : value[0]
255
307
  end
256
308
  end
257
309
 
@@ -1,11 +1,11 @@
1
1
  module Riak
2
2
  module Util
3
3
  module Escape
4
- # URI-escapes bucket or key names that may contain slashes for use in URLs.
4
+ # CGI-escapes bucket or key names that may contain slashes for use in URLs.
5
5
  # @param [String] bucket_or_key the bucket or key name
6
6
  # @return [String] the escaped path segment
7
7
  def escape(bucket_or_key)
8
- URI.escape(bucket_or_key.to_s).gsub("/", "%2F")
8
+ CGI.escape(bucket_or_key.to_s).gsub("+", "%20")
9
9
  end
10
10
  end
11
11
  end
@@ -57,6 +57,42 @@ describe Riak::CacheStore do
57
57
  @cache = ActiveSupport::Cache.lookup_store(:riak_store, :n_value => 1)
58
58
  @cache.bucket.n_value.should == 1
59
59
  end
60
+
61
+ it "should set the bucket R value to 1 by default" do
62
+ @cache.bucket.r.should == 1
63
+ end
64
+
65
+ it "should set the bucket R default to the specified value" do
66
+ @cache = ActiveSupport::Cache.lookup_store(:riak_store, :r => "quorum")
67
+ @cache.bucket.r.should == "quorum"
68
+ end
69
+
70
+ it "should set the bucket W value to 1 by default" do
71
+ @cache.bucket.w.should == 1
72
+ end
73
+
74
+ it "should set the bucket W default to the specified value" do
75
+ @cache = ActiveSupport::Cache.lookup_store(:riak_store, :w => "all")
76
+ @cache.bucket.w.should == "all"
77
+ end
78
+
79
+ it "should set the bucket DW value to 0 by default" do
80
+ @cache.bucket.dw.should == 0
81
+ end
82
+
83
+ it "should set the bucket DW default to the specified value" do
84
+ @cache = ActiveSupport::Cache.lookup_store(:riak_store, :dw => "quorum")
85
+ @cache.bucket.dw.should == "quorum"
86
+ end
87
+
88
+ it "should set the bucket RW value to quorum by default" do
89
+ @cache.bucket.rw.should == "quorum"
90
+ end
91
+
92
+ it "should set the bucket RW default to the specified value" do
93
+ @cache = ActiveSupport::Cache.lookup_store(:riak_store, :rw => "all")
94
+ @cache.bucket.rw.should == "all"
95
+ end
60
96
  end
61
97
 
62
98
 
@@ -93,20 +129,6 @@ describe Riak::CacheStore do
93
129
  @cache.fetch('foo', :force => true){'bar'}.should == 'bar'
94
130
  end
95
131
 
96
- it "should increment an integer value in the cache" do
97
- @cache.write('foo', 1, :raw => true)
98
- @cache.read('foo', :raw => true).to_i.should == 1
99
- @cache.increment('foo')
100
- @cache.read('foo', :raw => true).to_i.should == 2
101
- end
102
-
103
- it "should decrement an integer value in the cache" do
104
- @cache.write('foo', 1, :raw => true)
105
- @cache.read('foo', :raw => true).to_i.should == 1
106
- @cache.decrement('foo')
107
- @cache.read('foo', :raw => true).to_i.should == 0
108
- end
109
-
110
132
  it "should detect if a value exists in the cache" do
111
133
  @cache.write('foo', 'bar')
112
134
  @cache.exist?('foo').should be_true
@@ -21,7 +21,7 @@ describe Riak::Bucket do
21
21
 
22
22
  def do_load(overrides={})
23
23
  @bucket.load({
24
- :body => '{"props":{"name":"foo","allow_mult":false,"big_vclock":50,"chash_keyfun":{"mod":"riak_util","fun":"chash_std_keyfun"},"linkfun":{"mod":"jiak_object","fun":"mapreduce_linkfun"},"n_val":3,"old_vclock":86400,"small_vclock":10,"young_vclock":20},"keys":["bar"]}',
24
+ :body => '{"props":{"name":"foo","n_val":3,"allow_mult":false,"last_write_wins":false,"precommit":[],"postcommit":[],"chash_keyfun":{"mod":"riak_core_util","fun":"chash_std_keyfun"},"linkfun":{"mod":"riak_kv_wm_link_walker","fun":"mapreduce_linkfun"},"old_vclock":86400,"young_vclock":20,"big_vclock":50,"small_vclock":10,"r":"quorum","w":"quorum","dw":"quorum","rw":"quorum"},"keys":["bar"]}',
25
25
  :headers => {
26
26
  "vary" => ["Accept-Encoding"],
27
27
  "server" => ["MochiWeb/1.1 WebMachine/1.5.1 (hack the charles gibson)"],
@@ -53,7 +53,7 @@ describe Riak::Bucket do
53
53
  describe "when loading data from an HTTP response" do
54
54
  it "should load the bucket properties from the response body" do
55
55
  do_load
56
- @bucket.props.should == {"name"=>"foo","allow_mult" => false,"big_vclock" => 50,"chash_keyfun" => {"mod" =>"riak_util","fun"=>"chash_std_keyfun"},"linkfun"=>{"mod"=>"jiak_object","fun"=>"mapreduce_linkfun"},"n_val"=>3,"old_vclock"=>86400,"small_vclock"=>10,"young_vclock"=>20}
56
+ @bucket.props.should == {"name"=>"foo", "n_val"=>3, "allow_mult"=>false, "last_write_wins"=>false, "precommit"=>[], "postcommit"=>[], "chash_keyfun"=>{"mod"=>"riak_core_util", "fun"=>"chash_std_keyfun"}, "linkfun"=>{"mod"=>"riak_kv_wm_link_walker", "fun"=>"mapreduce_linkfun"}, "old_vclock"=>86400, "young_vclock"=>20, "big_vclock"=>50, "small_vclock"=>10, "r"=>"quorum", "w"=>"quorum", "dw"=>"quorum", "rw"=>"quorum"}
57
57
  end
58
58
 
59
59
  it "should load the keys from the response body" do
@@ -80,12 +80,12 @@ describe Riak::Bucket do
80
80
  end
81
81
 
82
82
  it "should load the keys if not present" do
83
- @http.should_receive(:get).with(200, "/riak/", "foo", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
83
+ @http.should_receive(:get).with(200, "/riak/", "foo", {:props => false, :keys => true}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
84
84
  @bucket.keys.should == ["bar"]
85
85
  end
86
86
 
87
87
  it "should allow reloading of the keys" do
88
- @http.should_receive(:get).with(200, "/riak/","foo", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
88
+ @http.should_receive(:get).with(200, "/riak/","foo", {:props => false, :keys => true}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
89
89
  do_load # Ensures they're already loaded
90
90
  @bucket.keys(:reload => true).should == ["bar"]
91
91
  end
@@ -101,13 +101,13 @@ describe Riak::Bucket do
101
101
  end
102
102
 
103
103
  it "should unescape key names" do
104
- @http.should_receive(:get).with(200, "/riak/","foo", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar%20baz"]}'})
104
+ @http.should_receive(:get).with(200, "/riak/","foo", {:props => false, :keys => true}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar%20baz"]}'})
105
105
  @bucket.keys.should == ["bar baz"]
106
106
  end
107
107
 
108
108
  it "should escape the bucket name" do
109
109
  @bucket.instance_variable_set :@name, "unescaped "
110
- @http.should_receive(:get).with(200, "/riak/","unescaped%20", {:props => false}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
110
+ @http.should_receive(:get).with(200, "/riak/","unescaped%20", {:props => false, :keys => true}, {}).and_return({:headers => {"content-type" => ["application/json"]}, :body => '{"keys":["bar"]}'})
111
111
  @bucket.keys.should == ["bar"]
112
112
  end
113
113
  end
@@ -228,6 +228,24 @@ describe Riak::Bucket do
228
228
  end
229
229
  end
230
230
 
231
+ [:r, :w, :dw, :rw].each do |q|
232
+ describe "get/set the default #{q} quorum" do
233
+ before :each do
234
+ do_load
235
+ end
236
+
237
+ it "should extract the default #{q} quorum" do
238
+ @bucket.send(q).should == "quorum"
239
+ end
240
+
241
+ it "should set the #{q} quorum" do
242
+ @bucket.should_receive(:props=).with(hash_including("#{q}" => 1))
243
+ @bucket.send("#{q}=",1)
244
+ end
245
+ end
246
+ end
247
+
248
+
231
249
  describe "checking whether a key exists" do
232
250
  it "should return true if the object does exist" do
233
251
  @client.http.should_receive(:head).and_return(:code => 200)
@@ -1,4 +1,4 @@
1
- # Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
1
+ 60# Copyright 2010 Sean Cribbs, Sonian Inc., and Basho Technologies, Inc.
2
2
  #
3
3
  # Licensed under the Apache License, Version 2.0 (the "License");
4
4
  # you may not use this file except in compliance with the License.
@@ -157,13 +157,13 @@ describe Riak::Client do
157
157
  end
158
158
 
159
159
  it "should send a GET request to the bucket name and return a Riak::Bucket" do
160
- @http.should_receive(:get).with(200, "/riak/", "foo", {}, {}).and_return(@payload)
160
+ @http.should_receive(:get).with(200, "/riak/", "foo", {:keys => false}, {}).and_return(@payload)
161
161
  @client.bucket("foo").should be_kind_of(Riak::Bucket)
162
162
  end
163
163
 
164
- it "should allow requesting bucket properties without the keys" do
165
- @http.should_receive(:get).with(200, "/riak/", "foo", {:keys => false}, {}).and_return(@payload)
166
- @client.bucket("foo", :keys => false)
164
+ it "should allow requesting bucket properties with the keys" do
165
+ @http.should_receive(:get).with(200, "/riak/", "foo", {:keys => true}, {}).and_return(@payload)
166
+ @client.bucket("foo", :keys => true)
167
167
  end
168
168
 
169
169
  it "should escape bucket names with invalid characters" do
@@ -9,6 +9,7 @@ describe Riak::Util::Escape do
9
9
  it "should escape standard non-safe characters" do
10
10
  @object.escape("some string").should == "some%20string"
11
11
  @object.escape("another^one").should == "another%5Eone"
12
+ @object.escape("bracket[one").should == "bracket%5Bone"
12
13
  end
13
14
 
14
15
  it "should escape slashes" do
@@ -49,11 +49,21 @@ describe Riak::MapReduce do
49
49
  @mr.inputs.should == [["foo","bar"]]
50
50
  end
51
51
 
52
+ it "should add bucket/key pairs to the inputs" do
53
+ @mr.add("[foo]","(bar)")
54
+ @mr.inputs.should == [["%5Bfoo%5D","%28bar%29"]]
55
+ end
56
+
52
57
  it "should add an array containing a bucket/key pair to the inputs" do
53
58
  @mr.add(["foo","bar"])
54
59
  @mr.inputs.should == [["foo","bar"]]
55
60
  end
56
61
 
62
+ it "should add an escaped array containing a bucket/key pair to the inputs" do
63
+ @mr.add(["[foo]","(bar)"])
64
+ @mr.inputs.should == [["%5Bfoo%5D","%28bar%29"]]
65
+ end
66
+
57
67
  it "should add an object to the inputs by its bucket and key" do
58
68
  bucket = Riak::Bucket.new(@client, "foo")
59
69
  obj = Riak::RObject.new(bucket, "bar")
@@ -61,17 +71,36 @@ describe Riak::MapReduce do
61
71
  @mr.inputs.should == [["foo", "bar"]]
62
72
  end
63
73
 
74
+ it "should add an object to the inputs by its escaped bucket and key" do
75
+ bucket = Riak::Bucket.new(@client, "[foo]")
76
+ obj = Riak::RObject.new(bucket, "(bar)")
77
+ @mr.add(obj)
78
+ @mr.inputs.should == [["%5Bfoo%5D", "%28bar%29"]]
79
+ end
80
+
64
81
  it "should add an array containing a bucket/key/key-data triple to the inputs" do
65
82
  @mr.add(["foo","bar",1000])
66
83
  @mr.inputs.should == [["foo","bar",1000]]
67
84
  end
68
85
 
86
+ it "should add an escaped array containing a bucket/key/key-data triple to the inputs" do
87
+ @mr.add(["[foo]","(bar)","[]()"])
88
+ @mr.inputs.should == [["%5Bfoo%5D", "%28bar%29","[]()"]]
89
+ end
90
+
69
91
  it "should use a bucket name as the single input" do
70
92
  @mr.add(Riak::Bucket.new(@client, "foo"))
71
93
  @mr.inputs.should == "foo"
72
94
  @mr.add("docs")
73
95
  @mr.inputs.should == "docs"
74
96
  end
97
+
98
+ it "should use an escaped bucket name as the single input" do
99
+ @mr.add(Riak::Bucket.new(@client, "[foo]"))
100
+ @mr.inputs.should == "%5Bfoo%5D"
101
+ @mr.add("docs")
102
+ @mr.inputs.should == "docs"
103
+ end
75
104
  end
76
105
 
77
106
  [:map, :reduce].each do |type|
@@ -101,39 +101,19 @@ describe Riak::RObject do
101
101
  end
102
102
  end
103
103
 
104
- describe "when the content type is an octet-stream" do
104
+ describe "when the content type is application/x-ruby-marshal" do
105
105
  before :each do
106
- @object.content_type = "application/octet-stream"
106
+ @object.content_type = "application/x-ruby-marshal"
107
+ @payload = Marshal.dump({"foo" => "bar"})
107
108
  end
108
109
 
109
- describe "if the ruby-serialization meta field is set to Marshal" do
110
- before :each do
111
- @object.meta['ruby-serialization'] = "Marshal"
112
- @payload = Marshal.dump({"foo" => "bar"})
113
- end
114
110
 
115
- it "should dump via Marshal" do
116
- @object.serialize({"foo" => "bar"}).should == @payload
117
- end
118
-
119
- it "should load from Marshal" do
120
- @object.deserialize(@payload).should == {"foo" => "bar"}
121
- end
111
+ it "should dump via Marshal" do
112
+ @object.serialize({"foo" => "bar"}).should == @payload
122
113
  end
123
114
 
124
- describe "if the ruby-serialization meta field is not set to Marshal" do
125
- before :each do
126
- @object.meta.delete("ruby-serialization")
127
- end
128
-
129
- it "should dump to a string" do
130
- @object.serialize(2).should == "2"
131
- @object.serialize("foo").should == "foo"
132
- end
133
-
134
- it "should load the body unmodified" do
135
- @object.deserialize("foo").should == "foo"
136
- end
115
+ it "should load from Marshal" do
116
+ @object.deserialize(@payload).should == {"foo" => "bar"}
137
117
  end
138
118
  end
139
119
  end
@@ -198,6 +178,11 @@ describe Riak::RObject do
198
178
  @object.key.should == "baz"
199
179
  end
200
180
 
181
+ it "should parse and escape the location header into the key when present" do
182
+ @object.load({:headers => {"content-type" => ["application/json"], "location" => ["/riak/foo/%5Bbaz%5D"]}})
183
+ @object.key.should == "[baz]"
184
+ end
185
+
201
186
  it "should be in conflict when the response code is 300 and the content-type is multipart/mixed" do
202
187
  @object.load({:headers => {"content-type" => ["multipart/mixed; boundary=foo"]}, :code => 300 })
203
188
  @object.should be_conflict
@@ -209,6 +194,106 @@ describe Riak::RObject do
209
194
  end
210
195
  end
211
196
 
197
+ describe "instantiating new object from a map reduce operation" do
198
+ before :each do
199
+ @client.stub!(:[]).and_return(@bucket)
200
+
201
+ @sample_response = [
202
+ {"bucket"=>"users",
203
+ "key"=>"A2IbUQ2KEMbe4WGtdL97LoTi1DN%5B%28%5C%2F%29%5D",
204
+ "vclock"=> "a85hYGBgzmDKBVIsCfs+fc9gSN9wlA8q/hKosDpIOAsA",
205
+ "values"=> [
206
+ {"metadata"=>
207
+ {"Links"=>[["addresses", "A2cbUQ2KEMbeyWGtdz97LoTi1DN", "home_address"]],
208
+ "X-Riak-VTag"=>"5bnavU3rrubcxLI8EvFXhB",
209
+ "content-type"=>"application/json",
210
+ "X-Riak-Last-Modified"=>"Mon, 12 Jul 2010 21:37:43 GMT",
211
+ "X-Riak-Meta"=>{"X-Riak-Meta-King-Of-Robots"=>"I"}},
212
+ "data"=>
213
+ "{\"email\":\"mail@test.com\",\"_type\":\"User\"}"
214
+ }
215
+ ]
216
+ }
217
+ ]
218
+ @object = Riak::RObject.load_from_mapreduce(@client,@sample_response).first
219
+ @object.should be_kind_of(Riak::RObject)
220
+ end
221
+
222
+ it "should load the content type" do
223
+ @object.content_type.should == "application/json"
224
+ end
225
+
226
+ it "should load the body data" do
227
+ @object.data.should be_present
228
+ end
229
+
230
+ it "should deserialize the body data" do
231
+ @object.data.should == {"email" => "mail@test.com", "_type" => "User"}
232
+ end
233
+
234
+ it "should set the vclock" do
235
+ @object.vclock.should == "a85hYGBgzmDKBVIsCfs+fc9gSN9wlA8q/hKosDpIOAsA"
236
+ end
237
+
238
+ it "should load and parse links" do
239
+ @object.links.should have(1).item
240
+ @object.links.first.url.should == "/riak/addresses/A2cbUQ2KEMbeyWGtdz97LoTi1DN"
241
+ @object.links.first.rel.should == "home_address"
242
+ end
243
+
244
+ it "should set the ETag" do
245
+ @object.etag.should == "5bnavU3rrubcxLI8EvFXhB"
246
+ end
247
+
248
+ it "should set modified date" do
249
+ @object.last_modified.to_i.should == Time.httpdate("Mon, 12 Jul 2010 21:37:43 GMT").to_i
250
+ end
251
+
252
+ it "should load meta information" do
253
+ @object.meta["King-Of-Robots"].should == ["I"]
254
+ end
255
+
256
+ it "should set the key" do
257
+ @object.key.should == "A2IbUQ2KEMbe4WGtdL97LoTi1DN[(\\/)]"
258
+ end
259
+
260
+ it "should not set conflict when there is none" do
261
+ @object.conflict?.should be_false
262
+ end
263
+
264
+ describe "when there are multiple values in an object" do
265
+ before :each do
266
+ response = @sample_response.dup
267
+ response[0]['values'] << {
268
+ "metadata"=> {
269
+ "Links"=>[],
270
+ "X-Riak-VTag"=>"7jDZLdu0fIj2iRsjGD8qq8",
271
+ "content-type"=>"application/json",
272
+ "X-Riak-Last-Modified"=>"Mon, 14 Jul 2010 19:28:27 GMT",
273
+ "X-Riak-Meta"=>[]
274
+ },
275
+ "data"=> "{\"email\":\"mail@domain.com\",\"_type\":\"User\"}"
276
+ }
277
+ @object = Riak::RObject.load_from_mapreduce( @client, response ).first
278
+ end
279
+
280
+ it "should expose siblings" do
281
+ @object.should have(2).siblings
282
+ @object.siblings[0].etag.should == "5bnavU3rrubcxLI8EvFXhB"
283
+ @object.siblings[1].etag.should == "7jDZLdu0fIj2iRsjGD8qq8"
284
+ end
285
+
286
+ it "should be in conflict" do
287
+ @object.data.should_not be_present
288
+ @object.should be_conflict
289
+ end
290
+
291
+ it "should assign the same vclock to all the siblings" do
292
+ @object.siblings.should be_all {|s| s.vclock == @object.vclock }
293
+ end
294
+ end
295
+ end
296
+
212
297
  describe "extracting siblings" do
213
298
  before :each do
214
299
  @object = Riak::RObject.new(@bucket, "bar").load({:headers => {"x-riak-vclock" => ["merged"], "content-type" => ["multipart/mixed; boundary=foo"]}, :code => 300, :body => "\n--foo\nContent-Type: text/plain\n\nbar\n--foo\nContent-Type: text/plain\n\nbaz\n--foo--\n"})
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: riak-client
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: false
4
+ prerelease: true
5
5
  segments:
6
6
  - 0
7
- - 7
8
- - 1
9
- version: 0.7.1
7
+ - 8
8
+ - 0
9
+ - beta
10
+ version: 0.8.0.beta
10
11
  platform: ruby
11
12
  authors:
12
13
  - Sean Cribbs
@@ -14,13 +15,14 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-06-08 00:00:00 -04:00
18
+ date: 2010-08-24 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: rspec
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ~>
26
28
  - !ruby/object:Gem::Version
@@ -29,14 +31,15 @@ dependencies:
29
31
  - 0
30
32
  - 0
31
33
  - beta
32
- - 6
33
- version: 2.0.0.beta.6
34
+ - 11
35
+ version: 2.0.0.beta.11
34
36
  type: :development
35
37
  version_requirements: *id001
36
38
  - !ruby/object:Gem::Dependency
37
39
  name: fakeweb
38
40
  prerelease: false
39
41
  requirement: &id002 !ruby/object:Gem::Requirement
42
+ none: false
40
43
  requirements:
41
44
  - - ">="
42
45
  - !ruby/object:Gem::Version
@@ -50,6 +53,7 @@ dependencies:
50
53
  name: rack
51
54
  prerelease: false
52
55
  requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
53
57
  requirements:
54
58
  - - ">="
55
59
  - !ruby/object:Gem::Version
@@ -63,6 +67,7 @@ dependencies:
63
67
  name: curb
64
68
  prerelease: false
65
69
  requirement: &id004 !ruby/object:Gem::Requirement
70
+ none: false
66
71
  requirements:
67
72
  - - ">="
68
73
  - !ruby/object:Gem::Version
@@ -76,6 +81,7 @@ dependencies:
76
81
  name: activesupport
77
82
  prerelease: false
78
83
  requirement: &id005 !ruby/object:Gem::Requirement
84
+ none: false
79
85
  requirements:
80
86
  - - ">="
81
87
  - !ruby/object:Gem::Version
@@ -86,6 +92,21 @@ dependencies:
86
92
  version: 2.3.5
87
93
  type: :runtime
88
94
  version_requirements: *id005
95
+ - !ruby/object:Gem::Dependency
96
+ name: i18n
97
+ prerelease: false
98
+ requirement: &id006 !ruby/object:Gem::Requirement
99
+ none: false
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ segments:
104
+ - 0
105
+ - 4
106
+ - 0
107
+ version: 0.4.0
108
+ type: :runtime
109
+ version_requirements: *id006
89
110
  description: riak-client is a rich client for Riak, the distributed database by Basho. It supports the full HTTP interface including storage operations, bucket configuration, link-walking and map-reduce.
90
111
  email: seancribbs@gmail.com
91
112
  executables: []
@@ -95,6 +116,8 @@ extensions: []
95
116
  extra_rdoc_files: []
96
117
 
97
118
  files:
119
+ - Gemfile
120
+ - Gemfile.lock
98
121
  - lib/riak/bucket.rb
99
122
  - lib/riak/cache_store.rb
100
123
  - lib/riak/client/curb_backend.rb
@@ -147,6 +170,7 @@ rdoc_options: []
147
170
  require_paths:
148
171
  - lib
149
172
  required_ruby_version: !ruby/object:Gem::Requirement
173
+ none: false
150
174
  requirements:
151
175
  - - ">="
152
176
  - !ruby/object:Gem::Version
@@ -154,16 +178,19 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
178
  - 0
155
179
  version: "0"
156
180
  required_rubygems_version: !ruby/object:Gem::Requirement
181
+ none: false
157
182
  requirements:
158
- - - ">="
183
+ - - ">"
159
184
  - !ruby/object:Gem::Version
160
185
  segments:
161
- - 0
162
- version: "0"
186
+ - 1
187
+ - 3
188
+ - 1
189
+ version: 1.3.1
163
190
  requirements:
164
191
  - `gem install curb` for better HTTP performance
165
192
  rubyforge_project:
166
- rubygems_version: 1.3.6
193
+ rubygems_version: 1.3.7
167
194
  signing_key:
168
195
  specification_version: 3
169
196
  summary: riak-client is a rich client for Riak, the distributed database by Basho.