couchrest 1.1.0.pre2 → 1.1.0.pre3

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/.gitignore CHANGED
@@ -4,3 +4,4 @@ pkg
4
4
  *.swp
5
5
  *.gem
6
6
  Gemfile.lock
7
+ *.rvmrc
data/Rakefile CHANGED
@@ -1,33 +1,20 @@
1
1
  require 'rubygems'
2
2
  require 'bundler'
3
- Bundler::GemHelper.install_tasks
4
-
5
- require 'rake'
3
+ require 'rspec/core/rake_task'
6
4
  require "rake/rdoctask"
7
5
 
8
- $LOAD_PATH.unshift File.expand_path("../lib", __FILE__)
9
- require 'couchrest'
10
-
11
- begin
12
- require 'spec/rake/spectask'
13
- rescue LoadError
14
- puts <<-EOS
15
- To use rspec for testing you must install rspec gem:
16
- gem install rspec
17
- EOS
18
- exit(0)
19
- end
6
+ Bundler::GemHelper.install_tasks
20
7
 
21
8
  desc "Run all specs"
22
- Spec::Rake::SpecTask.new('spec') do |t|
23
- t.spec_opts = ["--color"]
24
- t.spec_files = FileList['spec/**/*_spec.rb']
9
+ RSpec::Core::RakeTask.new(:spec) do |spec|
10
+ spec.rspec_opts = ["--color"]
11
+ spec.pattern = 'spec/**/*_spec.rb'
25
12
  end
26
13
 
27
14
  desc "Print specdocs"
28
- Spec::Rake::SpecTask.new(:doc) do |t|
29
- t.spec_opts = ["--format", "specdoc"]
30
- t.spec_files = FileList['spec/*_spec.rb']
15
+ RSpec::Core::RakeTask.new(:doc) do |spec|
16
+ spec.rspec_opts = ["--format", "specdoc"]
17
+ spec.pattern = 'spec/*_spec.rb'
31
18
  end
32
19
 
33
20
  desc "Generate the rdoc"
@@ -40,3 +27,12 @@ end
40
27
 
41
28
  desc "Run the rspec"
42
29
  task :default => :spec
30
+
31
+ module Rake
32
+ def self.remove_task(task_name)
33
+ Rake.application.instance_variable_get('@tasks').delete(task_name.to_s)
34
+ end
35
+ end
36
+
37
+ Rake.remove_task("github:release")
38
+ Rake.remove_task("release")
@@ -1,8 +1,8 @@
1
1
  # -*- encoding: utf-8 -*-
2
-
2
+ require File.join(File.dirname(__FILE__),'lib','couchrest','version')
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{couchrest}
5
- s.version = "1.1.0.pre2"
5
+ s.version = CouchRest::VERSION
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new("> 1.3.1") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["J. Chris Anderson", "Matt Aimonetti", "Marcos Tapajos", "Will Leinweber", "Sam Lown"]
@@ -28,7 +28,7 @@ Gem::Specification.new do |s|
28
28
 
29
29
  s.add_dependency(%q<rest-client>, ["~> 1.6.1"])
30
30
  s.add_dependency(%q<mime-types>, ["~> 1.15"])
31
- s.add_dependency(%q<json>, ["~> 1.5.1"])
32
- s.add_development_dependency(%q<rspec>, "~> 1.3.0")
33
-
31
+ s.add_dependency(%q<multi_json>, ["~> 1.0.0"])
32
+ s.add_development_dependency(%q<json>, ["~> 1.5.1"])
33
+ s.add_development_dependency(%q<rspec>, "~> 2.6.0")
34
34
  end
@@ -1,3 +1,10 @@
1
+ == 1.1.0.pre3 - 2011-06-06
2
+
3
+ * Major changes
4
+ * CouchRest::Response removed
5
+ * CouchRest::Document now forwards key Hash methods (instead of inheritance) (thanks @karmi for prompting the discussion: https://github.com/crx/tire/commit/abf491d0035843a0a7395c8c32b9b7c2120071f9)
6
+ * Support multiple JSON gems with multi_json (thanks chrisdurtschi)
7
+
1
8
  == 1.1.0.pre2 - 2011-04-08
2
9
 
3
10
  * Major changes
@@ -13,24 +13,24 @@
13
13
  # limitations under the License.
14
14
 
15
15
  require 'rest_client'
16
- require 'json'
16
+ require 'multi_json'
17
17
 
18
18
  # Not sure why this is required, so removed until a reason is found!
19
19
  $:.unshift File.dirname(__FILE__) unless
20
20
  $:.include?(File.dirname(__FILE__)) ||
21
21
  $:.include?(File.expand_path(File.dirname(__FILE__)))
22
-
22
+
23
23
  require 'couchrest/monkeypatches'
24
24
  require 'couchrest/rest_api'
25
25
  require 'couchrest/support/inheritable_attributes'
26
+ require 'couchrest/version'
27
+
28
+ require 'forwardable'
26
29
 
27
30
  # = CouchDB, close to the metal
28
31
  module CouchRest
29
- VERSION = '1.0.1'
30
-
31
32
  autoload :Server, 'couchrest/server'
32
33
  autoload :Database, 'couchrest/database'
33
- autoload :Response, 'couchrest/response'
34
34
  autoload :Document, 'couchrest/document'
35
35
  autoload :Design, 'couchrest/design'
36
36
  autoload :Model, 'couchrest/model'
@@ -38,11 +38,11 @@ module CouchRest
38
38
  autoload :Streamer, 'couchrest/helper/streamer'
39
39
  autoload :Attachments, 'couchrest/helper/attachments'
40
40
  autoload :Upgrade, 'couchrest/helper/upgrade'
41
-
41
+
42
42
  # we extend CouchRest with the RestAPI module which gives us acess to
43
43
  # the get, post, put, delete and copy
44
- CouchRest.extend(::RestAPI)
45
-
44
+ CouchRest.extend(::CouchRest::RestAPI)
45
+
46
46
  # The CouchRest module methods handle the basic JSON serialization
47
47
  # and deserialization, as well as query parameters. The module also includes
48
48
  # some helpers for tasks like instantiating a new Database or Server instance.
@@ -53,7 +53,7 @@ module CouchRest
53
53
  def new(*opts)
54
54
  Server.new(*opts)
55
55
  end
56
-
56
+
57
57
  def parse url
58
58
  case url
59
59
  when /^(https?:\/\/)(.*)\/(.*)\/(.*)/
@@ -111,7 +111,7 @@ module CouchRest
111
111
  def paramify_url url, params = {}
112
112
  if params && !params.empty?
113
113
  query = params.collect do |k,v|
114
- v = v.to_json if %w{key startkey endkey}.include?(k.to_s)
114
+ v = MultiJson.encode(v) if %w{key startkey endkey}.include?(k.to_s)
115
115
  "#{k}=#{CGI.escape(v.to_s)}"
116
116
  end.join("&")
117
117
  url = "#{url}?#{query}"
@@ -75,7 +75,7 @@ module CouchRest
75
75
 
76
76
  # == Retrieving and saving single documents
77
77
 
78
- # GET a document from CouchDB, by id. Returns a Ruby Hash.
78
+ # GET a document from CouchDB, by id. Returns a Document or Design.
79
79
  def get(id, params = {})
80
80
  slug = escape_docid(id)
81
81
  url = CouchRest.paramify_url("#{@root}/#{slug}", params)
@@ -118,13 +118,13 @@ module CouchRest
118
118
  if bulk
119
119
  @bulk_save_cache << doc
120
120
  bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit
121
- return {"ok" => true} # Compatibility with Document#save
121
+ return {'ok' => true} # Compatibility with Document#save
122
122
  elsif !bulk && @bulk_save_cache.length > 0
123
123
  bulk_save
124
124
  end
125
125
  result = if doc['_id']
126
126
  slug = escape_docid(doc['_id'])
127
- begin
127
+ begin
128
128
  uri = "#{@root}/#{slug}"
129
129
  uri << "?batch=ok" if batch
130
130
  CouchRest.put uri, doc
@@ -186,11 +186,11 @@ module CouchRest
186
186
  # If <tt>bulk</tt> is true (false by default) the deletion is recorded for bulk-saving (bulk-deletion :) later.
187
187
  # Bulk saving happens automatically when #bulk_save_cache limit is exceded, or on the next non bulk save.
188
188
  def delete_doc(doc, bulk = false)
189
- raise ArgumentError, "_id and _rev required for deleting" unless doc['_id'] && doc['_rev']
189
+ raise ArgumentError, "_id and _rev required for deleting" unless doc['_id'] && doc['_rev']
190
190
  if bulk
191
- @bulk_save_cache << { '_id' => doc['_id'], '_rev' => doc['_rev'], '_deleted' => true }
191
+ @bulk_save_cache << { '_id' => doc['_id'], '_rev' => doc['_rev'], :_deleted => true }
192
192
  return bulk_save if @bulk_save_cache.length >= @bulk_save_cache_limit
193
- return { "ok" => true } # Mimic the non-deferred version
193
+ return {'ok' => true} # Mimic the non-deferred version
194
194
  end
195
195
  slug = escape_docid(doc['_id'])
196
196
  CouchRest.delete "#{@root}/#{slug}?rev=#{doc['_rev']}"
@@ -201,7 +201,7 @@ module CouchRest
201
201
  # hash with a '_rev' key
202
202
  def copy_doc(doc, dest)
203
203
  raise ArgumentError, "_id is required for copying" unless doc['_id']
204
- slug = escape_docid(doc['_id'])
204
+ slug = escape_docid(doc['_id'])
205
205
  destination = if dest.respond_to?(:has_key?) && dest['_id'] && dest['_rev']
206
206
  "#{dest['_id']}?rev=#{dest['_rev']}"
207
207
  else
@@ -243,7 +243,7 @@ module CouchRest
243
243
  # Query a CouchDB view as defined by a <tt>_design</tt> document. Accepts
244
244
  # paramaters as described in http://wiki.apache.org/couchdb/HttpViewApi
245
245
  def view(name, params = {}, payload = {}, &block)
246
- payload[:keys] = params.delete(:keys) if params[:keys]
246
+ payload['keys'] = params.delete(:keys) if params[:keys]
247
247
  # Try recognising the name, otherwise assume already prepared
248
248
  view_path = name =~ /^([^_].+?)\/(.*)$/ ? "_design/#{$1}/_view/#{$2}" : name
249
249
  url = CouchRest.paramify_url "#{@root}/#{view_path}", params
@@ -306,14 +306,14 @@ module CouchRest
306
306
  # GET an attachment directly from CouchDB
307
307
  def fetch_attachment(doc, name)
308
308
  uri = url_for_attachment(doc, name)
309
- RestClient.get uri, CouchRest.default_headers
309
+ CouchRest.get uri, :raw => true
310
310
  end
311
311
 
312
312
  # PUT an attachment directly to CouchDB
313
313
  def put_attachment(doc, name, file, options = {})
314
314
  docid = escape_docid(doc['_id'])
315
315
  uri = url_for_attachment(doc, name)
316
- JSON.parse(RestClient.put(uri, file, CouchRest.default_headers.merge(options)))
316
+ CouchRest.put(uri, file, options.merge(:raw => true))
317
317
  end
318
318
 
319
319
  # DELETE an attachment directly from CouchDB
@@ -343,12 +343,12 @@ module CouchRest
343
343
  raise ArgumentError, "must provide a target or source option" unless (options.key?(:target) || options.key?(:source))
344
344
  payload = options
345
345
  if options.has_key?(:target)
346
- payload[:source] = other_db.root
346
+ payload['source'] = other_db.root
347
347
  else
348
- payload[:target] = other_db.root
348
+ payload['target'] = other_db.root
349
349
  end
350
- payload[:continuous] = continuous
351
- payload[:doc_ids] = options[:doc_ids] if options[:doc_ids]
350
+ payload['continuous'] = continuous
351
+ payload['doc_ids'] = options[:doc_ids] if options[:doc_ids]
352
352
  CouchRest.post "#{@host}/_replicate", payload
353
353
  end
354
354
 
@@ -1,11 +1,12 @@
1
- module CouchRest
1
+ module CouchRest
2
2
  class Design < Document
3
+
3
4
  def view_by *keys
4
5
  opts = keys.pop if keys.last.is_a?(Hash)
5
6
  opts ||= {}
6
7
  self['views'] ||= {}
7
8
  method_name = "by_#{keys.join('_and_')}"
8
-
9
+
9
10
  if opts[:map]
10
11
  view = {}
11
12
  view['map'] = opts.delete(:map)
@@ -31,7 +32,7 @@ JAVASCRIPT
31
32
  self['views'][method_name]['couchrest-defaults'] = opts unless opts.empty?
32
33
  method_name
33
34
  end
34
-
35
+
35
36
  # Dispatches to any named view.
36
37
  # (using the database where this design doc was saved)
37
38
  def view view_name, query={}, &block
@@ -1,38 +1,89 @@
1
- require 'delegate'
2
1
 
3
- module CouchRest
4
- class Document < Response
2
+ #
3
+ # CouchRest::Document
4
+ #
5
+ # Provides basic functions for controlling documents returned from
6
+ # the CouchDB database and provides methods to act as a wrapper around
7
+ # a Hash of @_attributes.
8
+ #
9
+ # The idea is to provide the basic functionality of a Hash, just
10
+ # enought to support the needs of CouchRest, but not inherit all
11
+ # of the functionality found in a basic Hash.
12
+ #
13
+ # A Response is similar to Rails' HashWithIndifferentAccess as all
14
+ # requests will convert the keys into Symbols and be stored in the
15
+ # master hash as such.
16
+ #
17
+
18
+ module CouchRest
19
+ class Document
20
+ extend Forwardable
5
21
  include CouchRest::Attachments
6
22
  extend CouchRest::InheritableAttributes
7
-
23
+
8
24
  couchrest_inheritable_accessor :database
9
25
  attr_accessor :database
10
-
11
- # override the CouchRest::Model-wide default_database
12
- # This is not a thread safe operation, do not change the model
13
- # database at runtime.
14
- def self.use_database(db)
15
- self.database = db
16
- end
17
-
26
+
27
+ # Initialize a new CouchRest Document and prepare
28
+ # a hidden attributes hash.
29
+ #
30
+ # When inherting a Document, it is essential that the
31
+ # super method is called before you own changes to ensure
32
+ # that the attributes hash has been initialized before
33
+ # you attempt to use it.
34
+ def initialize(attrs = nil)
35
+ @_attributes = {}
36
+ attrs.each{|k,v| self[k] = v} unless attrs.nil?
37
+ end
38
+
39
+ # Hash equivilent methods to access the attributes
40
+
41
+ def_delegators :@_attributes, :to_a, :==, :eql?, :keys, :values, :each,
42
+ :reject, :reject!, :empty?, :clear, :merge, :merge!,
43
+ :encode_json, :as_json, :to_json
44
+
45
+ def []=(key, value)
46
+ @_attributes[key.to_s] = value
47
+ end
48
+ def [](key)
49
+ @_attributes[key.to_s]
50
+ end
51
+ def has_key?(key)
52
+ @_attributes.has_key?(key.to_s)
53
+ end
54
+ def delete(key)
55
+ @_attributes.delete(key.to_s)
56
+ end
57
+ def dup
58
+ new = super
59
+ @_attributes = @_attributes.dup
60
+ new
61
+ end
62
+ def clone
63
+ new = super
64
+ @_attributes = @_attributes.dup
65
+ new
66
+ end
67
+ def to_hash
68
+ @_attributes
69
+ end
70
+
18
71
  def id
19
72
  self['_id']
20
73
  end
21
-
22
74
  def id=(id)
23
75
  self['_id'] = id
24
76
  end
25
-
26
77
  def rev
27
78
  self['_rev']
28
79
  end
29
-
80
+
30
81
  # returns true if the document has never been saved
31
82
  def new?
32
83
  !rev
33
84
  end
34
85
  alias :new_document? :new?
35
-
86
+
36
87
  # Saves the document to the db using create or update. Also runs the :save
37
88
  # callbacks. Sets the <tt>_id</tt> and <tt>_rev</tt> fields based on
38
89
  # CouchDB's response.
@@ -57,7 +108,7 @@ module CouchRest
57
108
  end
58
109
  result['ok']
59
110
  end
60
-
111
+
61
112
  # copies the document to a new id. If the destination id currently exists, a rev must be provided.
62
113
  # <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
63
114
  # hash with a '_rev' key
@@ -66,7 +117,7 @@ module CouchRest
66
117
  result = database.copy_doc(self, dest)
67
118
  result['ok']
68
119
  end
69
-
120
+
70
121
  # Returns the CouchDB uri for the document
71
122
  def uri(append_rev = false)
72
123
  return nil if new?
@@ -78,12 +129,29 @@ module CouchRest
78
129
  end
79
130
  couch_uri
80
131
  end
81
-
132
+
82
133
  # Returns the document's database
83
134
  def database
84
135
  @database || self.class.database
85
136
  end
86
-
137
+
138
+ # Provide details of the current keys in the reponse. Based on ActiveRecord::Base.
139
+ def inspect
140
+ attributes_as_nice_string = self.keys.collect { |key|
141
+ "#{key}: #{self[key].inspect}"
142
+ }.compact.join(", ")
143
+ "#<#{self.class} #{attributes_as_nice_string}>"
144
+ end
145
+
146
+ class << self
147
+ # override the CouchRest::Model-wide default_database
148
+ # This is not a thread safe operation, do not change the model
149
+ # database at runtime.
150
+ def use_database(db)
151
+ self.database = db
152
+ end
153
+ end
154
+
87
155
  end
88
-
156
+
89
157
  end
@@ -16,7 +16,7 @@ module CouchRest
16
16
  end
17
17
 
18
18
  def post(url, params = {}, &block)
19
- open_pipe("curl #{default_curl_opts} -d \"#{escape_quotes(params.to_json)}\" \"#{url}\"", &block)
19
+ open_pipe("curl #{default_curl_opts} -d \"#{escape_quotes(MultiJson.encode(params))}\" \"#{url}\"", &block)
20
20
  end
21
21
 
22
22
  protected
@@ -40,7 +40,7 @@ module CouchRest
40
40
  def parse_line line
41
41
  return nil unless line
42
42
  if /(\{.*\}),?/.match(line.chomp)
43
- JSON.parse($1)
43
+ MultiJson.decode($1)
44
44
  end
45
45
  end
46
46
 
@@ -49,7 +49,7 @@ module CouchRest
49
49
  parts = first.split(',')
50
50
  parts.pop
51
51
  line = parts.join(',')
52
- JSON.parse("#{line}}")
52
+ MultiJson.decode("#{line}}")
53
53
  rescue
54
54
  nil
55
55
  end
@@ -68,7 +68,7 @@ module RestClient
68
68
 
69
69
  def self.post(uri, payload, headers=nil)
70
70
  start_query = Time.now
71
- log = {:method => :post, :uri => uri, :payload => (payload ? (JSON.load(payload) rescue 'parsing error') : nil), :headers => headers}
71
+ log = {:method => :post, :uri => uri, :payload => (payload ? (MultiJson.decode(payload) rescue 'parsing error') : nil), :headers => headers}
72
72
  response = super(uri, payload, headers=nil)
73
73
  end_query = Time.now
74
74
  log[:duration] = (end_query - start_query)
@@ -78,7 +78,7 @@ module RestClient
78
78
 
79
79
  def self.put(uri, payload, headers=nil)
80
80
  start_query = Time.now
81
- log = {:method => :put, :uri => uri, :payload => (payload ? (JSON.load(payload) rescue 'parsing error') : nil), :headers => headers}
81
+ log = {:method => :put, :uri => uri, :payload => (payload ? (MultiJson.decode(payload) rescue 'parsing error') : nil), :headers => headers}
82
82
  response = super(uri, payload, headers=nil)
83
83
  end_query = Time.now
84
84
  log[:duration] = (end_query - start_query)
@@ -1,59 +1,77 @@
1
- module RestAPI
1
+ module CouchRest
2
2
 
3
- def default_headers
4
- {
5
- :content_type => :json,
6
- :accept => :json
7
- }
8
- end
3
+ module RestAPI
4
+
5
+ def default_headers
6
+ {
7
+ :content_type => :json,
8
+ :accept => :json
9
+ }
10
+ end
9
11
 
10
- def put(uri, doc = nil)
11
- payload = doc.to_json if doc
12
- begin
13
- JSON.parse(RestClient.put(uri, payload, default_headers))
14
- rescue Exception => e
15
- if $DEBUG
16
- raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
17
- else
18
- raise e
12
+ def get(uri, options = {})
13
+ begin
14
+ parse_response(RestClient.get(uri, default_headers), options.dup)
15
+ rescue => e
16
+ if $DEBUG
17
+ raise "Error while sending a GET request #{uri}\n: #{e}"
18
+ else
19
+ raise e
20
+ end
19
21
  end
20
22
  end
21
- end
22
23
 
23
- def get(uri)
24
- begin
25
- JSON.parse(RestClient.get(uri, default_headers), :max_nesting => false)
26
- rescue => e
27
- if $DEBUG
28
- raise "Error while sending a GET request #{uri}\n: #{e}"
29
- else
30
- raise e
24
+ def put(uri, doc = nil, options = {})
25
+ opts = options.dup
26
+ payload = payload_from_doc(doc, opts)
27
+ begin
28
+ parse_response(RestClient.put(uri, payload, default_headers.merge(opts)), opts)
29
+ rescue Exception => e
30
+ if $DEBUG
31
+ raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
32
+ else
33
+ raise e
34
+ end
31
35
  end
32
36
  end
33
- end
34
37
 
35
- def post(uri, doc = nil)
36
- payload = doc.to_json if doc
37
- begin
38
- JSON.parse(RestClient.post(uri, payload, default_headers))
39
- rescue Exception => e
40
- if $DEBUG
41
- raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
42
- else
43
- raise e
38
+ def post(uri, doc = nil, options = {})
39
+ opts = options.dup
40
+ payload = payload_from_doc(doc, opts)
41
+ begin
42
+ parse_response(RestClient.post(uri, payload, default_headers.merge(opts)), opts)
43
+ rescue Exception => e
44
+ if $DEBUG
45
+ raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
46
+ else
47
+ raise e
48
+ end
44
49
  end
45
50
  end
46
- end
47
51
 
48
- def delete(uri)
49
- JSON.parse(RestClient.delete(uri, default_headers))
50
- end
52
+ def delete(uri, options = {})
53
+ parse_response(RestClient.delete(uri, default_headers), options.dup)
54
+ end
51
55
 
52
- def copy(uri, destination)
53
- JSON.parse(RestClient::Request.execute( :method => :copy,
54
- :url => uri,
55
- :headers => default_headers.merge('Destination' => destination)
56
- ).to_s)
57
- end
56
+ def copy(uri, destination, options = {})
57
+ parse_response(RestClient::Request.execute( :method => :copy,
58
+ :url => uri,
59
+ :headers => default_headers.merge('Destination' => destination)
60
+ ).to_s, options)
61
+ end
62
+
63
+ protected
64
+
65
+ # Check if the provided doc is nil or special IO device or temp file. If not,
66
+ # encode it into a string.
67
+ def payload_from_doc(doc, opts = {})
68
+ (opts.delete(:raw) || doc.nil? || doc.is_a?(IO) || doc.is_a?(Tempfile)) ? doc : MultiJson.encode(doc)
69
+ end
58
70
 
71
+ # Parse the response provided.
72
+ def parse_response(result, opts = {})
73
+ opts.delete(:raw) ? result : MultiJson.decode(result, opts.update(:max_nesting => false))
74
+ end
75
+
76
+ end
59
77
  end
@@ -0,0 +1,3 @@
1
+ module CouchRest
2
+ VERSION = '1.1.0.pre3'
3
+ end
@@ -257,7 +257,7 @@ describe CouchRest::Database do
257
257
  ])
258
258
  rescue RestClient::RequestFailed => e
259
259
  # soon CouchDB will provide _which_ docs conflicted
260
- JSON.parse(e.response.body)['error'].should == 'conflict'
260
+ MultiJson.decode(e.response.body)['error'].should == 'conflict'
261
261
  end
262
262
  end
263
263
  end
@@ -9,6 +9,36 @@ describe CouchRest::Document do
9
9
  @db = @couch.database!(TESTDB)
10
10
  end
11
11
 
12
+ describe "#new" do
13
+ it "should not be a Hash" do
14
+ @doc = CouchRest::Document.new
15
+ @doc.class.should eql(CouchRest::Document)
16
+ @doc.is_a?(Hash).should be_false
17
+ end
18
+
19
+ it "should be possible to initialize a new Document with attributes" do
20
+ @doc = CouchRest::Document.new('foo' => 'bar', :test => 'foo')
21
+ @doc['foo'].should eql('bar')
22
+ @doc['test'].should eql('foo')
23
+ end
24
+
25
+ it "should accept new with _id" do
26
+ @doc = CouchRest::Document.new('_id' => 'sample', 'foo' => 'bar')
27
+ @doc['_id'].should eql('sample')
28
+ @doc['foo'].should eql('bar')
29
+ end
30
+ end
31
+
32
+ describe "hash methods" do
33
+ it "should respond to forwarded hash methods" do
34
+ @doc = CouchRest::Document.new(:foo => 'bar')
35
+ [:to_a, :==, :eql?, :keys, :values, :each, :reject, :reject!, :empty?,
36
+ :clear, :merge, :merge!, :encode_json, :as_json, :to_json].each do |call|
37
+ @doc.should respond_to(call)
38
+ end
39
+ end
40
+ end
41
+
12
42
  describe "[]=" do
13
43
  before(:each) do
14
44
  @doc = CouchRest::Document.new
@@ -29,6 +59,57 @@ describe CouchRest::Document do
29
59
  end
30
60
  end
31
61
 
62
+ describe "#has_key?" do
63
+ before :each do
64
+ @doc = CouchRest::Document.new
65
+ end
66
+ it "should confirm existance of key" do
67
+ @doc[:test] = 'example'
68
+ @doc.has_key?('test').should be_true
69
+ @doc.has_key?(:test).should be_true
70
+ end
71
+ it "should deny existance of key" do
72
+ @doc.has_key?(:bardom).should be_false
73
+ @doc.has_key?('bardom').should be_false
74
+ end
75
+ end
76
+
77
+ describe "#dup" do
78
+ it "should also clone the attributes" do
79
+ @doc = CouchRest::Document.new('foo' => 'bar')
80
+ @doc2 = @doc.dup
81
+ @doc2.delete('foo')
82
+ @doc2['foo'].should be_nil
83
+ @doc['foo'].should eql('bar')
84
+ end
85
+ end
86
+
87
+ describe "#clone" do
88
+ it "should also clone the attributes" do
89
+ @doc = CouchRest::Document.new('foo' => 'bar')
90
+ @doc2 = @doc.clone
91
+ @doc2.delete('foo')
92
+ @doc2['foo'].should be_nil
93
+ @doc['foo'].should eql('bar')
94
+ end
95
+ end
96
+
97
+
98
+ describe "#inspect" do
99
+ it "should provide a string of keys and values of the Response" do
100
+ @doc = CouchRest::Document.new('foo' => 'bar')
101
+ @doc.inspect.should eql("#<CouchRest::Document foo: \"bar\">")
102
+ end
103
+ end
104
+
105
+ describe "responding to Hash methods" do
106
+ it "should delegate requests" do
107
+ @doc = CouchRest::Document.new('foo' => 'bar')
108
+ @doc.keys.should eql(['foo'])
109
+ @doc.values.should eql(['bar'])
110
+ end
111
+ end
112
+
32
113
  describe "default database" do
33
114
  before(:each) do
34
115
  Video.use_database nil
@@ -220,7 +301,7 @@ describe "dealing with attachments" do
220
301
  response = @db.save_doc({'key' => 'value'})
221
302
  @doc = @db.get(response['id'])
222
303
  end
223
-
304
+
224
305
  def append_attachment(name='test.html', attach=@attach)
225
306
  @doc['_attachments'] ||= {}
226
307
  @doc['_attachments'][name] = {
@@ -230,50 +311,50 @@ describe "dealing with attachments" do
230
311
  @doc.save
231
312
  @rev = @doc['_rev']
232
313
  end
233
-
314
+
234
315
  describe "PUTing an attachment directly to the doc" do
235
316
  before do
236
317
  @doc.put_attachment('test.html', @attach)
237
318
  end
238
-
319
+
239
320
  it "is there" do
240
321
  @db.fetch_attachment(@doc, 'test.html').should == @attach
241
322
  end
242
-
323
+
243
324
  it "updates the revision" do
244
- @doc['_rev'].should_not == @rev
325
+ @doc[:_rev].should_not == @rev
245
326
  end
246
-
327
+
247
328
  it "updates attachments" do
248
329
  @attach2 = "<html><head><title>My Doc</title></head><body><p>Is Different.</p></body></html>"
249
330
  @doc.put_attachment('test.html', @attach2)
250
331
  @db.fetch_attachment(@doc, 'test.html').should == @attach2
251
332
  end
252
333
  end
253
-
334
+
254
335
  describe "fetching an attachment from a doc directly" do
255
336
  before do
256
337
  append_attachment
257
338
  end
258
-
339
+
259
340
  it "pulls the attachment" do
260
341
  @doc.fetch_attachment('test.html').should == @attach
261
342
  end
262
343
  end
263
-
344
+
264
345
  describe "deleting an attachment from a doc directly" do
265
346
  before do
266
347
  append_attachment
267
348
  @doc.delete_attachment('test.html')
268
349
  end
269
-
350
+
270
351
  it "removes it" do
271
352
  lambda { @db.fetch_attachment(@doc, 'test.html').should }.should raise_error(RestClient::ResourceNotFound)
272
353
  end
273
-
354
+
274
355
  it "updates the revision" do
275
- @doc['_rev'].should_not == @rev
356
+ @doc[:_rev].should_not == @rev
276
357
  end
277
358
  end
278
-
359
+
279
360
  end
@@ -7,6 +7,11 @@ describe CouchRest::Pager do
7
7
  @db.delete! rescue nil
8
8
  @db = @cr.create_db(TESTDB) rescue nil
9
9
  @pager = CouchRest::Pager.new(@db)
10
+ @docs = []
11
+ 100.times do |i|
12
+ @docs << ({:number => (i % 10)})
13
+ end
14
+ @db.bulk_save(@docs)
10
15
  end
11
16
 
12
17
  after(:all) do
@@ -21,13 +26,6 @@ describe CouchRest::Pager do
21
26
  end
22
27
 
23
28
  describe "paging all docs" do
24
- before(:all) do
25
- @docs = []
26
- 100.times do |i|
27
- @docs << ({:number => (i % 10)})
28
- end
29
- @db.bulk_save(@docs)
30
- end
31
29
  it "should yield total_docs / limit times" do
32
30
  n = 0
33
31
  @pager.all_docs(10) do |doc|
@@ -55,11 +53,6 @@ describe CouchRest::Pager do
55
53
 
56
54
  describe "Pager with a view and docs" do
57
55
  before(:all) do
58
- @docs = []
59
- 100.times do |i|
60
- @docs << ({:number => (i % 10)})
61
- end
62
- @db.bulk_save(@docs)
63
56
  @db.save_doc({
64
57
  '_id' => '_design/magic',
65
58
  'views' => {
@@ -119,4 +112,4 @@ describe CouchRest::Pager do
119
112
  results[9].should be_nil
120
113
  end
121
114
  end
122
- end
115
+ end
@@ -1,5 +1,6 @@
1
+ require "bundler/setup"
1
2
  require "rubygems"
2
- require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
3
+ require "rspec"
3
4
 
4
5
  require File.join(File.dirname(__FILE__), '..','lib','couchrest')
5
6
  # check the following file to see how to use the spec'd features.
@@ -21,7 +22,7 @@ def reset_test_db!
21
22
  DB
22
23
  end
23
24
 
24
- Spec::Runner.configure do |config|
25
+ RSpec.configure do |config|
25
26
  config.before(:all) { reset_test_db! }
26
27
 
27
28
  config.after(:all) do
metadata CHANGED
@@ -1,13 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: couchrest
3
3
  version: !ruby/object:Gem::Version
4
- prerelease: true
5
- segments:
6
- - 1
7
- - 1
8
- - 0
9
- - pre2
10
- version: 1.1.0.pre2
4
+ prerelease: 6
5
+ version: 1.1.0.pre3
11
6
  platform: ruby
12
7
  authors:
13
8
  - J. Chris Anderson
@@ -30,10 +25,6 @@ dependencies:
30
25
  requirements:
31
26
  - - ~>
32
27
  - !ruby/object:Gem::Version
33
- segments:
34
- - 1
35
- - 6
36
- - 1
37
28
  version: 1.6.1
38
29
  type: :runtime
39
30
  version_requirements: *id001
@@ -45,42 +36,42 @@ dependencies:
45
36
  requirements:
46
37
  - - ~>
47
38
  - !ruby/object:Gem::Version
48
- segments:
49
- - 1
50
- - 15
51
39
  version: "1.15"
52
40
  type: :runtime
53
41
  version_requirements: *id002
54
42
  - !ruby/object:Gem::Dependency
55
- name: json
43
+ name: multi_json
56
44
  prerelease: false
57
45
  requirement: &id003 !ruby/object:Gem::Requirement
58
46
  none: false
59
47
  requirements:
60
48
  - - ~>
61
49
  - !ruby/object:Gem::Version
62
- segments:
63
- - 1
64
- - 5
65
- - 1
66
- version: 1.5.1
50
+ version: 1.0.0
67
51
  type: :runtime
68
52
  version_requirements: *id003
69
53
  - !ruby/object:Gem::Dependency
70
- name: rspec
54
+ name: json
71
55
  prerelease: false
72
56
  requirement: &id004 !ruby/object:Gem::Requirement
73
57
  none: false
74
58
  requirements:
75
59
  - - ~>
76
60
  - !ruby/object:Gem::Version
77
- segments:
78
- - 1
79
- - 3
80
- - 0
81
- version: 1.3.0
61
+ version: 1.5.1
82
62
  type: :development
83
63
  version_requirements: *id004
64
+ - !ruby/object:Gem::Dependency
65
+ name: rspec
66
+ prerelease: false
67
+ requirement: &id005 !ruby/object:Gem::Requirement
68
+ none: false
69
+ requirements:
70
+ - - ~>
71
+ - !ruby/object:Gem::Version
72
+ version: 2.6.0
73
+ type: :development
74
+ version_requirements: *id005
84
75
  description: CouchRest provides a simple interface on top of CouchDB's RESTful HTTP API, as well as including some utility scripts for managing views and attachments.
85
76
  email: jchris@apache.org
86
77
  executables: []
@@ -123,10 +114,10 @@ files:
123
114
  - lib/couchrest/helper/upgrade.rb
124
115
  - lib/couchrest/middlewares/logger.rb
125
116
  - lib/couchrest/monkeypatches.rb
126
- - lib/couchrest/response.rb
127
117
  - lib/couchrest/rest_api.rb
128
118
  - lib/couchrest/server.rb
129
119
  - lib/couchrest/support/inheritable_attributes.rb
120
+ - lib/couchrest/version.rb
130
121
  - spec/.gitignore
131
122
  - spec/couchrest/couchrest_spec.rb
132
123
  - spec/couchrest/database_spec.rb
@@ -161,23 +152,17 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
152
  requirements:
162
153
  - - ">="
163
154
  - !ruby/object:Gem::Version
164
- segments:
165
- - 0
166
155
  version: "0"
167
156
  required_rubygems_version: !ruby/object:Gem::Requirement
168
157
  none: false
169
158
  requirements:
170
159
  - - ">"
171
160
  - !ruby/object:Gem::Version
172
- segments:
173
- - 1
174
- - 3
175
- - 1
176
161
  version: 1.3.1
177
162
  requirements: []
178
163
 
179
164
  rubyforge_project:
180
- rubygems_version: 1.3.7
165
+ rubygems_version: 1.3.9.1
181
166
  signing_key:
182
167
  specification_version: 3
183
168
  summary: Lean and RESTful interface to CouchDB.
@@ -1,16 +0,0 @@
1
- module CouchRest
2
- class Response < Hash
3
- def initialize(pkeys = {})
4
- pkeys ||= {}
5
- pkeys.each do |k,v|
6
- self[k.to_s] = v
7
- end
8
- end
9
- def []=(key, value)
10
- super(key.to_s, value)
11
- end
12
- def [](key)
13
- super(key.to_s)
14
- end
15
- end
16
- end