namelessjon-couchrest 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. data/LICENSE +176 -0
  2. data/README.md +46 -0
  3. data/Rakefile +69 -0
  4. data/THANKS.md +21 -0
  5. data/couchrest.gemspec +111 -0
  6. data/examples/word_count/markov +38 -0
  7. data/examples/word_count/views/books/chunked-map.js +3 -0
  8. data/examples/word_count/views/books/united-map.js +1 -0
  9. data/examples/word_count/views/markov/chain-map.js +6 -0
  10. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  11. data/examples/word_count/views/word_count/count-map.js +6 -0
  12. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  13. data/examples/word_count/word_count.rb +46 -0
  14. data/examples/word_count/word_count_query.rb +40 -0
  15. data/examples/word_count/word_count_views.rb +26 -0
  16. data/history.txt +145 -0
  17. data/lib/couchrest/commands/generate.rb +71 -0
  18. data/lib/couchrest/commands/push.rb +103 -0
  19. data/lib/couchrest/database.rb +373 -0
  20. data/lib/couchrest/design.rb +80 -0
  21. data/lib/couchrest/document.rb +89 -0
  22. data/lib/couchrest/helper/attachments.rb +29 -0
  23. data/lib/couchrest/helper/pager.rb +103 -0
  24. data/lib/couchrest/helper/streamer.rb +51 -0
  25. data/lib/couchrest/helper/upgrade.rb +52 -0
  26. data/lib/couchrest/json_response.rb +14 -0
  27. data/lib/couchrest/middlewares/logger.rb +263 -0
  28. data/lib/couchrest/monkeypatches.rb +42 -0
  29. data/lib/couchrest/response.rb +35 -0
  30. data/lib/couchrest/rest_api.rb +62 -0
  31. data/lib/couchrest/server.rb +90 -0
  32. data/lib/couchrest/support/inheritable_attributes.rb +107 -0
  33. data/lib/couchrest.rb +127 -0
  34. data/spec/couchrest/couchrest_spec.rb +202 -0
  35. data/spec/couchrest/database_spec.rb +870 -0
  36. data/spec/couchrest/design_spec.rb +158 -0
  37. data/spec/couchrest/document_spec.rb +279 -0
  38. data/spec/couchrest/helpers/pager_spec.rb +123 -0
  39. data/spec/couchrest/helpers/streamer_spec.rb +52 -0
  40. data/spec/couchrest/server_spec.rb +35 -0
  41. data/spec/fixtures/attachments/README +3 -0
  42. data/spec/fixtures/attachments/couchdb.png +0 -0
  43. data/spec/fixtures/attachments/test.html +11 -0
  44. data/spec/fixtures/views/lib.js +3 -0
  45. data/spec/fixtures/views/test_view/lib.js +3 -0
  46. data/spec/fixtures/views/test_view/only-map.js +4 -0
  47. data/spec/fixtures/views/test_view/test-map.js +3 -0
  48. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  49. data/spec/spec.opts +5 -0
  50. data/spec/spec_helper.rb +44 -0
  51. data/utils/remap.rb +27 -0
  52. data/utils/subset.rb +30 -0
  53. metadata +179 -0
@@ -0,0 +1,42 @@
1
+ require 'timeout'
2
+
3
+ # This file must be loaded after the JSON gem and any other library that beats up the Time class.
4
+ class Time
5
+ # This date format sorts lexicographically
6
+ # and is compatible with Javascript's <tt>new Date(time_string)</tt> constructor.
7
+ # Note this this format stores all dates in UTC so that collation
8
+ # order is preserved. (There's no longer a need to set <tt>ENV['TZ'] = 'UTC'</tt>
9
+ # in your application.)
10
+
11
+ def to_json(options = nil)
12
+ u = self.getutc
13
+ %("#{u.strftime("%Y/%m/%d %H:%M:%S +0000")}")
14
+ end
15
+
16
+ end
17
+
18
+ # Monkey patch for faster net/http io
19
+ if RUBY_VERSION.to_f < 1.9
20
+ class Net::BufferedIO #:nodoc:
21
+ alias :old_rbuf_fill :rbuf_fill
22
+ def rbuf_fill
23
+ if @io.respond_to?(:read_nonblock)
24
+ begin
25
+ @rbuf << @io.read_nonblock(65536)
26
+ rescue Errno::EWOULDBLOCK
27
+ if IO.select([@io], nil, nil, @read_timeout)
28
+ retry
29
+ else
30
+ raise Timeout::Error, "IO timeout"
31
+ end
32
+ end
33
+ else
34
+ timeout(@read_timeout) do
35
+ @rbuf << @io.sysread(65536)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
42
+
@@ -0,0 +1,35 @@
1
+ module CouchRest
2
+ class Response < Hash
3
+ attr_reader :headers, :raw
4
+ def initialize(pkeys = {})
5
+ pkeys ||= {}
6
+ pkeys.each do |k,v|
7
+ self[k.to_s] = v
8
+ end
9
+ @headers = pkeys.respond_to?(:headers) ? pkeys.headers : {}
10
+ @raw = pkeys.respond_to?(:raw) ? pkeys.raw : nil
11
+ @original = {}
12
+ end
13
+
14
+ def []=(key, value)
15
+ k = key.to_s
16
+ @original[k] ||= self[k] if defined?(@original)
17
+ super(k, value)
18
+ end
19
+
20
+ def original
21
+ self.merge(@original)
22
+ end
23
+
24
+ def delete(key)
25
+ k = key.to_s
26
+ r = self.delete(k)
27
+ @original[k] ||= r
28
+ r
29
+ end
30
+
31
+ def [](key)
32
+ super(key.to_s)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,62 @@
1
+ require 'couchrest/json_response'
2
+ module CouchRest
3
+ module RestAPI
4
+
5
+ def default_headers
6
+ {
7
+ :content_type => :json,
8
+ :accept => :json
9
+ }
10
+ end
11
+
12
+ def put(uri, doc = nil)
13
+ payload = doc.to_json if doc
14
+ begin
15
+ JsonResponse.create(RestClient.put(uri, payload, default_headers))
16
+ rescue Exception => e
17
+ if $DEBUG
18
+ raise "Error while sending a PUT request #{uri}\npayload: #{payload.inspect}\n#{e}"
19
+ else
20
+ raise e
21
+ end
22
+ end
23
+ end
24
+
25
+ def get(uri)
26
+ begin
27
+ JsonResponse.create(RestClient.get(uri, default_headers))
28
+ rescue => e
29
+ if $DEBUG
30
+ raise "Error while sending a GET request #{uri}\n: #{e}"
31
+ else
32
+ raise e
33
+ end
34
+ end
35
+ end
36
+
37
+ def post(uri, doc = nil)
38
+ payload = doc.to_json if doc
39
+ begin
40
+ JsonResponse.create(RestClient.post(uri, payload, default_headers))
41
+ rescue Exception => e
42
+ if $DEBUG
43
+ raise "Error while sending a POST request #{uri}\npayload: #{payload.inspect}\n#{e}"
44
+ else
45
+ raise e
46
+ end
47
+ end
48
+ end
49
+
50
+ def delete(uri)
51
+ JsonResponse.create(RestClient.delete(uri, default_headers))
52
+ end
53
+
54
+ def copy(uri, destination)
55
+ JsonResponse.create(RestClient::Request.execute( :method => :copy,
56
+ :url => uri,
57
+ :headers => default_headers.merge('Destination' => destination)
58
+ ))
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,90 @@
1
+ module CouchRest
2
+ class Server
3
+ attr_accessor :uri, :uuid_batch_count, :available_databases
4
+ def initialize(server = 'http://127.0.0.1:5984', uuid_batch_count = 1000)
5
+ @uri = server
6
+ @uuid_batch_count = uuid_batch_count
7
+ end
8
+
9
+ # Lists all "available" databases.
10
+ # An available database, is a database that was specified
11
+ # as avaiable by your code.
12
+ # It allows to define common databases to use and reuse in your code
13
+ def available_databases
14
+ @available_databases ||= {}
15
+ end
16
+
17
+ # Adds a new available database and create it unless it already exists
18
+ #
19
+ # Example:
20
+ #
21
+ # @couch = CouchRest::Server.new
22
+ # @couch.define_available_database(:default, "tech-blog")
23
+ #
24
+ def define_available_database(reference, db_name, create_unless_exists = true)
25
+ available_databases[reference.to_sym] = create_unless_exists ? database!(db_name) : database(db_name)
26
+ end
27
+
28
+ # Checks that a database is set as available
29
+ #
30
+ # Example:
31
+ #
32
+ # @couch.available_database?(:default)
33
+ #
34
+ def available_database?(ref_or_name)
35
+ ref_or_name.is_a?(Symbol) ? available_databases.keys.include?(ref_or_name) : available_databases.values.map{|db| db.name}.include?(ref_or_name)
36
+ end
37
+
38
+ def default_database=(name, create_unless_exists = true)
39
+ define_available_database(:default, name, create_unless_exists = true)
40
+ end
41
+
42
+ def default_database
43
+ available_databases[:default]
44
+ end
45
+
46
+ # Lists all databases on the server
47
+ def databases
48
+ CouchRest.get "#{@uri}/_all_dbs"
49
+ end
50
+
51
+ # Returns a CouchRest::Database for the given name
52
+ def database(name)
53
+ CouchRest::Database.new(self, name)
54
+ end
55
+
56
+ # Creates the database if it doesn't exist
57
+ def database!(name)
58
+ create_db(name) rescue nil
59
+ database(name)
60
+ end
61
+
62
+ # GET the welcome message
63
+ def info
64
+ CouchRest.get "#{@uri}/"
65
+ end
66
+
67
+ # Create a database
68
+ def create_db(name)
69
+ CouchRest.put "#{@uri}/#{name}"
70
+ database(name)
71
+ end
72
+
73
+ # Restart the CouchDB instance
74
+ def restart!
75
+ CouchRest.post "#{@uri}/_restart"
76
+ rescue RestClient::ServerBrokeConnection
77
+ # Shouldn't really happen, but does in CouchDB 1.0.0
78
+ end
79
+
80
+ # Retrive an unused UUID from CouchDB. Server instances manage caching a list of unused UUIDs.
81
+ def next_uuid(count = @uuid_batch_count)
82
+ @uuids ||= []
83
+ if @uuids.empty?
84
+ @uuids = CouchRest.get("#{@uri}/_uuids?count=#{count}")["uuids"]
85
+ end
86
+ @uuids.pop
87
+ end
88
+
89
+ end
90
+ end
@@ -0,0 +1,107 @@
1
+ # Copyright (c) 2006-2009 David Heinemeier Hansson
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ #
22
+ # Extracted From
23
+ # http://github.com/rails/rails/commit/971e2438d98326c994ec6d3ef8e37b7e868ed6e2
24
+
25
+ module CouchRest
26
+ module InheritableAttributes
27
+
28
+ # Defines class-level inheritable attribute reader. Attributes are available to subclasses,
29
+ # each subclass has a copy of parent's attribute.
30
+ #
31
+ # @param *syms<Array[#to_s]> Array of attributes to define inheritable reader for.
32
+ # @return <Array[#to_s]> Array of attributes converted into inheritable_readers.
33
+ #
34
+ # @api public
35
+ #
36
+ # @todo Do we want to block instance_reader via :instance_reader => false
37
+ # @todo It would be preferable that we do something with a Hash passed in
38
+ # (error out or do the same as other methods above) instead of silently
39
+ # moving on). In particular, this makes the return value of this function
40
+ # less useful.
41
+ def couchrest_inheritable_reader(*ivars)
42
+ instance_reader = ivars.pop[:reader] if ivars.last.is_a?(Hash)
43
+
44
+ ivars.each do |ivar|
45
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
46
+ def self.#{ivar}
47
+ return @#{ivar} if self.object_id == #{self.object_id} || defined?(@#{ivar})
48
+ ivar = superclass.#{ivar}
49
+ return nil if ivar.nil? && !#{self}.instance_variable_defined?("@#{ivar}")
50
+ @#{ivar} = ivar && !ivar.is_a?(Module) && !ivar.is_a?(Numeric) && !ivar.is_a?(TrueClass) && !ivar.is_a?(FalseClass) ? ivar.dup : ivar
51
+ end
52
+ RUBY
53
+ unless instance_reader == false
54
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
55
+ def #{ivar}
56
+ self.class.#{ivar}
57
+ end
58
+ RUBY
59
+ end
60
+ end
61
+ end
62
+
63
+ # Defines class-level inheritable attribute writer. Attributes are available to subclasses,
64
+ # each subclass has a copy of parent's attribute.
65
+ #
66
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
67
+ # define inheritable writer for.
68
+ # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
69
+ # @return <Array[#to_s]> An Array of the attributes that were made into inheritable writers.
70
+ #
71
+ # @api public
72
+ #
73
+ # @todo We need a style for class_eval <<-HEREDOC. I'd like to make it
74
+ # class_eval(<<-RUBY, __FILE__, __LINE__), but we should codify it somewhere.
75
+ def couchrest_inheritable_writer(*ivars)
76
+ instance_writer = ivars.pop[:writer] if ivars.last.is_a?(Hash)
77
+ ivars.each do |ivar|
78
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
79
+ def self.#{ivar}=(obj)
80
+ @#{ivar} = obj
81
+ end
82
+ RUBY
83
+ unless instance_writer == false
84
+ self.class_eval <<-RUBY, __FILE__, __LINE__ + 1
85
+ def #{ivar}=(obj) self.class.#{ivar} = obj end
86
+ RUBY
87
+ end
88
+
89
+ self.send("#{ivar}=", yield) if block_given?
90
+ end
91
+ end
92
+
93
+ # Defines class-level inheritable attribute accessor. Attributes are available to subclasses,
94
+ # each subclass has a copy of parent's attribute.
95
+ #
96
+ # @param *syms<Array[*#to_s, Hash{:instance_writer => Boolean}]> Array of attributes to
97
+ # define inheritable accessor for.
98
+ # @option syms :instance_writer<Boolean> if true, instance-level inheritable attribute writer is defined.
99
+ # @return <Array[#to_s]> An Array of attributes turned into inheritable accessors.
100
+ #
101
+ # @api public
102
+ def couchrest_inheritable_accessor(*syms, &block)
103
+ couchrest_inheritable_reader(*syms)
104
+ couchrest_inheritable_writer(*syms, &block)
105
+ end
106
+ end
107
+ end
data/lib/couchrest.rb ADDED
@@ -0,0 +1,127 @@
1
+ # Copyright 2008 J. Chris Anderson
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
+
15
+ require 'yajl/json_gem'
16
+ require 'rest_client'
17
+
18
+ # Not sure why this is required, so removed until a reason is found!
19
+ $:.unshift File.dirname(__FILE__) unless
20
+ $:.include?(File.dirname(__FILE__)) ||
21
+ $:.include?(File.expand_path(File.dirname(__FILE__)))
22
+
23
+ require 'couchrest/monkeypatches'
24
+ require 'couchrest/rest_api'
25
+ require 'couchrest/support/inheritable_attributes'
26
+
27
+ # = CouchDB, close to the metal
28
+ module CouchRest
29
+ VERSION = '1.0.0'
30
+
31
+ # we always want these
32
+ require 'couchrest/server'
33
+ require 'couchrest/database'
34
+
35
+ # we extend CouchRest with the RestAPI module which gives us acess to
36
+ # the get, post, put, delete and copy
37
+ CouchRest.extend(RestAPI)
38
+
39
+ # The CouchRest module methods handle the basic JSON serialization
40
+ # and deserialization, as well as query parameters. The module also includes
41
+ # some helpers for tasks like instantiating a new Database or Server instance.
42
+ class << self
43
+
44
+ # todo, make this parse the url and instantiate a Server or Database instance
45
+ # depending on the specificity.
46
+ def new(*opts)
47
+ Server.new(*opts)
48
+ end
49
+
50
+ def parse url
51
+ case url
52
+ when /^(https?:\/\/)(.*)\/(.*)\/(.*)/
53
+ scheme = $1
54
+ host = $2
55
+ db = $3
56
+ docid = $4
57
+ when /^(https?:\/\/)(.*)\/(.*)/
58
+ scheme = $1
59
+ host = $2
60
+ db = $3
61
+ when /^(https?:\/\/)(.*)/
62
+ scheme = $1
63
+ host = $2
64
+ when /(.*)\/(.*)\/(.*)/
65
+ host = $1
66
+ db = $2
67
+ docid = $3
68
+ when /(.*)\/(.*)/
69
+ host = $1
70
+ db = $2
71
+ else
72
+ db = url
73
+ end
74
+
75
+ db = nil if db && db.empty?
76
+
77
+ {
78
+ :host => (scheme || "http://") + (host || "127.0.0.1:5984"),
79
+ :database => db,
80
+ :doc => docid
81
+ }
82
+ end
83
+
84
+ # set proxy to use
85
+ def proxy url
86
+ RestClient.proxy = url
87
+ end
88
+
89
+ # ensure that a database exists
90
+ # creates it if it isn't already there
91
+ # returns it after it's been created
92
+ def database! url
93
+ parsed = parse url
94
+ cr = CouchRest.new(parsed[:host])
95
+ cr.database!(parsed[:database])
96
+ end
97
+
98
+ def database url
99
+ parsed = parse url
100
+ cr = CouchRest.new(parsed[:host])
101
+ cr.database(parsed[:database])
102
+ end
103
+
104
+ def paramify_url url, params = {}
105
+ if params && !params.empty?
106
+ query = params.collect do |k,v|
107
+ v = v.to_json if %w{key startkey endkey}.include?(k.to_s)
108
+ "#{k}=#{CGI.escape(v.to_s)}"
109
+ end.join("&")
110
+ url = "#{url}?#{query}"
111
+ end
112
+ url
113
+ end
114
+ end # class << self
115
+ end
116
+ # For the sake of backwards compatability, generate a dummy ExtendedDocument class
117
+ # which should be replaced by real library: couchrest_extended_document.
118
+ #
119
+ # Added 2010-05-10 by Sam Lown. Please remove at some point in the future.
120
+ #
121
+ class CouchRest::ExtendedDocument < CouchRest::Document
122
+
123
+ def self.inherited(subclass)
124
+ raise "ExtendedDocument is no longer included in CouchRest base driver, see couchrest_extended_document gem"
125
+ end
126
+
127
+ end
@@ -0,0 +1,202 @@
1
+ require File.expand_path("../../spec_helper", __FILE__)
2
+
3
+ describe CouchRest do
4
+
5
+ before(:each) do
6
+ @cr = CouchRest.new(COUCHHOST)
7
+ begin
8
+ @db = @cr.database(TESTDB)
9
+ @db.delete! rescue nil
10
+ end
11
+ end
12
+
13
+ after(:each) do
14
+ begin
15
+ @db.delete! rescue nil
16
+ end
17
+ end
18
+
19
+ describe "getting info" do
20
+ it "should list databases" do
21
+ @cr.databases.should be_an_instance_of(Array)
22
+ end
23
+ it "should get info" do
24
+ @cr.info["couchdb"].should == "Welcome"
25
+ @cr.info.class.should == Hash
26
+ end
27
+ end
28
+
29
+ it "should restart" do
30
+ @cr.restart!
31
+ begin
32
+ @cr.info
33
+ rescue
34
+ # Give the couchdb time to restart
35
+ sleep 0.2
36
+ retry
37
+ end
38
+ end
39
+
40
+ it "should provide one-time access to uuids" do
41
+ @cr.next_uuid.should_not be_nil
42
+ end
43
+
44
+ describe "initializing a database" do
45
+ it "should return a db" do
46
+ db = @cr.database(TESTDB)
47
+ db.should be_an_instance_of(CouchRest::Database)
48
+ db.host.should == @cr.uri
49
+ end
50
+ end
51
+
52
+ describe "parsing urls" do
53
+ it "should parse just a dbname" do
54
+ db = CouchRest.parse "my-db"
55
+ db[:database].should == "my-db"
56
+ db[:host].should == "http://127.0.0.1:5984"
57
+ end
58
+ it "should parse a host and db" do
59
+ db = CouchRest.parse "127.0.0.1/my-db"
60
+ db[:database].should == "my-db"
61
+ db[:host].should == "http://127.0.0.1"
62
+ end
63
+ it "should parse a host and db with http" do
64
+ db = CouchRest.parse "http://127.0.0.1/my-db"
65
+ db[:database].should == "my-db"
66
+ db[:host].should == "http://127.0.0.1"
67
+ end
68
+ it "should parse a host and db with https" do
69
+ db = CouchRest.parse "https://127.0.0.1/my-db"
70
+ db[:database].should == "my-db"
71
+ db[:host].should == "https://127.0.0.1"
72
+ end
73
+ it "should parse a host with a port and db" do
74
+ db = CouchRest.parse "127.0.0.1:5555/my-db"
75
+ db[:database].should == "my-db"
76
+ db[:host].should == "http://127.0.0.1:5555"
77
+ end
78
+ it "should parse a host with a port and db with http" do
79
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db"
80
+ db[:database].should == "my-db"
81
+ db[:host].should == "http://127.0.0.1:5555"
82
+ end
83
+ it "should parse a host with a port and db with https" do
84
+ db = CouchRest.parse "https://127.0.0.1:5555/my-db"
85
+ db[:database].should == "my-db"
86
+ db[:host].should == "https://127.0.0.1:5555"
87
+ end
88
+ it "should parse just a host" do
89
+ db = CouchRest.parse "http://127.0.0.1:5555/"
90
+ db[:database].should be_nil
91
+ db[:host].should == "http://127.0.0.1:5555"
92
+ end
93
+ it "should parse just a host with https" do
94
+ db = CouchRest.parse "https://127.0.0.1:5555/"
95
+ db[:database].should be_nil
96
+ db[:host].should == "https://127.0.0.1:5555"
97
+ end
98
+ it "should parse just a host no slash" do
99
+ db = CouchRest.parse "http://127.0.0.1:5555"
100
+ db[:host].should == "http://127.0.0.1:5555"
101
+ db[:database].should be_nil
102
+ end
103
+ it "should parse just a host no slash and https" do
104
+ db = CouchRest.parse "https://127.0.0.1:5555"
105
+ db[:host].should == "https://127.0.0.1:5555"
106
+ db[:database].should be_nil
107
+ end
108
+ it "should get docid" do
109
+ db = CouchRest.parse "127.0.0.1:5555/my-db/my-doc"
110
+ db[:database].should == "my-db"
111
+ db[:host].should == "http://127.0.0.1:5555"
112
+ db[:doc].should == "my-doc"
113
+ end
114
+ it "should get docid with http" do
115
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db/my-doc"
116
+ db[:database].should == "my-db"
117
+ db[:host].should == "http://127.0.0.1:5555"
118
+ db[:doc].should == "my-doc"
119
+ end
120
+ it "should get docid with https" do
121
+ db = CouchRest.parse "https://127.0.0.1:5555/my-db/my-doc"
122
+ db[:database].should == "my-db"
123
+ db[:host].should == "https://127.0.0.1:5555"
124
+ db[:doc].should == "my-doc"
125
+ end
126
+ end
127
+
128
+ describe "easy initializing a database adapter" do
129
+ it "should be possible without an explicit CouchRest instantiation" do
130
+ db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
131
+ db.should be_an_instance_of(CouchRest::Database)
132
+ db.host.should == "http://127.0.0.1:5984"
133
+ end
134
+ # TODO add https support (need test environment...)
135
+ # it "should work with https" # do
136
+ # db = CouchRest.database "https://127.0.0.1:5984/couchrest-test"
137
+ # db.host.should == "https://127.0.0.1:5984"
138
+ # end
139
+ it "should not create the database automatically" do
140
+ db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
141
+ lambda{db.info}.should raise_error(RestClient::ResourceNotFound)
142
+ end
143
+ end
144
+
145
+ describe "ensuring the db exists" do
146
+ it "should be super easy" do
147
+ db = CouchRest.database! "#{COUCHHOST}/couchrest-test-2"
148
+ db.name.should == 'couchrest-test-2'
149
+ db.info["db_name"].should == 'couchrest-test-2'
150
+ end
151
+ end
152
+
153
+ describe "successfully creating a database" do
154
+ it "should start without a database" do
155
+ @cr.databases.should_not include(TESTDB)
156
+ end
157
+ it "should return the created database" do
158
+ db = @cr.create_db(TESTDB)
159
+ db.should be_an_instance_of(CouchRest::Database)
160
+ end
161
+ it "should create the database" do
162
+ db = @cr.create_db(TESTDB)
163
+ @cr.databases.should include(TESTDB)
164
+ end
165
+ end
166
+
167
+ describe "failing to create a database because the name is taken" do
168
+ before(:each) do
169
+ db = @cr.create_db(TESTDB)
170
+ end
171
+ it "should start with the test database" do
172
+ @cr.databases.should include(TESTDB)
173
+ end
174
+ it "should PUT the database and raise an error" do
175
+ lambda{
176
+ @cr.create_db(TESTDB)
177
+ }.should raise_error(RestClient::Request::RequestFailed)
178
+ end
179
+ end
180
+
181
+ describe "using a proxy for RestClient connections" do
182
+ it "should set proxy url for RestClient" do
183
+ CouchRest.proxy 'http://localhost:8888/'
184
+ proxy_uri = URI.parse(RestClient.proxy)
185
+ proxy_uri.host.should eql( 'localhost' )
186
+ proxy_uri.port.should eql( 8888 )
187
+ CouchRest.proxy nil
188
+ end
189
+ end
190
+
191
+ describe "Including old ExtendedDocument library" do
192
+
193
+ it "should raise an exception" do
194
+ lambda do
195
+ class TestDoc < CouchRest::ExtendedDocument
196
+ attr_reader :fail
197
+ end
198
+ end.should raise_error(RuntimeError)
199
+ end
200
+
201
+ end
202
+ end