dpla-couchrest 1.2.1.pre.dpla

Sign up to get free protection for your applications and to get access to all the features.
Files changed (60) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +7 -0
  3. data/.travis.yml +8 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +176 -0
  6. data/README.md +66 -0
  7. data/Rakefile +23 -0
  8. data/THANKS.md +21 -0
  9. data/VERSION +1 -0
  10. data/couchrest.gemspec +36 -0
  11. data/examples/word_count/markov +38 -0
  12. data/examples/word_count/views/books/chunked-map.js +3 -0
  13. data/examples/word_count/views/books/united-map.js +1 -0
  14. data/examples/word_count/views/markov/chain-map.js +6 -0
  15. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  16. data/examples/word_count/views/word_count/count-map.js +6 -0
  17. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  18. data/examples/word_count/word_count.rb +46 -0
  19. data/examples/word_count/word_count_query.rb +40 -0
  20. data/examples/word_count/word_count_views.rb +26 -0
  21. data/history.txt +214 -0
  22. data/init.rb +1 -0
  23. data/lib/couchrest.rb +146 -0
  24. data/lib/couchrest/attributes.rb +89 -0
  25. data/lib/couchrest/commands/generate.rb +71 -0
  26. data/lib/couchrest/commands/push.rb +103 -0
  27. data/lib/couchrest/database.rb +402 -0
  28. data/lib/couchrest/design.rb +91 -0
  29. data/lib/couchrest/document.rb +105 -0
  30. data/lib/couchrest/helper/attachments.rb +29 -0
  31. data/lib/couchrest/helper/pager.rb +103 -0
  32. data/lib/couchrest/helper/streamer.rb +60 -0
  33. data/lib/couchrest/helper/upgrade.rb +51 -0
  34. data/lib/couchrest/middlewares/logger.rb +263 -0
  35. data/lib/couchrest/monkeypatches.rb +25 -0
  36. data/lib/couchrest/rest_api.rb +166 -0
  37. data/lib/couchrest/server.rb +92 -0
  38. data/lib/couchrest/support/inheritable_attributes.rb +107 -0
  39. data/spec/.gitignore +1 -0
  40. data/spec/couchrest/couchrest_spec.rb +197 -0
  41. data/spec/couchrest/database_spec.rb +914 -0
  42. data/spec/couchrest/design_spec.rb +206 -0
  43. data/spec/couchrest/document_spec.rb +400 -0
  44. data/spec/couchrest/helpers/pager_spec.rb +115 -0
  45. data/spec/couchrest/helpers/streamer_spec.rb +134 -0
  46. data/spec/couchrest/rest_api_spec.rb +241 -0
  47. data/spec/couchrest/server_spec.rb +35 -0
  48. data/spec/fixtures/attachments/README +3 -0
  49. data/spec/fixtures/attachments/couchdb.png +0 -0
  50. data/spec/fixtures/attachments/test.html +11 -0
  51. data/spec/fixtures/views/lib.js +3 -0
  52. data/spec/fixtures/views/test_view/lib.js +3 -0
  53. data/spec/fixtures/views/test_view/only-map.js +4 -0
  54. data/spec/fixtures/views/test_view/test-map.js +3 -0
  55. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  56. data/spec/spec.opts +5 -0
  57. data/spec/spec_helper.rb +46 -0
  58. data/utils/remap.rb +27 -0
  59. data/utils/subset.rb +30 -0
  60. metadata +212 -0
@@ -0,0 +1,25 @@
1
+ # Monkey patch for faster net/http io
2
+ if RUBY_VERSION.to_f < 1.9
3
+ require 'timeout'
4
+
5
+ class Net::BufferedIO #:nodoc:
6
+ alias :old_rbuf_fill :rbuf_fill
7
+ def rbuf_fill
8
+ if @io.respond_to?(:read_nonblock)
9
+ begin
10
+ @rbuf << @io.read_nonblock(65536)
11
+ rescue Errno::EWOULDBLOCK
12
+ if IO.select([@io], nil, nil, @read_timeout)
13
+ retry
14
+ else
15
+ raise Timeout::Error, "IO timeout"
16
+ end
17
+ end
18
+ else
19
+ timeout(@read_timeout) do
20
+ @rbuf << @io.sysread(65536)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,166 @@
1
+ module CouchRest
2
+
3
+ # CouchRest RestAPI
4
+ #
5
+ # The basic low-level interface for all REST requests to the database. Everything must pass
6
+ # through here before it is sent to the server.
7
+ #
8
+ # Six types of REST requests are supported: get, put, post, delete, copy and head.
9
+ #
10
+ # Requests that do not have a payload, get, delete and copy, accept the URI and options parameters,
11
+ # where as put and post both expect a document as the second parameter.
12
+ #
13
+ # The API will try to intelegently split the options between the JSON parser and RestClient API.
14
+ #
15
+ # The following options will be recognised as header options and automatically added
16
+ # to the header hash:
17
+ #
18
+ # * :content_type, type of content to be sent, especially useful when sending files as this will set the file type. The default is :json.
19
+ # * :accept, the content type to accept in the response. This should pretty much always be :json.
20
+ #
21
+ # The following request options are supported:
22
+ #
23
+ # * :method override the requested method (should not be used!).
24
+ # * :url override the URL used in the request.
25
+ # * :payload override the document or data sent in the message body (only PUT or POST).
26
+ # * :headers any additional headers (overrides :content_type and :accept)
27
+ # * :timeout and :open_timeout the time in miliseconds to wait for the request, see RestClient API for more details.
28
+ # * :verify_ssl, :ssl_client_cert, :ssl_client_key, and :ssl_ca_file, SSL handling methods.
29
+ #
30
+ #
31
+ # Any other remaining options will be sent to the MultiJSON backend except for the :raw option.
32
+ #
33
+ # When :raw is true in PUT and POST requests, no attempt will be made to convert the document payload to JSON. This is
34
+ # not normally necessary as IO and Tempfile objects will not be parsed anyway. The result of the request will
35
+ # *always* be parsed.
36
+ #
37
+ # For all other requests, mainly GET, the :raw option will make no attempt to parse the result. This
38
+ # is useful for receiving files from the database.
39
+ #
40
+
41
+ module RestAPI
42
+
43
+ # Send a GET request.
44
+ def get(uri, options = {})
45
+ execute(uri, :get, options)
46
+ end
47
+
48
+ # Send a PUT request.
49
+ def put(uri, doc = nil, options = {})
50
+ execute(uri, :put, options, doc)
51
+ end
52
+
53
+ # Send a POST request.
54
+ def post(uri, doc = nil, options = {})
55
+ execute(uri, :post, options, doc)
56
+ end
57
+
58
+ # Send a DELETE request.
59
+ def delete(uri, options = {})
60
+ execute(uri, :delete, options)
61
+ end
62
+
63
+ # Send a COPY request to the URI provided.
64
+ def copy(uri, destination, options = {})
65
+ opts = options.nil? ? {} : options.dup
66
+ # also copy headers!
67
+ opts[:headers] = options[:headers].nil? ? {} : options[:headers].dup
68
+ opts[:headers]['Destination'] = destination
69
+ execute(uri, :copy, opts)
70
+ end
71
+
72
+ # Send a HEAD request.
73
+ def head(uri, options = {})
74
+ execute(uri, :head, options)
75
+ end
76
+
77
+ # The default RestClient headers used in each request.
78
+ def default_headers
79
+ {
80
+ :content_type => :json,
81
+ :accept => :json
82
+ }
83
+ end
84
+
85
+ private
86
+
87
+ # Perform the RestClient request by removing the parse specific options, ensuring the
88
+ # payload is prepared, and sending the request ready to parse the response.
89
+ def execute(url, method, options = {}, payload = nil)
90
+ request, parser = prepare_and_split_options(url, method, options)
91
+ # Prepare the payload if it is provided
92
+ request[:payload] = payload_from_doc(payload, parser) if payload
93
+ begin
94
+ parse_response(RestClient::Request.execute(request), parser)
95
+ rescue Exception => e
96
+ if $DEBUG
97
+ raise "Error while sending a #{method.to_s.upcase} request #{uri}\noptions: #{opts.inspect}\n#{e}"
98
+ else
99
+ raise e
100
+ end
101
+ end
102
+ end
103
+
104
+ # Prepare two hashes, one for the request to the REST backend and a second
105
+ # for the JSON parser.
106
+ #
107
+ # Returns an array of request and parser options.
108
+ #
109
+ def prepare_and_split_options(url, method, options)
110
+ request = {
111
+ :url => url,
112
+ :method => method,
113
+ :headers => default_headers.merge(options[:headers] || {})
114
+ }
115
+ parser = {
116
+ :raw => false,
117
+ :head => (method == :head)
118
+ }
119
+ # Split the options
120
+ (options || {}).each do |k,v|
121
+ k = k.to_sym
122
+ next if k == :headers # already dealt with
123
+ if restclient_option_keys.include?(k)
124
+ request[k] = v
125
+ elsif header_option_keys.include?(k)
126
+ request[:headers][k] = v
127
+ else
128
+ parser[k] = v
129
+ end
130
+ end
131
+ [request, parser]
132
+ end
133
+
134
+ # Check if the provided doc is nil or special IO device or temp file. If not,
135
+ # encode it into a string.
136
+ #
137
+ # The options supported are:
138
+ # * :raw TrueClass, if true the payload will not be altered.
139
+ #
140
+ def payload_from_doc(doc, opts = {})
141
+ if (opts.delete(:raw) || doc.nil? || doc.is_a?(IO) || doc.is_a?(Tempfile))
142
+ doc
143
+ else
144
+ MultiJson.encode(doc.respond_to?(:as_couch_json) ? doc.as_couch_json : doc)
145
+ end
146
+ end
147
+
148
+ # Parse the response provided.
149
+ def parse_response(result, opts = {})
150
+ opts = opts.update(:create_additions => true) if decode_json_objects
151
+ (opts.delete(:raw) || opts.delete(:head)) ? result : MultiJson.decode(result, opts.update(:max_nesting => false))
152
+ end
153
+
154
+ # An array of all the options that should be passed through to restclient.
155
+ # Anything not in this list will be passed to the JSON parser.
156
+ def restclient_option_keys
157
+ [:method, :url, :payload, :headers, :timeout, :open_timeout,
158
+ :verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file]
159
+ end
160
+
161
+ def header_option_keys
162
+ [ :content_type, :accept ]
163
+ end
164
+
165
+ end
166
+ end
@@ -0,0 +1,92 @@
1
+ module CouchRest
2
+ class Server
3
+
4
+ attr_accessor :uri, :uuid_batch_count, :available_databases
5
+
6
+ def initialize(server = 'http://127.0.0.1:5984', uuid_batch_count = 1000)
7
+ @uri = server
8
+ @uuid_batch_count = uuid_batch_count
9
+ end
10
+
11
+ # Lists all "available" databases.
12
+ # An available database, is a database that was specified
13
+ # as avaiable by your code.
14
+ # It allows to define common databases to use and reuse in your code
15
+ def available_databases
16
+ @available_databases ||= {}
17
+ end
18
+
19
+ # Adds a new available database and create it unless it already exists
20
+ #
21
+ # Example:
22
+ #
23
+ # @couch = CouchRest::Server.new
24
+ # @couch.define_available_database(:default, "tech-blog")
25
+ #
26
+ def define_available_database(reference, db_name, create_unless_exists = true)
27
+ available_databases[reference.to_sym] = create_unless_exists ? database!(db_name) : database(db_name)
28
+ end
29
+
30
+ # Checks that a database is set as available
31
+ #
32
+ # Example:
33
+ #
34
+ # @couch.available_database?(:default)
35
+ #
36
+ def available_database?(ref_or_name)
37
+ ref_or_name.is_a?(Symbol) ? available_databases.keys.include?(ref_or_name) : available_databases.values.map{|db| db.name}.include?(ref_or_name)
38
+ end
39
+
40
+ def default_database=(name, create_unless_exists = true)
41
+ define_available_database(:default, name, create_unless_exists = true)
42
+ end
43
+
44
+ def default_database
45
+ available_databases[:default]
46
+ end
47
+
48
+ # Lists all databases on the server
49
+ def databases
50
+ CouchRest.get "#{@uri}/_all_dbs"
51
+ end
52
+
53
+ # Returns a CouchRest::Database for the given name
54
+ def database(name)
55
+ CouchRest::Database.new(self, name)
56
+ end
57
+
58
+ # Creates the database if it doesn't exist
59
+ def database!(name)
60
+ CouchRest.head "#{@uri}/#{name}" # Check if the URL is valid
61
+ database(name)
62
+ rescue RestClient::ResourceNotFound # Thrown if the HTTP HEAD fails
63
+ create_db(name)
64
+ end
65
+
66
+ # GET the welcome message
67
+ def info
68
+ CouchRest.get "#{@uri}/"
69
+ end
70
+
71
+ # Create a database
72
+ def create_db(name)
73
+ CouchRest.put "#{@uri}/#{name}"
74
+ database(name)
75
+ end
76
+
77
+ # Restart the CouchDB instance
78
+ def restart!
79
+ CouchRest.post "#{@uri}/_restart"
80
+ end
81
+
82
+ # Retrive an unused UUID from CouchDB. Server instances manage caching a list of unused UUIDs.
83
+ def next_uuid(count = @uuid_batch_count)
84
+ @uuids ||= []
85
+ if @uuids.empty?
86
+ @uuids = CouchRest.get("#{@uri}/_uuids?count=#{count}")["uuids"]
87
+ end
88
+ @uuids.pop
89
+ end
90
+
91
+ end
92
+ 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/spec/.gitignore ADDED
@@ -0,0 +1 @@
1
+ tmp
@@ -0,0 +1,197 @@
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
+ # we really do not need to perform a proper restart!
31
+ CouchRest.should_receive(:post).with("#{@cr.uri}/_restart")
32
+ @cr.restart!
33
+ end
34
+
35
+ it "should provide one-time access to uuids" do
36
+ @cr.next_uuid.should_not be_nil
37
+ end
38
+
39
+ describe "initializing a database" do
40
+ it "should return a db" do
41
+ db = @cr.database(TESTDB)
42
+ db.should be_an_instance_of(CouchRest::Database)
43
+ db.host.should == @cr.uri
44
+ end
45
+ end
46
+
47
+ describe "parsing urls" do
48
+ it "should parse just a dbname" do
49
+ db = CouchRest.parse "my-db"
50
+ db[:database].should == "my-db"
51
+ db[:host].should == "http://127.0.0.1:5984"
52
+ end
53
+ it "should parse a host and db" do
54
+ db = CouchRest.parse "127.0.0.1/my-db"
55
+ db[:database].should == "my-db"
56
+ db[:host].should == "http://127.0.0.1"
57
+ end
58
+ it "should parse a host and db with http" do
59
+ db = CouchRest.parse "http://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 https" do
64
+ db = CouchRest.parse "https://127.0.0.1/my-db"
65
+ db[:database].should == "my-db"
66
+ db[:host].should == "https://127.0.0.1"
67
+ end
68
+ it "should parse a host with a port and db" do
69
+ db = CouchRest.parse "127.0.0.1:5555/my-db"
70
+ db[:database].should == "my-db"
71
+ db[:host].should == "http://127.0.0.1:5555"
72
+ end
73
+ it "should parse a host with a port and db with http" do
74
+ db = CouchRest.parse "http://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 https" do
79
+ db = CouchRest.parse "https://127.0.0.1:5555/my-db"
80
+ db[:database].should == "my-db"
81
+ db[:host].should == "https://127.0.0.1:5555"
82
+ end
83
+ it "should parse just a host" do
84
+ db = CouchRest.parse "http://127.0.0.1:5555/"
85
+ db[:database].should be_nil
86
+ db[:host].should == "http://127.0.0.1:5555"
87
+ end
88
+ it "should parse just a host with https" do
89
+ db = CouchRest.parse "https://127.0.0.1:5555/"
90
+ db[:database].should be_nil
91
+ db[:host].should == "https://127.0.0.1:5555"
92
+ end
93
+ it "should parse just a host no slash" do
94
+ db = CouchRest.parse "http://127.0.0.1:5555"
95
+ db[:host].should == "http://127.0.0.1:5555"
96
+ db[:database].should be_nil
97
+ end
98
+ it "should parse just a host no slash and https" do
99
+ db = CouchRest.parse "https://127.0.0.1:5555"
100
+ db[:host].should == "https://127.0.0.1:5555"
101
+ db[:database].should be_nil
102
+ end
103
+ it "should get docid" do
104
+ db = CouchRest.parse "127.0.0.1:5555/my-db/my-doc"
105
+ db[:database].should == "my-db"
106
+ db[:host].should == "http://127.0.0.1:5555"
107
+ db[:doc].should == "my-doc"
108
+ end
109
+ it "should get docid with http" do
110
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db/my-doc"
111
+ db[:database].should == "my-db"
112
+ db[:host].should == "http://127.0.0.1:5555"
113
+ db[:doc].should == "my-doc"
114
+ end
115
+ it "should get docid with https" do
116
+ db = CouchRest.parse "https://127.0.0.1:5555/my-db/my-doc"
117
+ db[:database].should == "my-db"
118
+ db[:host].should == "https://127.0.0.1:5555"
119
+ db[:doc].should == "my-doc"
120
+ end
121
+ end
122
+
123
+ describe "easy initializing a database adapter" do
124
+ it "should be possible without an explicit CouchRest instantiation" do
125
+ db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
126
+ db.should be_an_instance_of(CouchRest::Database)
127
+ db.host.should == "http://127.0.0.1:5984"
128
+ end
129
+ # TODO add https support (need test environment...)
130
+ # it "should work with https" # do
131
+ # db = CouchRest.database "https://127.0.0.1:5984/couchrest-test"
132
+ # db.host.should == "https://127.0.0.1:5984"
133
+ # end
134
+ it "should not create the database automatically" do
135
+ db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
136
+ lambda{db.info}.should raise_error(RestClient::ResourceNotFound)
137
+ end
138
+ end
139
+
140
+ describe "ensuring the db exists" do
141
+ it "should be super easy" do
142
+ db = CouchRest.database! "#{COUCHHOST}/couchrest-test-2"
143
+ db.name.should == 'couchrest-test-2'
144
+ db.info["db_name"].should == 'couchrest-test-2'
145
+ end
146
+ end
147
+
148
+ describe "successfully creating a database" do
149
+ it "should start without a database" do
150
+ @cr.databases.should_not include(TESTDB)
151
+ end
152
+ it "should return the created database" do
153
+ db = @cr.create_db(TESTDB)
154
+ db.should be_an_instance_of(CouchRest::Database)
155
+ end
156
+ it "should create the database" do
157
+ db = @cr.create_db(TESTDB)
158
+ @cr.databases.should include(TESTDB)
159
+ end
160
+ end
161
+
162
+ describe "failing to create a database because the name is taken" do
163
+ before(:each) do
164
+ db = @cr.create_db(TESTDB)
165
+ end
166
+ it "should start with the test database" do
167
+ @cr.databases.should include(TESTDB)
168
+ end
169
+ it "should PUT the database and raise an error" do
170
+ lambda{
171
+ @cr.create_db(TESTDB)
172
+ }.should raise_error(RestClient::Request::RequestFailed)
173
+ end
174
+ end
175
+
176
+ describe "using a proxy for RestClient connections" do
177
+ it "should set proxy url for RestClient" do
178
+ CouchRest.proxy 'http://localhost:8888/'
179
+ proxy_uri = URI.parse(RestClient.proxy)
180
+ proxy_uri.host.should eql( 'localhost' )
181
+ proxy_uri.port.should eql( 8888 )
182
+ CouchRest.proxy nil
183
+ end
184
+ end
185
+
186
+ describe "Including old ExtendedDocument library" do
187
+
188
+ it "should raise an exception" do
189
+ lambda do
190
+ class TestDoc < CouchRest::ExtendedDocument
191
+ attr_reader :fail
192
+ end
193
+ end.should raise_error(RuntimeError)
194
+ end
195
+
196
+ end
197
+ end