dpla-couchrest 1.2.1.pre.dpla

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 (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