couchbase-jruby-client 0.1.0-java → 0.1.5-java

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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/.jrubyrc +722 -0
  3. data/.ruby-version +1 -1
  4. data/README.md +12 -90
  5. data/couchbase-jruby-client.gemspec +6 -6
  6. data/lib/couchbase/async.rb +18 -0
  7. data/lib/couchbase/bucket.rb +90 -180
  8. data/lib/couchbase/constants.rb +17 -0
  9. data/lib/couchbase/design_doc.rb +83 -0
  10. data/lib/couchbase/error.rb +31 -0
  11. data/lib/couchbase/operations/arithmetic.rb +17 -0
  12. data/lib/couchbase/operations/delete.rb +17 -0
  13. data/lib/couchbase/operations/design_docs.rb +99 -0
  14. data/lib/couchbase/operations/get.rb +73 -67
  15. data/lib/couchbase/operations/stats.rb +28 -1
  16. data/lib/couchbase/operations/store.rb +114 -97
  17. data/lib/couchbase/operations/touch.rb +49 -19
  18. data/lib/couchbase/operations/unlock.rb +209 -0
  19. data/lib/couchbase/operations/utils.rb +22 -10
  20. data/lib/couchbase/operations.rb +21 -0
  21. data/lib/couchbase/query.rb +92 -0
  22. data/lib/couchbase/result.rb +18 -1
  23. data/lib/couchbase/transcoder.rb +36 -42
  24. data/lib/couchbase/version.rb +18 -1
  25. data/lib/couchbase/view.rb +30 -172
  26. data/lib/couchbase/view_row.rb +38 -98
  27. data/lib/couchbase.rb +74 -72
  28. data/test/profile/.jrubyrc +722 -0
  29. data/test/profile/Gemfile +5 -5
  30. data/test/profile/benchmark.rb +106 -124
  31. data/test/profile/profile.rb +59 -0
  32. data/test/setup.rb +10 -145
  33. data/test/test_arithmetic.rb +54 -77
  34. data/test/test_async.rb +74 -102
  35. data/test/test_bucket.rb +74 -60
  36. data/test/test_cas.rb +10 -23
  37. data/test/test_couchbase.rb +11 -3
  38. data/test/test_delete.rb +41 -43
  39. data/test/test_design_docs.rb +62 -0
  40. data/test/test_errors.rb +9 -18
  41. data/test/test_format.rb +21 -31
  42. data/test/test_get.rb +107 -151
  43. data/test/test_query.rb +23 -0
  44. data/test/test_stats.rb +9 -24
  45. data/test/test_store.rb +52 -65
  46. data/test/test_timer.rb +4 -12
  47. data/test/test_touch.rb +26 -33
  48. data/test/test_unlock.rb +47 -78
  49. data/test/test_utils.rb +2 -11
  50. data/test/test_version.rb +5 -14
  51. data/test/test_view.rb +87 -0
  52. metadata +27 -14
  53. data/lib/couchbase/jruby/couchbase_client.rb +0 -22
  54. data/lib/couchbase/jruby/future.rb +0 -8
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
- # Couchbase::Jruby::Client
1
+ # Couchbase JRuby Client
2
2
 
3
- Attempt to recreate the ruby Couchbase cient api in Jruby and the
3
+ Attempt to recreate the ruby Couchbase client api in JRuby and the
4
4
  Couchbase Java SDK.
5
5
 
6
6
  ## Installation
@@ -19,12 +19,17 @@ Or install it yourself as:
19
19
 
20
20
  ## Caveat
21
21
 
22
- Please consider this project a very incomplete "alpha" version at best.
23
- Most of your typical operations such as connecting to a Couchbase cluster, storing
24
- and retrieving documents are working, though I'm currently skeptical on the performance
25
- compared to the native Java SDK without this wrapper.
22
+ Please consider this project a very incomplete "alpha" version at best. I'm getting close
23
+ to full coverage, though there are still some missing features. In fact, as I've gotten
24
+ more familiar with the differences between the native ruby api and the java, there are
25
+ definitely some features that don't make sense to implement.
26
26
 
27
- ## Usage (Copied from )
27
+ Ultimately hoping to get to 100% support of the couchbase-ruby-model gem.
28
+
29
+ ## Usage
30
+
31
+ See https://github.com/couchbase/couchbase-ruby-client for usage instructions as
32
+ they are largely the same. Important bits copied below:
28
33
 
29
34
  First of all you need to load library:
30
35
 
@@ -65,89 +70,6 @@ connection options via `Couchbase.connection_options`:
65
70
  Couchbase.bucket.name #=> "blog"
66
71
  Couchbase.bucket.set("foo", "bar") #=> 3289400178357895424
67
72
 
68
- The library supports both synchronous and asynchronous mode. In
69
- asynchronous mode all operations will return control to caller
70
- without blocking current thread. You can pass the block to method and it
71
- will be called with result when the operation will be completed. You
72
- need to run event loop when you scheduled your operations:
73
-
74
- c = Couchbase.connect
75
- c.run do |conn|
76
- conn.get("foo") {|ret| puts ret.value}
77
- conn.set("bar", "baz")
78
- end
79
-
80
- The handlers could be nested
81
-
82
- c.run do |conn|
83
- conn.get("foo") do |ret|
84
- conn.incr(ret.value, :initial => 0)
85
- end
86
- end
87
-
88
- The asynchronous callback receives instance of `Couchbase::Result` which
89
- responds to several methods to figure out what was happened:
90
-
91
- * `success?`. Returns `true` if operation succed.
92
-
93
- * `error`. Returns `nil` or exception object (subclass of
94
- `Couchbase::Error::Base`) if something went wrong.
95
-
96
- * `key`
97
-
98
- * `value`
99
-
100
- * `flags`
101
-
102
- * `cas`. The CAS version tag.
103
-
104
- * `node`. Node address. It is used in flush and stats commands.
105
-
106
- * `operation`. The symbol, representing an operation.
107
-
108
-
109
- To handle global errors in async mode `#on_error` callback should be
110
- used. It can be set in following fashions:
111
-
112
- c.on_error do |opcode, key, exc|
113
- # ...
114
- end
115
-
116
- handler = lambda {|opcode, key, exc| }
117
- c.on_error = handler
118
-
119
- By default connection uses `:quiet` mode. This mean it won't raise
120
- exceptions when the given key is not exists:
121
-
122
- c.get("missing-key") #=> nil
123
-
124
- It could be useful when you are trying to make you code a bit efficient
125
- by avoiding exception handling. (See `#add` and `#replace` operations).
126
- You can turn on these exception by passing `:quiet => false` when you
127
- are instantiating the connection or change corresponding attribute:
128
-
129
- c.quiet = false
130
- c.get("missing-key") #=> raise Couchbase::Error::NotFound
131
- c.get("missing-key", :quiet => true) #=> nil
132
-
133
- The library supports three different formats for representing values:
134
-
135
- * `:document` (default) format supports most of ruby types which could
136
- be mapped to JSON data (hashes, arrays, string, numbers). A future
137
- version will be able to run map/reduce queries on the values in the
138
- document form (hashes)
139
-
140
- * `:plain` This format avoids any conversions to be applied to your
141
- data, but your data should be passed as String. This is useful for
142
- building custom algorithms or formats. For example to implement a set:
143
- http://dustin.github.com/2011/02/17/memcached-set.html
144
-
145
- * `:marshal` Use this format if you'd like to transparently serialize your
146
- ruby object with standard `Marshal.dump` and `Marshal.load` methods
147
-
148
- The couchbase API is the superset of [Memcached binary protocol][5], so
149
- you can use its operations.
150
-
151
73
  ### Get
152
74
 
153
75
  val = c.get("foo")
@@ -12,19 +12,19 @@ Gem::Specification.new do |s|
12
12
  s.summary = %q{The unofficial jruby client library for use with Couchbase Server.}
13
13
  s.homepage = 'https://github.com/mje113/couchbase-jruby-client'
14
14
  s.license = 'Apache'
15
- s.platform = Gem::Platform::JAVA
15
+ s.platform = 'java'
16
16
 
17
17
  s.files = `git ls-files`.split($/)
18
18
  s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
19
19
  s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
20
  s.require_paths = ['lib']
21
21
 
22
- s.add_runtime_dependency 'multi_json', '~> 1.0'
23
- s.add_runtime_dependency 'atomic', '~> 1.1.14'
22
+ s.add_runtime_dependency 'multi_json', '~> 1.0'
23
+ s.add_runtime_dependency 'thread_safe', '~> 0.1.2'
24
24
 
25
- s.add_development_dependency 'bundler', '~> 1.3'
25
+ s.add_development_dependency 'bundler', '~> 1.3'
26
26
  s.add_development_dependency 'rake'
27
- s.add_development_dependency 'minitest', '~> 5.0.4'
27
+ s.add_development_dependency 'minitest', '~> 5.0.4'
28
+ s.add_development_dependency 'jrjackson', '~> 0.2.3'
28
29
  s.add_development_dependency 'active_support'
29
- s.add_development_dependency 'pry'
30
30
  end
@@ -1,3 +1,20 @@
1
+ # Author:: Mike Evans <mike@urlgonomics.com>
2
+ # Copyright:: 2013 Urlgonomics LLC.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
1
18
  require 'couchbase/async/callback'
2
19
  require 'couchbase/async/queue'
3
20
 
@@ -128,6 +145,7 @@ module Couchbase
128
145
  else
129
146
  register_callback(future, &block)
130
147
  end
148
+ future
131
149
  end
132
150
 
133
151
  def register_callback(future, &block)
@@ -1,31 +1,74 @@
1
- require 'pry'
1
+ # Author:: Mike Evans <mike@urlgonomics.com>
2
+ # Copyright:: 2013 Urlgonomics LLC.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
2
17
 
3
18
  module Couchbase
4
19
 
5
20
  class Bucket
6
21
 
7
- import java.io.IOException
8
- import java.net.SocketAddress
9
- import java.net.URI
10
- import java.net.URISyntaxException
11
- import java.util.ArrayList
12
- import java.util.LinkedList
13
- import java.util.List
14
- import java.util.concurrent.Future
15
- import java.util.concurrent.TimeUnit
16
- import com.couchbase.client.CouchbaseClient
17
- import com.couchbase.client.CouchbaseConnectionFactory
18
- import com.couchbase.client.protocol.views.Query
22
+ java_import java.io.IOException
23
+ java_import java.net.SocketAddress
24
+ java_import java.net.URI
25
+ java_import java.net.URISyntaxException
26
+ java_import java.util.ArrayList
27
+ java_import java.util.LinkedList
28
+ java_import java.util.List
29
+ java_import java.util.concurrent.Future
30
+ java_import java.util.concurrent.TimeUnit
31
+ java_import com.couchbase.client.CouchbaseClient
32
+ java_import com.couchbase.client.CouchbaseConnectionFactory
33
+ java_import com.couchbase.client.CouchbaseConnectionFactoryBuilder
19
34
 
20
35
  include Couchbase::Operations
21
36
  include Couchbase::Async
22
37
 
23
38
  attr_accessor :quiet, :hostname, :port, :pool, :bucket, :username,
24
- :password, :default_ttl, :timeout,
39
+ :password, :default_ttl, :timeout, :default_format,
25
40
  :default_arithmetic_init, :transcoder
26
41
 
27
42
  attr_reader :client, :key_prefix, :default_format
28
43
 
44
+ DEFAULT_OPTIONS = {
45
+ type: nil,
46
+ quiet: false,
47
+ hostname: 'localhost',
48
+ port: 8091,
49
+ pool: 'default',
50
+ bucket: 'default',
51
+ password: '',
52
+ engine: nil,
53
+ default_ttl: 0,
54
+ async: false,
55
+ default_arithmetic_init: 0,
56
+ default_flags: 0,
57
+ default_format: :document,
58
+ default_observe_timeout: 2_500_000,
59
+ on_error: nil,
60
+ on_connect: nil,
61
+ timeout: 0,
62
+ environment: nil,
63
+ key_prefix: nil,
64
+ node_list: nil,
65
+ destroying: 0,
66
+ connected: 0,
67
+ on_connect_proc: nil,
68
+ async_disconnect_hook_set: 0,
69
+ connected: false
70
+ }.freeze
71
+
29
72
  # Initialize new Bucket.
30
73
  #
31
74
  # @since 1.0.0
@@ -119,63 +162,30 @@ module Couchbase
119
162
  # @return [Bucket]
120
163
  #
121
164
  def initialize(url = nil, options = {})
122
- default_options = {
123
- type: nil,
124
- quiet: false,
125
- hostname: 'localhost',
126
- port: 8091,
127
- pool: 'default',
128
- bucket: 'default',
129
- password: '',
130
- engine: nil,
131
- default_ttl: 0,
132
- async: false,
133
- default_arithmetic_init: 0,
134
- default_flags: 0,
135
- default_format: :document,
136
- default_observe_timeout: 2500000,
137
- on_error: nil,
138
- on_connect: nil,
139
- timeout: 0,
140
- environment: nil,
141
- key_prefix: nil,
142
- node_list: nil,
143
- destroying: 0,
144
- connected: 0,
145
- on_connect_proc: nil,
146
- async_disconnect_hook_set: 0,
147
- connected: false
148
- }
149
-
150
165
  url_options = if url.is_a? String
151
- raise ArgumentError.new unless url =~ /^http:\/\//
152
-
166
+ fail ArgumentError.new unless url =~ /^http:\/\//
153
167
  uri = URI.new(url)
154
-
155
- {
156
- host: uri.host,
157
- port: uri.port,
158
- }.merge(path_to_pool_and_bucket(uri.path))
168
+ { hostname: uri.host, port: uri.port }.
169
+ merge(path_to_pool_and_bucket(uri.path))
159
170
  elsif url.nil?
160
171
  {}
161
172
  else
162
173
  url
163
174
  end
164
175
 
165
- connection_options = default_options.merge(options).merge(url_options)
176
+ options = Couchbase.normalize_connection_options(options)
177
+
178
+ connection_options = DEFAULT_OPTIONS.merge(url_options).merge(options)
166
179
 
167
180
  connection_options.each_pair do |key, value|
168
181
  instance_variable_set("@#{key}", value)
169
182
  end
170
183
 
171
- @transcoder = case @default_format
172
- when :document
173
- Transcoder::Document
174
- when :marshal
175
- Transcoder::Marshal
176
- when :plain
177
- Transcoder::Plain
178
- end
184
+ @transcoders = {
185
+ document: Transcoder::Document.new,
186
+ marshal: Transcoder::Marshal.new,
187
+ plain: Transcoder::Plain.new
188
+ }
179
189
 
180
190
  connect unless async?
181
191
  end
@@ -189,9 +199,6 @@ module Couchbase
189
199
  end
190
200
 
191
201
  def connect
192
- # TODO: doesn't work
193
- ObjectSpace.define_finalizer(self, -> conn { conn.disconnect })
194
-
195
202
  uris = if @node_list
196
203
  Array(@node_list).map { |n| URI.new(n) }
197
204
  else
@@ -199,14 +206,15 @@ module Couchbase
199
206
  end
200
207
 
201
208
  begin
202
- @connection_factory = CouchbaseConnectionFactory.new(uris, bucket.to_java_string, password.to_java_string)
203
- @client = CouchbaseClient.new(@connection_factory)
209
+ builder = CouchbaseConnectionFactoryBuilder.new
210
+ builder.setTranscoder(transcoder)
211
+ connection_factory = builder.buildCouchbaseConnection(uris, bucket.to_java_string, password.to_java_string)
212
+ @client = CouchbaseClient.new(connection_factory)
204
213
  @connected = true
205
- rescue Java::ComCouchbaseClientVbucket::ConfigurationException #,
206
- #Java::Io::IOException
207
- raise Couchbase::Error::Auth.new
214
+ rescue Java::ComCouchbaseClientVbucket::ConfigurationException
215
+ fail Couchbase::Error::Auth, 'Couchbase configurations are incorrect.'
208
216
  rescue java.net.ConnectException => e
209
- raise Couchbase::Error::Connect.new
217
+ fail Couchbase::Error::Connect
210
218
  end
211
219
 
212
220
  self
@@ -236,10 +244,14 @@ module Couchbase
236
244
  @connection_factory = nil
237
245
  @connected = false
238
246
  else
239
- raise Couchbase::Error::Connect.new
247
+ fail Couchbase::Error::Connect
240
248
  end
241
249
  end
242
250
 
251
+ def transcoder
252
+ @transcoders[@default_format]
253
+ end
254
+
243
255
  def on_connect(&block)
244
256
  @on_connect = block
245
257
  end
@@ -248,6 +260,14 @@ module Couchbase
248
260
  @on_error = block
249
261
  end
250
262
 
263
+ def version
264
+ {}.tap do |hash|
265
+ @client.getVersions.to_hash.each_pair do |ip, ver|
266
+ hash[ip.to_s] = ver
267
+ end
268
+ end
269
+ end
270
+
251
271
  # Compare and swap value.
252
272
  #
253
273
  # @since 1.0.0
@@ -313,126 +333,16 @@ module Couchbase
313
333
  block = Proc.new
314
334
  get(key) do |ret|
315
335
  val = block.call(ret) # get new value from caller
316
- set(ret.key, val, options.merge(:cas => ret.cas, :flags => ret.flags), &block)
336
+ set(ret.key, val, options.merge(:cas => ret.cas, &block))
317
337
  end
318
338
  else
319
339
  val, flags, ver = get(key, :extended => true)
320
340
  val = yield(val) # get new value from caller
321
- set(key, val, options.merge(:cas => ver, :flags => flags))
341
+ set(key, val, options.merge(:cas => ver))
322
342
  end
323
343
  end
324
344
  alias :compare_and_swap :cas
325
345
 
326
- # Fetch design docs stored in current bucket
327
- #
328
- # @since 1.2.0
329
- #
330
- # @return [Hash]
331
- def design_docs
332
- req = make_http_request("/pools/default/buckets/#{bucket}/ddocs",
333
- :type => :management, :extended => true)
334
- docmap = {}
335
- req.on_body do |body|
336
- res = MultiJson.load(body.value)
337
- res["rows"].each do |obj|
338
- if obj['doc']
339
- obj['doc']['value'] = obj['doc'].delete('json')
340
- end
341
- doc = DesignDoc.wrap(self, obj)
342
- key = doc.id.sub(/^_design\//, '')
343
- next if self.environment == :production && key =~ /dev_/
344
- docmap[key] = doc
345
- end
346
- yield(docmap) if block_given?
347
- end
348
- req.continue
349
- async? ? nil : docmap
350
- end
351
-
352
- # Update or create design doc with supplied views
353
- #
354
- # @since 1.2.0
355
- #
356
- # @param [Hash, IO, String] data The source object containing JSON
357
- # encoded design document. It must have +_id+ key set, this key
358
- # should start with +_design/+.
359
- #
360
- # @return [true, false]
361
- def save_design_doc(data)
362
- attrs = case data
363
- when String
364
- MultiJson.load(data)
365
- when IO
366
- MultiJson.load(data.read)
367
- when Hash
368
- data
369
- else
370
- raise ArgumentError, "Document should be Hash, String or IO instance"
371
- end
372
- rv = nil
373
- id = attrs.delete('_id').to_s
374
- attrs['language'] ||= 'javascript'
375
- if id !~ /\A_design\//
376
- rv = Result.new(:operation => :http_request,
377
- :key => id,
378
- :error => ArgumentError.new("'_id' key must be set and start with '_design/'."))
379
- yield rv if block_given?
380
- raise rv.error unless async?
381
- end
382
- req = make_http_request(id, :body => MultiJson.dump(attrs),
383
- :method => :put, :extended => true)
384
- req.on_body do |res|
385
- rv = res
386
- val = MultiJson.load(res.value)
387
- if block_given?
388
- if res.success? && val['error']
389
- res.error = Error::View.new("save_design_doc", val['error'])
390
- end
391
- yield(res)
392
- end
393
- end
394
- req.continue
395
- unless async?
396
- rv.success? or raise res.error
397
- end
398
- end
399
-
400
- # Delete design doc with given id and revision.
401
- #
402
- # @since 1.2.0
403
- #
404
- # @param [String] id Design document id. It might have '_design/'
405
- # prefix.
406
- #
407
- # @param [String] rev Document revision. It uses latest revision if
408
- # +rev+ parameter is nil.
409
- #
410
- # @return [true, false]
411
- def delete_design_doc(id, rev = nil)
412
- ddoc = design_docs[id.sub(/^_design\//, '')]
413
- unless ddoc
414
- yield nil if block_given?
415
- return nil
416
- end
417
- path = Utils.build_query(ddoc.id, :rev => rev || ddoc.meta['rev'])
418
- req = make_http_request(path, :method => :delete, :extended => true)
419
- rv = nil
420
- req.on_body do |res|
421
- rv = res
422
- val = MultiJson.load(res.value)
423
- if block_given?
424
- if res.success? && val['error']
425
- res.error = Error::View.new("delete_design_doc", val['error'])
426
- end
427
- yield(res)
428
- end
429
- end
430
- req.continue
431
- unless async?
432
- rv.success? or raise res.error
433
- end
434
- end
435
-
436
346
  # Delete contents of the bucket
437
347
  #
438
348
  # @see http://www.couchbase.com/docs/couchbase-manual-2.0/restapi-flushing-bucket.html
@@ -1,3 +1,20 @@
1
+ # Author:: Couchbase <info@couchbase.com>
2
+ # Copyright:: 2011, 2012 Couchbase, Inc.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
1
18
  module Couchbase
2
19
  module Constants # :nodoc:
3
20
  S_ID = 'id'.freeze
@@ -0,0 +1,83 @@
1
+ # Author:: Mike Evans <mike@urlgonomics.com>
2
+ # Copyright:: 2013 Urlgonomics LLC.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+
18
+ module Couchbase
19
+ class DesignDoc < ViewRow
20
+
21
+ # It isn't allowed to change design document ID after
22
+ # initialization
23
+ undef id=
24
+
25
+ def initialize(bucket, doc)
26
+ @all_views = {}
27
+ @bucket = bucket
28
+ @name = doc.name
29
+ @views = doc.views
30
+ @spatial = doc.spatial_views
31
+ @doc = {}
32
+ @views.each { |view| @all_views[view.name] = "#{@name}/_view/#{view.name}" }
33
+ @spatial.each { |view| @all_views[view.name] = "#{@name}/_spatial/#{view.name}" }
34
+ end
35
+
36
+ def method_missing(meth, *args)
37
+ if path = @all_views[meth.to_s]
38
+ View.new(@bucket, path, *args)
39
+ else
40
+ super
41
+ end
42
+ end
43
+
44
+ def respond_to_missing?(meth, *args)
45
+ @all_views[meth.to_s] || super
46
+ end
47
+
48
+ # The list of views defined or empty array
49
+ #
50
+ # @since 1.2.1
51
+ #
52
+ # @return [Array<View>]
53
+ attr_accessor :views
54
+
55
+ # The list of spatial views defined or empty array
56
+ #
57
+ # @since 1.2.1
58
+ #
59
+ # @return [Array<View>]
60
+ attr_accessor :spatial
61
+
62
+ # Check if the document has views defines
63
+ #
64
+ # @since 1.2.1
65
+ #
66
+ # @see DesignDoc#views
67
+ #
68
+ # @return [true, false] +true+ if the document have views
69
+ def has_views?
70
+ !@views.empty?
71
+ end
72
+
73
+ def inspect
74
+ desc = "#<#{self.class.name}:#{self.object_id}"
75
+ [:@id, :@views, :@spatial].each do |iv|
76
+ desc << " #{iv}=#{instance_variable_get(iv).inspect}"
77
+ end
78
+ desc << ">"
79
+ desc
80
+ end
81
+
82
+ end
83
+ end
@@ -1,7 +1,32 @@
1
+ # Author:: Mike Evans <mike@urlgonomics.com>
2
+ # Copyright:: 2013 Urlgonomics LLC.
3
+ # License:: Apache License, Version 2.0
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
1
17
 
2
18
  module Couchbase
3
19
  module Error
4
20
  class Base < Exception
21
+ attr_accessor :cas, :error, :inner_exception, :key, :operation, :status
22
+
23
+ def to_s
24
+ if inner_exception
25
+ inner_exception.to_s
26
+ else
27
+ super
28
+ end
29
+ end
5
30
  end
6
31
 
7
32
  class Connect < Base
@@ -24,5 +49,11 @@ module Couchbase
24
49
 
25
50
  class ValueFormat < Base
26
51
  end
52
+
53
+ class TemporaryFail < Base
54
+ end
55
+
56
+ class NotStored < Base
57
+ end
27
58
  end
28
59
  end