riak-client 0.9.8 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/.gitignore +32 -0
  2. data/Gemfile +17 -11
  3. data/Guardfile +14 -0
  4. data/Rakefile +18 -44
  5. data/erl_src/riak_kv_test_backend.beam +0 -0
  6. data/erl_src/riak_kv_test_backend.erl +461 -128
  7. data/erl_src/riak_search_test_backend.beam +0 -0
  8. data/erl_src/riak_search_test_backend.erl +175 -0
  9. data/lib/active_support/cache/riak_store.rb +0 -13
  10. data/lib/riak.rb +11 -16
  11. data/lib/riak/bucket.rb +59 -41
  12. data/lib/riak/cache_store.rb +1 -14
  13. data/lib/riak/client.rb +145 -73
  14. data/lib/riak/client/beefcake/messages.rb +36 -31
  15. data/lib/riak/client/beefcake/object_methods.rb +27 -19
  16. data/lib/riak/client/beefcake_protobuffs_backend.rb +27 -33
  17. data/lib/riak/client/excon_backend.rb +0 -13
  18. data/lib/riak/client/http_backend.rb +95 -60
  19. data/lib/riak/client/http_backend/configuration.rb +144 -19
  20. data/lib/riak/client/http_backend/key_streamer.rb +1 -14
  21. data/lib/riak/client/http_backend/object_methods.rb +16 -16
  22. data/lib/riak/client/http_backend/request_headers.rb +0 -13
  23. data/lib/riak/client/http_backend/transport_methods.rb +26 -56
  24. data/lib/riak/client/net_http_backend.rb +11 -13
  25. data/lib/riak/client/protobuffs_backend.rb +21 -19
  26. data/lib/riak/client/pump.rb +1 -15
  27. data/lib/riak/client/search.rb +85 -0
  28. data/lib/riak/cluster.rb +151 -0
  29. data/lib/riak/core_ext.rb +1 -0
  30. data/lib/riak/core_ext/deep_dup.rb +13 -0
  31. data/lib/riak/core_ext/json.rb +15 -0
  32. data/lib/riak/core_ext/stringify_keys.rb +1 -1
  33. data/lib/riak/core_ext/symbolize_keys.rb +1 -1
  34. data/lib/riak/encoding.rb +6 -0
  35. data/lib/riak/failed_request.rb +2 -15
  36. data/lib/riak/i18n.rb +0 -13
  37. data/lib/riak/json.rb +19 -8
  38. data/lib/riak/link.rb +18 -20
  39. data/lib/riak/locale/en.yml +13 -16
  40. data/lib/riak/map_reduce.rb +40 -20
  41. data/lib/riak/map_reduce/filter_builder.rb +14 -18
  42. data/lib/riak/map_reduce/phase.rb +0 -13
  43. data/lib/riak/map_reduce_error.rb +0 -13
  44. data/lib/riak/node.rb +38 -0
  45. data/lib/riak/node/configuration.rb +286 -0
  46. data/lib/riak/node/console.rb +139 -0
  47. data/lib/riak/node/control.rb +207 -0
  48. data/lib/riak/node/defaults.rb +70 -0
  49. data/lib/riak/node/generation.rb +99 -0
  50. data/lib/riak/node/log.rb +34 -0
  51. data/lib/riak/node/version.rb +37 -0
  52. data/lib/riak/robject.rb +45 -41
  53. data/lib/riak/search.rb +2 -161
  54. data/lib/riak/serializers.rb +74 -0
  55. data/lib/riak/stamp.rb +77 -0
  56. data/lib/riak/test_server.rb +56 -220
  57. data/lib/riak/util/escape.rb +58 -17
  58. data/lib/riak/util/headers.rb +2 -15
  59. data/lib/riak/util/multipart.rb +0 -13
  60. data/lib/riak/util/multipart/stream_parser.rb +0 -13
  61. data/lib/riak/util/tcp_socket_extensions.rb +1 -14
  62. data/lib/riak/util/translation.rb +0 -13
  63. data/lib/riak/version.rb +3 -0
  64. data/lib/riak/walk_spec.rb +0 -13
  65. data/riak-client.gemspec +27 -47
  66. data/spec/fixtures/multipart-with-marked-tombstones.txt +17 -0
  67. data/spec/fixtures/multipart-with-unmarked-tombstone.txt +16 -0
  68. data/spec/integration/riak/cache_store_spec.rb +2 -40
  69. data/spec/integration/riak/cluster_spec.rb +88 -0
  70. data/spec/integration/riak/http_backends_spec.rb +6 -30
  71. data/spec/integration/riak/node_spec.rb +184 -0
  72. data/spec/integration/riak/protobuffs_backends_spec.rb +2 -26
  73. data/spec/integration/riak/test_server_spec.rb +31 -167
  74. data/spec/riak/beefcake_protobuffs_backend_spec.rb +5 -4
  75. data/spec/riak/bucket_spec.rb +26 -36
  76. data/spec/riak/client_spec.rb +44 -38
  77. data/spec/riak/escape_spec.rb +56 -30
  78. data/spec/riak/excon_backend_spec.rb +4 -17
  79. data/spec/riak/headers_spec.rb +1 -14
  80. data/spec/riak/http_backend/configuration_spec.rb +211 -34
  81. data/spec/riak/http_backend/object_methods_spec.rb +52 -18
  82. data/spec/riak/http_backend/transport_methods_spec.rb +5 -38
  83. data/spec/riak/http_backend_spec.rb +84 -78
  84. data/spec/riak/link_spec.rb +19 -18
  85. data/spec/riak/map_reduce/filter_builder_spec.rb +1 -14
  86. data/spec/riak/map_reduce/phase_spec.rb +1 -14
  87. data/spec/riak/map_reduce_spec.rb +141 -43
  88. data/spec/riak/multipart_spec.rb +1 -14
  89. data/spec/riak/net_http_backend_spec.rb +2 -15
  90. data/spec/riak/robject_spec.rb +129 -97
  91. data/spec/riak/search_spec.rb +45 -62
  92. data/spec/riak/serializers_spec.rb +93 -0
  93. data/spec/riak/stamp_spec.rb +54 -0
  94. data/spec/riak/stream_parser_spec.rb +3 -16
  95. data/spec/riak/walk_spec_spec.rb +1 -14
  96. data/spec/spec_helper.rb +22 -27
  97. data/spec/support/http_backend_implementation_examples.rb +49 -79
  98. data/spec/support/integration_setup.rb +10 -0
  99. data/spec/support/mock_server.rb +0 -14
  100. data/spec/support/mocks.rb +0 -13
  101. data/spec/support/test_server.rb +30 -0
  102. data/spec/support/test_server.yml.example +14 -2
  103. data/spec/support/unified_backend_examples.rb +36 -27
  104. metadata +100 -31
  105. data/lib/riak/client/curb_backend.rb +0 -89
  106. data/spec/riak/curb_backend_spec.rb +0 -76
@@ -0,0 +1,34 @@
1
+ module Riak
2
+ class Node
3
+ LAGER_LEVELS = [
4
+ :debug,
5
+ :info,
6
+ :notice,
7
+ :warning,
8
+ :error,
9
+ :critical,
10
+ :alert,
11
+ :emergency
12
+ ]
13
+
14
+ def read_console_log(*levels)
15
+ console_log = log + 'console.log'
16
+ if console_log.exist?
17
+ levels = levels.map { |level| expand_log_level(level) }.compact.flatten
18
+ pattern = /(#{levels.map { |level| "\\[#{level}\\]" }.join("|")})/
19
+ console_log.readlines.grep(pattern)
20
+ end
21
+ end
22
+
23
+ def expand_log_level(level)
24
+ case level
25
+ when Range
26
+ first = LAGER_LEVELS.index(level.begin) || 0
27
+ last = LAGER_LEVELS.index(level.end) || -1
28
+ LAGER_LEVELS[first..last]
29
+ when Symbol
30
+ level
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ require 'pathname'
2
+
3
+ module Riak
4
+ class Node
5
+ def version
6
+ @version ||= configure_version
7
+ end
8
+
9
+ def configure_version
10
+ if base_dir
11
+ versions = (base_dir + 'releases' + 'start_erl.data').read
12
+ versions.split(" ")[1]
13
+ end
14
+ end
15
+
16
+ def base_dir
17
+ @base_dir ||= configure_base_dir
18
+ end
19
+
20
+ def configure_base_dir
21
+ pattern = /^RUNNER_BASE_DIR=(.*)/
22
+ lines = control_script.readlines.grep(pattern)
23
+ if lines.empty?
24
+ nil
25
+ else
26
+ line = lines.first
27
+ case line
28
+ when /^RUNNER_BASE_DIR=$\{RUNNER_SCRIPT_DIR%\/*\}/
29
+ source.parent
30
+ else
31
+ path = pattern.match(line)[1]
32
+ Pathname.new(path).expand_path if File.directory?(path)
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,16 +1,3 @@
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
1
  require 'set'
15
2
  require 'time'
16
3
  require 'yaml'
@@ -19,12 +6,14 @@ require 'riak/util/escape'
19
6
  require 'riak/bucket'
20
7
  require 'riak/link'
21
8
  require 'riak/walk_spec'
9
+ require 'riak/serializers'
22
10
 
23
11
  module Riak
24
12
  # Represents the data and metadata stored in a bucket/key pair in
25
13
  # the Riak database, the base unit of data manipulation.
26
14
  class RObject
27
15
  include Util::Translation
16
+ extend Util::Translation
28
17
  include Util::Escape
29
18
  extend Util::Escape
30
19
 
@@ -52,10 +41,34 @@ module Riak
52
41
  # @return [Hash] a hash of any X-Riak-Meta-* headers that were in the HTTP response, keyed on the trailing portion
53
42
  attr_accessor :meta
54
43
 
44
+ # @return [Hash<Set>] a hash of secondary indexes, where the
45
+ # key is the index name and the value is a Set of index
46
+ # entries for that index
47
+ attr_accessor :indexes
48
+
55
49
  # @return [Boolean] whether to attempt to prevent stale writes using conditional PUT semantics, If-None-Match: * or If-Match: {#etag}
56
50
  # @see http://wiki.basho.com/display/RIAK/REST+API#RESTAPI-Storeaneworexistingobjectwithakey Riak Rest API Docs
57
51
  attr_accessor :prevent_stale_writes
58
52
 
53
+ def self.on_conflict(&conflict_hook)
54
+ on_conflict_hooks << conflict_hook
55
+ end
56
+
57
+ def self.on_conflict_hooks
58
+ @on_conflict_hooks ||= []
59
+ end
60
+
61
+ def attempt_conflict_resolution
62
+ return self unless conflict?
63
+
64
+ self.class.on_conflict_hooks.each do |hook|
65
+ result = hook.call(self)
66
+ return result if result.is_a?(RObject)
67
+ end
68
+
69
+ self
70
+ end
71
+
59
72
  # Loads a list of RObjects that were emitted from a MapReduce
60
73
  # query.
61
74
  # @param [Client] client A Riak::Client with which the results will be associated
@@ -75,6 +88,7 @@ module Riak
75
88
  def initialize(bucket, key=nil)
76
89
  @bucket, @key = bucket, key
77
90
  @links, @meta = Set.new, {}
91
+ @indexes = Hash.new {|h,k| h[k] = Set.new }
78
92
  yield self if block_given?
79
93
  end
80
94
 
@@ -103,7 +117,8 @@ module Riak
103
117
  # @return [Object] the unmarshaled form of {#raw_data} stored in riak at this object's key
104
118
  def data
105
119
  if @raw_data && !@data
106
- @data = deserialize(@raw_data)
120
+ raw = @raw_data.respond_to?(:read) ? @raw_data.read : @raw_data
121
+ @data = deserialize(raw)
107
122
  @raw_data = nil
108
123
  end
109
124
  @data
@@ -112,6 +127,10 @@ module Riak
112
127
  # @param [Object] unmarshaled form of the data to be stored in riak. Object will be serialized using {#serialize} if a known content_type is used. Setting this overrides values stored with {#raw_data=}
113
128
  # @return [Object] the object stored
114
129
  def data=(new_data)
130
+ if new_data.respond_to?(:read)
131
+ raise ArgumentError.new(t("invalid_io_object"))
132
+ end
133
+
115
134
  @raw_data = nil
116
135
  @data = new_data
117
136
  end
@@ -142,8 +161,7 @@ module Riak
142
161
  # @raise [ArgumentError] if the content_type is not defined
143
162
  def store(options={})
144
163
  raise ArgumentError, t("content_type_undefined") unless @content_type.present?
145
- params = {:returnbody => true}.merge(options)
146
- @bucket.client.backend.store_object(self, params[:returnbody], params[:w], params[:dw])
164
+ @bucket.client.store_object(self, options)
147
165
  self
148
166
  end
149
167
 
@@ -158,15 +176,17 @@ module Riak
158
176
  force = options.delete(:force)
159
177
  return self unless @key && (@vclock || force)
160
178
  self.etag = self.last_modified = nil if force
161
- bucket.client.backend.reload_object(self, options[:r])
179
+ bucket.client.reload_object(self, options)
162
180
  end
163
181
 
164
182
  alias :fetch :reload
165
183
 
166
184
  # Delete the object from Riak and freeze this instance. Will work whether or not the object actually
167
185
  # exists in the Riak database.
186
+ # @see Bucket#delete
168
187
  def delete(options={})
169
188
  return if key.blank?
189
+ options[:vclock] = vclock if vclock
170
190
  @bucket.delete(key, options)
171
191
  freeze
172
192
  end
@@ -196,17 +216,7 @@ module Riak
196
216
  # be done.
197
217
  # @param [Object] payload the data to serialize
198
218
  def serialize(payload)
199
- return payload if payload.respond_to?(:read)
200
- case @content_type
201
- when /json/
202
- payload.to_json(Riak.json_options)
203
- when /yaml/
204
- YAML.dump(payload)
205
- when "application/x-ruby-marshal"
206
- Marshal.dump(payload)
207
- else
208
- payload.to_s
209
- end
219
+ Serializers.serialize(@content_type, payload)
210
220
  end
211
221
 
212
222
  # Deserializes the internal object data from a Riak response. Differs based on the content-type.
@@ -217,21 +227,12 @@ module Riak
217
227
  # * Marshal (application/x-ruby-marshal)
218
228
  # @param [String] body the serialized response body
219
229
  def deserialize(body)
220
- case @content_type
221
- when /json/
222
- JSON.parse(body, Riak.json_options)
223
- when /yaml/
224
- YAML.load(body)
225
- when "application/x-ruby-marshal"
226
- Marshal.load(body)
227
- else
228
- body
229
- end
230
+ Serializers.deserialize(@content_type, body)
230
231
  end
231
232
 
232
233
  # @return [String] A representation suitable for IRB and debugging output
233
234
  def inspect
234
- body = if @data || content_type =~ /json|yaml|marshal/
235
+ body = if @data || Serializers[content_type]
235
236
  data.inspect
236
237
  else
237
238
  @raw_data && "(#{@raw_data.size} bytes)"
@@ -257,7 +258,7 @@ module Riak
257
258
  # If the key is blank, the bucket URL will be returned (where the object will be
258
259
  # submitted to when stored).
259
260
  def url
260
- segments = [ @bucket.client.prefix, escape(@bucket.name)]
261
+ segments = [ @bucket.client.http_paths[:prefix], escape(@bucket.name)]
261
262
  segments << escape(@key) if @key
262
263
  @bucket.client.http.path(*segments).to_s
263
264
  end
@@ -265,12 +266,15 @@ module Riak
265
266
  alias :vector_clock :vclock
266
267
  alias :vector_clock= :vclock=
267
268
 
268
- protected
269
+ protected
269
270
  def load_map_reduce_value(hash)
270
271
  metadata = hash['metadata']
271
272
  extract_if_present(metadata, 'X-Riak-VTag', :etag)
272
273
  extract_if_present(metadata, 'content-type', :content_type)
273
274
  extract_if_present(metadata, 'X-Riak-Last-Modified', :last_modified) { |v| Time.httpdate( v ) }
275
+ extract_if_present(metadata, 'index', :indexes) do |entries|
276
+ Hash[ entries.map {|k,v| [k, Set.new(Array(v))] } ]
277
+ end
274
278
  extract_if_present(metadata, 'Links', :links) do |links|
275
279
  Set.new( links.map { |l| Link.new(*l) } )
276
280
  end
@@ -1,162 +1,3 @@
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.
1
+ require 'riak'
14
2
 
15
- require 'riak/json'
16
- require 'riak/client'
17
- require 'riak/bucket'
18
- require 'riak/map_reduce'
19
- require 'builder' # Needed to generate Solr XML
20
-
21
- module Riak
22
- class Client
23
- # @return [String] The URL path prefix to the Solr HTTP endpoint
24
- attr_accessor :solr
25
-
26
- # @private
27
- alias :initialize_core :initialize
28
- # @option options [String] :solr ('/solr') The URL path prefix to the Solr HTTP endpoint
29
- def initialize(options={})
30
- self.solr = options.delete(:solr) || "/solr"
31
- initialize_core(options)
32
- end
33
-
34
- # Performs a search via the Solr interface.
35
- # @overload search(index, query, options={})
36
- # @param [String] index the index to query on
37
- # @param [String] query a Lucene query string
38
- # @overload search(query, options={})
39
- # Queries the default index
40
- # @param [String] query a Lucene query string
41
- # @param [Hash] options extra options for the Solr query
42
- # @option options [String] :df the default field to search in
43
- # @option options [String] :'q.op' the default operator between terms ("or", "and")
44
- # @option options [String] :wt ("json") the response type - "json" and "xml" are valid
45
- # @option options [String] :sort ('none') the field and direction to sort, e.g. "name asc"
46
- # @option options [Fixnum] :start (0) the offset into the query to start from, e.g. for pagination
47
- # @option options [Fixnum] :rows (10) the number of results to return
48
- # @return [Hash] the query result, containing the 'responseHeaders' and 'response' keys
49
- def search(*args)
50
- options = args.extract_options!
51
- index, query = args[-2], args[-1] # Allows nil index, while keeping it as first argument
52
- path = [solr, index, "select", {"q" => query, "wt" => "json"}.merge(options.stringify_keys), {}].compact
53
- response = http.get(200, *path)
54
- if response[:headers]['content-type'].include?("application/json")
55
- JSON.parse(response[:body])
56
- else
57
- response[:body]
58
- end
59
- end
60
- alias :select :search
61
-
62
- # Adds documents to a search index via the Solr interface.
63
- # @overload index(index, *docs)
64
- # Adds documents to the specified search index
65
- # @param [String] index the index in which to add/update the given documents
66
- # @param [Array<Hash>] docs unnested document hashes, with one key per field
67
- # @overload index(*docs)
68
- # Adds documents to the default search index
69
- # @param [Array<Hash>] docs unnested document hashes, with one key per field
70
- # @raise [ArgumentError] if any documents don't include 'id' key
71
- def index(*args)
72
- index = args.shift if String === args.first # Documents must be hashes of fields
73
- raise ArgumentError.new(t("search_docs_require_id")) unless args.all? {|d| d.key?("id") || d.key?(:id) }
74
- xml = Builder::XmlMarkup.new
75
- xml.add do
76
- args.each do |doc|
77
- xml.doc do
78
- doc.each do |k,v|
79
- xml.field('name' => k.to_s) { xml.text!(v.to_s) }
80
- end
81
- end
82
- end
83
- end
84
- path = [solr, index, "update", xml.target!, {'Content-Type' => 'text/xml'}].compact
85
- http.post(200, *path)
86
- true
87
- end
88
- alias :add_doc :index
89
-
90
- # Removes documents from a search index via the Solr interface.
91
- # @overload remove(index, specs)
92
- # Removes documents from the specified index
93
- # @param [String] index the index from which to remove documents
94
- # @param [Array<Hash>] specs the specificaiton of documents to remove (must contain 'id' or 'query' keys)
95
- # @overload remove(specs)
96
- # Removes documents from the default index
97
- # @param [Array<Hash>] specs the specification of documents to remove (must contain 'id' or 'query' keys)
98
- # @raise [ArgumentError] if any document specs don't include 'id' or 'query' keys
99
- def remove(*args)
100
- index = args.shift if String === args.first
101
- raise ArgumentError.new(t("search_remove_requires_id_or_query")) unless args.all? { |s|
102
- s.include? :id or
103
- s.include? 'id' or
104
- s.include? :query or
105
- s.include? 'query'
106
- }
107
- xml = Builder::XmlMarkup.new
108
- xml.delete do
109
- args.each do |spec|
110
- spec.each do |k,v|
111
- xml.tag!(k.to_sym, v)
112
- end
113
- end
114
- end
115
- path = [solr, index, "update", xml.target!, {'Content-Type' => 'text/xml'}].compact
116
- http.post(200, *path)
117
- true
118
- end
119
- alias :delete_doc :remove
120
- alias :deindex :remove
121
- end
122
-
123
- class Bucket
124
- # The precommit specification for kv/search integration
125
- SEARCH_PRECOMMIT_HOOK = {"mod" => "riak_search_kv_hook", "fun" => "precommit"}
126
-
127
- # Installs a precommit hook that automatically indexes objects
128
- # into riak_search.
129
- def enable_index!
130
- unless is_indexed?
131
- self.props = {"precommit" => (props['precommit'] + [SEARCH_PRECOMMIT_HOOK])}
132
- end
133
- end
134
-
135
- # Removes the precommit hook that automatically indexes objects
136
- # into riak_search.
137
- def disable_index!
138
- if is_indexed?
139
- self.props = {"precommit" => (props['precommit'] - [SEARCH_PRECOMMIT_HOOK])}
140
- end
141
- end
142
-
143
- # Detects whether the bucket is automatically indexed into
144
- # riak_search.
145
- # @return [true,false] whether the bucket includes the search indexing hook
146
- def is_indexed?
147
- props['precommit'].include?(SEARCH_PRECOMMIT_HOOK)
148
- end
149
- end
150
-
151
- class MapReduce
152
- # Use a search query to start a map/reduce job.
153
- # @param [String, Bucket] bucket the bucket/index to search
154
- # @param [String] query the query to run
155
- # @return [MapReduce] self
156
- def search(bucket, query)
157
- bucket = bucket.name if bucket.respond_to?(:name)
158
- @inputs = {:module => "riak_search", :function => "mapred_search", :arg => [bucket, query]}
159
- self
160
- end
161
- end
162
- end
3
+ warn Riak.t('deprecated.search', :backtrace => " "+caller.join("\n "))
@@ -0,0 +1,74 @@
1
+ module Riak
2
+ module Serializers
3
+ include Util::Translation
4
+ extend self
5
+
6
+ def [](content_type)
7
+ serializers[content_type]
8
+ end
9
+
10
+ def []=(content_type, serializer)
11
+ serializers[content_type] = serializer
12
+ end
13
+
14
+ def serialize(content_type, content)
15
+ serializer_for(content_type).dump(content)
16
+ end
17
+
18
+ def deserialize(content_type, content)
19
+ serializer_for(content_type).load(content)
20
+ end
21
+
22
+ private
23
+
24
+ def serializer_for(content_type)
25
+ serializers.fetch(content_type) do
26
+ raise NotImplementedError.new(t('serializer_not_implemented', :content_type => content_type.inspect))
27
+ end
28
+ end
29
+
30
+ def serializers
31
+ @serializers ||= {}
32
+ end
33
+
34
+ module TextPlain
35
+ extend self
36
+
37
+ def dump(object)
38
+ object.to_s
39
+ end
40
+
41
+ def load(string)
42
+ string
43
+ end
44
+ end
45
+
46
+ module ApplicationJSON
47
+ extend self
48
+
49
+ def dump(object)
50
+ object.to_json(Riak.json_options)
51
+ end
52
+
53
+ def load(string)
54
+ Riak::JSON.parse(string)
55
+ end
56
+ end
57
+
58
+ Serializers['text/plain'] = TextPlain
59
+ Serializers['application/json'] = ApplicationJSON
60
+ Serializers['application/x-ruby-marshal'] = ::Marshal
61
+
62
+ YAML_MIME_TYPES = %w[
63
+ text/yaml
64
+ text/x-yaml
65
+ application/yaml
66
+ application/x-yaml
67
+ ]
68
+
69
+ YAML_MIME_TYPES.each do |mime_type|
70
+ Serializers[mime_type] = ::YAML
71
+ end
72
+ end
73
+ end
74
+