will-couchrest 0.32.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (98) hide show
  1. data/LICENSE +176 -0
  2. data/README.md +165 -0
  3. data/Rakefile +74 -0
  4. data/THANKS.md +18 -0
  5. data/examples/model/example.rb +144 -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 +65 -0
  17. data/lib/couchrest.rb +199 -0
  18. data/lib/couchrest/commands/generate.rb +71 -0
  19. data/lib/couchrest/commands/push.rb +103 -0
  20. data/lib/couchrest/core/adapters/restclient.rb +35 -0
  21. data/lib/couchrest/core/database.rb +317 -0
  22. data/lib/couchrest/core/design.rb +79 -0
  23. data/lib/couchrest/core/document.rb +83 -0
  24. data/lib/couchrest/core/http_abstraction.rb +48 -0
  25. data/lib/couchrest/core/response.rb +16 -0
  26. data/lib/couchrest/core/server.rb +88 -0
  27. data/lib/couchrest/core/view.rb +4 -0
  28. data/lib/couchrest/helper/pager.rb +103 -0
  29. data/lib/couchrest/helper/streamer.rb +44 -0
  30. data/lib/couchrest/helper/upgrade.rb +51 -0
  31. data/lib/couchrest/mixins.rb +4 -0
  32. data/lib/couchrest/mixins/attachments.rb +31 -0
  33. data/lib/couchrest/mixins/callbacks.rb +483 -0
  34. data/lib/couchrest/mixins/class_proxy.rb +116 -0
  35. data/lib/couchrest/mixins/collection.rb +225 -0
  36. data/lib/couchrest/mixins/design_doc.rb +103 -0
  37. data/lib/couchrest/mixins/document_queries.rb +82 -0
  38. data/lib/couchrest/mixins/extended_attachments.rb +74 -0
  39. data/lib/couchrest/mixins/extended_document_mixins.rb +8 -0
  40. data/lib/couchrest/mixins/properties.rb +158 -0
  41. data/lib/couchrest/mixins/validation.rb +257 -0
  42. data/lib/couchrest/mixins/views.rb +173 -0
  43. data/lib/couchrest/monkeypatches.rb +113 -0
  44. data/lib/couchrest/more/casted_model.rb +29 -0
  45. data/lib/couchrest/more/extended_document.rb +246 -0
  46. data/lib/couchrest/more/property.rb +40 -0
  47. data/lib/couchrest/support/blank.rb +42 -0
  48. data/lib/couchrest/support/class.rb +176 -0
  49. data/lib/couchrest/support/rails.rb +35 -0
  50. data/lib/couchrest/validation/auto_validate.rb +161 -0
  51. data/lib/couchrest/validation/contextual_validators.rb +78 -0
  52. data/lib/couchrest/validation/validation_errors.rb +125 -0
  53. data/lib/couchrest/validation/validators/absent_field_validator.rb +74 -0
  54. data/lib/couchrest/validation/validators/confirmation_validator.rb +99 -0
  55. data/lib/couchrest/validation/validators/format_validator.rb +117 -0
  56. data/lib/couchrest/validation/validators/formats/email.rb +66 -0
  57. data/lib/couchrest/validation/validators/formats/url.rb +43 -0
  58. data/lib/couchrest/validation/validators/generic_validator.rb +120 -0
  59. data/lib/couchrest/validation/validators/length_validator.rb +134 -0
  60. data/lib/couchrest/validation/validators/method_validator.rb +89 -0
  61. data/lib/couchrest/validation/validators/numeric_validator.rb +104 -0
  62. data/lib/couchrest/validation/validators/required_field_validator.rb +109 -0
  63. data/spec/couchrest/core/couchrest_spec.rb +201 -0
  64. data/spec/couchrest/core/database_spec.rb +700 -0
  65. data/spec/couchrest/core/design_spec.rb +138 -0
  66. data/spec/couchrest/core/document_spec.rb +267 -0
  67. data/spec/couchrest/core/server_spec.rb +35 -0
  68. data/spec/couchrest/helpers/pager_spec.rb +122 -0
  69. data/spec/couchrest/helpers/streamer_spec.rb +23 -0
  70. data/spec/couchrest/more/casted_extended_doc_spec.rb +75 -0
  71. data/spec/couchrest/more/casted_model_spec.rb +177 -0
  72. data/spec/couchrest/more/extended_doc_attachment_spec.rb +135 -0
  73. data/spec/couchrest/more/extended_doc_spec.rb +588 -0
  74. data/spec/couchrest/more/extended_doc_subclass_spec.rb +98 -0
  75. data/spec/couchrest/more/extended_doc_view_spec.rb +426 -0
  76. data/spec/couchrest/more/property_spec.rb +169 -0
  77. data/spec/fixtures/attachments/README +3 -0
  78. data/spec/fixtures/attachments/couchdb.png +0 -0
  79. data/spec/fixtures/attachments/test.html +11 -0
  80. data/spec/fixtures/more/article.rb +34 -0
  81. data/spec/fixtures/more/card.rb +22 -0
  82. data/spec/fixtures/more/cat.rb +18 -0
  83. data/spec/fixtures/more/course.rb +14 -0
  84. data/spec/fixtures/more/event.rb +6 -0
  85. data/spec/fixtures/more/invoice.rb +17 -0
  86. data/spec/fixtures/more/person.rb +8 -0
  87. data/spec/fixtures/more/question.rb +6 -0
  88. data/spec/fixtures/more/service.rb +12 -0
  89. data/spec/fixtures/views/lib.js +3 -0
  90. data/spec/fixtures/views/test_view/lib.js +3 -0
  91. data/spec/fixtures/views/test_view/only-map.js +4 -0
  92. data/spec/fixtures/views/test_view/test-map.js +3 -0
  93. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  94. data/spec/spec.opts +6 -0
  95. data/spec/spec_helper.rb +37 -0
  96. data/utils/remap.rb +27 -0
  97. data/utils/subset.rb +30 -0
  98. metadata +198 -0
@@ -0,0 +1,104 @@
1
+ # Extracted from dm-validations 0.9.10
2
+ #
3
+ # Copyright (c) 2007 Guy van den Berg
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ module CouchRest
25
+ module Validation
26
+
27
+ ##
28
+ #
29
+ # @author Guy van den Berg
30
+ # @since 0.9
31
+ class NumericValidator < GenericValidator
32
+
33
+ def initialize(field_name, options={})
34
+ super
35
+ @field_name, @options = field_name, options
36
+ @options[:integer_only] = false unless @options.has_key?(:integer_only)
37
+ end
38
+
39
+ def call(target)
40
+ value = target.send(field_name)
41
+ return true if @options[:allow_nil] && value.nil?
42
+
43
+ value = (defined?(BigDecimal) && value.kind_of?(BigDecimal)) ? value.to_s('F') : value.to_s
44
+
45
+ error_message = @options[:message]
46
+ precision = @options[:precision]
47
+ scale = @options[:scale]
48
+
49
+ if @options[:integer_only]
50
+ return true if value =~ /\A[+-]?\d+\z/
51
+ error_message ||= ValidationErrors.default_error_message(:not_an_integer, field_name)
52
+ else
53
+ # FIXME: if precision and scale are not specified, can we assume that it is an integer?
54
+ # probably not, as floating point numbers don't have hard
55
+ # defined scale. the scale floats with the length of the
56
+ # integral and precision. Ie. if precision = 10 and integral
57
+ # portion of the number is 9834 (4 digits), the max scale will
58
+ # be 6 (10 - 4). But if the integral length is 1, max scale
59
+ # will be (10 - 1) = 9, so 1.234567890.
60
+ if precision && scale
61
+ #handles both Float when it has scale specified and BigDecimal
62
+ if precision > scale && scale > 0
63
+ return true if value =~ /\A[+-]?(?:\d{1,#{precision - scale}}|\d{0,#{precision - scale}}\.\d{1,#{scale}})\z/
64
+ elsif precision > scale && scale == 0
65
+ return true if value =~ /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
66
+ elsif precision == scale
67
+ return true if value =~ /\A[+-]?(?:0(?:\.\d{1,#{scale}})?)\z/
68
+ else
69
+ raise ArgumentError, "Invalid precision #{precision.inspect} and scale #{scale.inspect} for #{field_name} (value: #{value.inspect} #{value.class})"
70
+ end
71
+ elsif precision && scale.nil?
72
+ # for floats, if scale is not set
73
+
74
+ #total number of digits is less or equal precision
75
+ return true if value.gsub(/[^\d]/, '').length <= precision
76
+
77
+ #number of digits before decimal == precision, and the number is x.0. same as scale = 0
78
+ return true if value =~ /\A[+-]?(?:\d{1,#{precision}}(?:\.0)?)\z/
79
+ else
80
+ return true if value =~ /\A[+-]?(?:\d+|\d*\.\d+)\z/
81
+ end
82
+ error_message ||= ValidationErrors.default_error_message(:not_a_number, field_name)
83
+ end
84
+
85
+ add_error(target, error_message, field_name)
86
+
87
+ # TODO: check the gt, gte, lt, lte, and eq options
88
+
89
+ return false
90
+ end
91
+ end # class NumericValidator
92
+
93
+ module ValidatesIsNumber
94
+
95
+ # Validate whether a field is numeric
96
+ #
97
+ def validates_is_number(*fields)
98
+ opts = opts_from_validator_args(fields)
99
+ add_validator_to_context(opts, fields, CouchRest::Validation::NumericValidator)
100
+ end
101
+
102
+ end # module ValidatesIsNumber
103
+ end # module Validation
104
+ end # module CouchRest
@@ -0,0 +1,109 @@
1
+ # Extracted from dm-validations 0.9.10
2
+ #
3
+ # Copyright (c) 2007 Guy van den Berg
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining
6
+ # a copy of this software and associated documentation files (the
7
+ # "Software"), to deal in the Software without restriction, including
8
+ # without limitation the rights to use, copy, modify, merge, publish,
9
+ # distribute, sublicense, and/or sell copies of the Software, and to
10
+ # permit persons to whom the Software is furnished to do so, subject to
11
+ # the following conditions:
12
+ #
13
+ # The above copyright notice and this permission notice shall be
14
+ # included in all copies or substantial portions of the Software.
15
+ #
16
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+
24
+ module CouchRest
25
+ module Validation
26
+
27
+ ##
28
+ #
29
+ # @author Guy van den Berg
30
+ # @since 0.9
31
+ class RequiredFieldValidator < GenericValidator
32
+
33
+ def initialize(field_name, options={})
34
+ super
35
+ @field_name, @options = field_name, options
36
+ end
37
+
38
+ def call(target)
39
+ value = target.validation_property_value(field_name)
40
+ property = target.validation_property(field_name)
41
+ return true if present?(value, property)
42
+
43
+ error_message = @options[:message] || default_error(property)
44
+ add_error(target, error_message, field_name)
45
+
46
+ false
47
+ end
48
+
49
+ protected
50
+
51
+ # Boolean property types are considered present if non-nil.
52
+ # Other property types are considered present if non-blank.
53
+ # Non-properties are considered present if non-blank.
54
+ def present?(value, property)
55
+ boolean_type?(property) ? !value.nil? : !value.blank?
56
+ end
57
+
58
+ def default_error(property)
59
+ actual = boolean_type?(property) ? :nil : :blank
60
+ ValidationErrors.default_error_message(actual, field_name)
61
+ end
62
+
63
+ # Is +property+ a boolean property?
64
+ #
65
+ # Returns true for Boolean, ParanoidBoolean, TrueClass, etc. properties.
66
+ # Returns false for other property types.
67
+ # Returns false for non-properties.
68
+ def boolean_type?(property)
69
+ property ? property.type == TrueClass : false
70
+ end
71
+
72
+ end # class RequiredFieldValidator
73
+
74
+ module ValidatesPresent
75
+
76
+ ##
77
+ # Validates that the specified attribute is present.
78
+ #
79
+ # For most property types "being present" is the same as being "not
80
+ # blank" as determined by the attribute's #blank? method. However, in
81
+ # the case of Boolean, "being present" means not nil; i.e. true or
82
+ # false.
83
+ #
84
+ # @note
85
+ # dm-core's support lib adds the blank? method to many classes,
86
+ # @see lib/dm-core/support/blank.rb (dm-core) for more information.
87
+ #
88
+ # @example [Usage]
89
+ #
90
+ # class Page
91
+ #
92
+ # property :required_attribute, String
93
+ # property :another_required, String
94
+ # property :yet_again, String
95
+ #
96
+ # validates_present :required_attribute
97
+ # validates_present :another_required, :yet_again
98
+ #
99
+ # # a call to valid? will return false unless
100
+ # # all three attributes are !blank?
101
+ # end
102
+ def validates_present(*fields)
103
+ opts = opts_from_validator_args(fields)
104
+ add_validator_to_context(opts, fields, CouchRest::Validation::RequiredFieldValidator)
105
+ end
106
+
107
+ end # module ValidatesPresent
108
+ end # module Validation
109
+ end # module CouchRest
@@ -0,0 +1,201 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
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
+ end
32
+
33
+ it "should provide one-time access to uuids" do
34
+ @cr.next_uuid.should_not be_nil
35
+ end
36
+
37
+ describe "initializing a database" do
38
+ it "should return a db" do
39
+ db = @cr.database(TESTDB)
40
+ db.should be_an_instance_of(CouchRest::Database)
41
+ db.host.should == @cr.uri
42
+ end
43
+ end
44
+
45
+ describe "parsing urls" do
46
+ it "should parse just a dbname" do
47
+ db = CouchRest.parse "my-db"
48
+ db[:database].should == "my-db"
49
+ db[:host].should == "127.0.0.1:5984"
50
+ end
51
+ it "should parse a host and db" do
52
+ db = CouchRest.parse "127.0.0.1/my-db"
53
+ db[:database].should == "my-db"
54
+ db[:host].should == "127.0.0.1"
55
+ end
56
+ it "should parse a host and db with http" do
57
+ db = CouchRest.parse "http://127.0.0.1/my-db"
58
+ db[:database].should == "my-db"
59
+ db[:host].should == "127.0.0.1"
60
+ end
61
+ it "should parse a host with a port and db" do
62
+ db = CouchRest.parse "127.0.0.1:5555/my-db"
63
+ db[:database].should == "my-db"
64
+ db[:host].should == "127.0.0.1:5555"
65
+ end
66
+ it "should parse a host with a port and db with http" do
67
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db"
68
+ db[:database].should == "my-db"
69
+ db[:host].should == "127.0.0.1:5555"
70
+ end
71
+ it "should parse just a host" do
72
+ db = CouchRest.parse "http://127.0.0.1:5555/"
73
+ db[:database].should be_nil
74
+ db[:host].should == "127.0.0.1:5555"
75
+ end
76
+ it "should parse just a host no slash" do
77
+ db = CouchRest.parse "http://127.0.0.1:5555"
78
+ db[:host].should == "127.0.0.1:5555"
79
+ db[:database].should be_nil
80
+ end
81
+ it "should get docid" do
82
+ db = CouchRest.parse "127.0.0.1:5555/my-db/my-doc"
83
+ db[:database].should == "my-db"
84
+ db[:host].should == "127.0.0.1:5555"
85
+ db[:doc].should == "my-doc"
86
+ end
87
+ it "should get docid with http" do
88
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db/my-doc"
89
+ db[:database].should == "my-db"
90
+ db[:host].should == "127.0.0.1:5555"
91
+ db[:doc].should == "my-doc"
92
+ end
93
+
94
+ it "should parse a host and db" do
95
+ db = CouchRest.parse "127.0.0.1/my-db"
96
+ db[:database].should == "my-db"
97
+ db[:host].should == "127.0.0.1"
98
+ end
99
+ it "should parse a host and db with http" do
100
+ db = CouchRest.parse "http://127.0.0.1/my-db"
101
+ db[:database].should == "my-db"
102
+ db[:host].should == "127.0.0.1"
103
+ end
104
+ it "should parse a host with a port and db" do
105
+ db = CouchRest.parse "127.0.0.1:5555/my-db"
106
+ db[:database].should == "my-db"
107
+ db[:host].should == "127.0.0.1:5555"
108
+ end
109
+ it "should parse a host with a port and db with http" do
110
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db"
111
+ db[:database].should == "my-db"
112
+ db[:host].should == "127.0.0.1:5555"
113
+ end
114
+ it "should parse just a host" do
115
+ db = CouchRest.parse "http://127.0.0.1:5555/"
116
+ db[:database].should be_nil
117
+ db[:host].should == "127.0.0.1:5555"
118
+ end
119
+ it "should parse just a host no slash" do
120
+ db = CouchRest.parse "http://127.0.0.1:5555"
121
+ db[:host].should == "127.0.0.1:5555"
122
+ db[:database].should be_nil
123
+ end
124
+ it "should get docid" do
125
+ db = CouchRest.parse "127.0.0.1:5555/my-db/my-doc"
126
+ db[:database].should == "my-db"
127
+ db[:host].should == "127.0.0.1:5555"
128
+ db[:doc].should == "my-doc"
129
+ end
130
+ it "should get docid with http" do
131
+ db = CouchRest.parse "http://127.0.0.1:5555/my-db/my-doc"
132
+ db[:database].should == "my-db"
133
+ db[:host].should == "127.0.0.1:5555"
134
+ db[:doc].should == "my-doc"
135
+ end
136
+ end
137
+
138
+ describe "easy initializing a database adapter" do
139
+ it "should be possible without an explicit CouchRest instantiation" do
140
+ db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
141
+ db.should be_an_instance_of(CouchRest::Database)
142
+ db.host.should == "127.0.0.1:5984"
143
+ end
144
+ # TODO add https support (need test environment...)
145
+ # it "should work with https" # do
146
+ # db = CouchRest.database "https://127.0.0.1:5984/couchrest-test"
147
+ # db.host.should == "https://127.0.0.1:5984"
148
+ # end
149
+ it "should not create the database automatically" do
150
+ db = CouchRest.database "http://127.0.0.1:5984/couchrest-test"
151
+ lambda{db.info}.should raise_error(RestClient::ResourceNotFound)
152
+ end
153
+ end
154
+
155
+ describe "ensuring the db exists" do
156
+ it "should be super easy" do
157
+ db = CouchRest.database! "http://127.0.0.1:5984/couchrest-test-2"
158
+ db.name.should == 'couchrest-test-2'
159
+ db.info["db_name"].should == 'couchrest-test-2'
160
+ end
161
+ end
162
+
163
+ describe "successfully creating a database" do
164
+ it "should start without a database" do
165
+ @cr.databases.should_not include(TESTDB)
166
+ end
167
+ it "should return the created database" do
168
+ db = @cr.create_db(TESTDB)
169
+ db.should be_an_instance_of(CouchRest::Database)
170
+ end
171
+ it "should create the database" do
172
+ db = @cr.create_db(TESTDB)
173
+ @cr.databases.should include(TESTDB)
174
+ end
175
+ end
176
+
177
+ describe "failing to create a database because the name is taken" do
178
+ before(:each) do
179
+ db = @cr.create_db(TESTDB)
180
+ end
181
+ it "should start with the test database" do
182
+ @cr.databases.should include(TESTDB)
183
+ end
184
+ it "should PUT the database and raise an error" do
185
+ lambda{
186
+ @cr.create_db(TESTDB)
187
+ }.should raise_error(RestClient::Request::RequestFailed)
188
+ end
189
+ end
190
+
191
+ describe "using a proxy for RestClient connections" do
192
+ it "should set proxy url for RestClient" do
193
+ CouchRest.proxy 'http://localhost:8888/'
194
+ proxy_uri = URI.parse(HttpAbstraction.proxy)
195
+ proxy_uri.host.should eql( 'localhost' )
196
+ proxy_uri.port.should eql( 8888 )
197
+ CouchRest.proxy nil
198
+ end
199
+ end
200
+
201
+ end
@@ -0,0 +1,700 @@
1
+ require File.dirname(__FILE__) + '/../../spec_helper'
2
+
3
+ describe CouchRest::Database do
4
+ before(:each) do
5
+ @cr = CouchRest.new(COUCHHOST)
6
+ @db = @cr.database(TESTDB)
7
+ @db.delete! rescue nil
8
+ @db = @cr.create_db(TESTDB) rescue nil
9
+ end
10
+
11
+ describe "database name including slash" do
12
+ it "should escape the name in the URI" do
13
+ db = @cr.database("foo/bar")
14
+ db.name.should == "foo/bar"
15
+ db.root.should == "#{COUCHHOST}/foo%2Fbar"
16
+ db.uri.should == "/foo%2Fbar"
17
+ end
18
+ end
19
+
20
+ describe "map query with _temp_view in Javascript" do
21
+ before(:each) do
22
+ @db.bulk_save([
23
+ {"wild" => "and random"},
24
+ {"mild" => "yet local"},
25
+ {"another" => ["set","of","keys"]}
26
+ ])
27
+ @temp_view = {:map => "function(doc){for(var w in doc){ if(!w.match(/^_/))emit(w,doc[w])}}"}
28
+ end
29
+ it "should return the result of the temporary function" do
30
+ rs = @db.temp_view(@temp_view)
31
+ rs['rows'].select{|r|r['key'] == 'wild' && r['value'] == 'and random'}.length.should == 1
32
+ end
33
+ it "should work with a range" do
34
+ rs = @db.temp_view(@temp_view, :startkey => "b", :endkey => "z")
35
+ rs['rows'].length.should == 2
36
+ end
37
+ it "should work with a key" do
38
+ rs = @db.temp_view(@temp_view, :key => "wild")
39
+ rs['rows'].length.should == 1
40
+ end
41
+ it "should work with a limit" do
42
+ rs = @db.temp_view(@temp_view, :limit => 1)
43
+ rs['rows'].length.should == 1
44
+ end
45
+ it "should work with multi-keys" do
46
+ rs = @db.temp_view(@temp_view, :keys => ["another", "wild"])
47
+ rs['rows'].length.should == 2
48
+ end
49
+ end
50
+
51
+ describe "map/reduce query with _temp_view in Javascript" do
52
+ before(:each) do
53
+ @db.bulk_save([
54
+ {"beverage" => "beer", :count => 4},
55
+ {"beverage" => "beer", :count => 2},
56
+ {"beverage" => "tea", :count => 3}
57
+ ])
58
+ end
59
+ it "should return the result of the temporary function" do
60
+ rs = @db.temp_view(:map => "function(doc){emit(doc.beverage, doc.count)}", :reduce => "function(beverage,counts){return sum(counts)}")
61
+ # rs.should == 'x'
62
+ rs['rows'][0]['value'].should == 9
63
+ end
64
+ end
65
+
66
+ describe "saving a view" do
67
+ before(:each) do
68
+ @view = {'test' => {'map' => 'function(doc) {
69
+ if (doc.word && !/\W/.test(doc.word)) {
70
+ emit(doc.word,null);
71
+ }
72
+ }'}}
73
+ @db.save_doc({
74
+ "_id" => "_design/test",
75
+ :views => @view
76
+ })
77
+ end
78
+ it "should work properly" do
79
+ @db.bulk_save([
80
+ {"word" => "once"},
81
+ {"word" => "and again"}
82
+ ])
83
+ @db.view('test/test')['total_rows'].should == 1
84
+ end
85
+ it "should round trip" do
86
+ @db.get("_design/test")['views'].should == @view
87
+ end
88
+ end
89
+
90
+ describe "select from an existing view" do
91
+ before(:each) do
92
+ r = @db.save_doc({
93
+ "_id" => "_design/first",
94
+ :views => {
95
+ :test => {
96
+ :map => "function(doc){for(var w in doc){ if(!w.match(/^_/))emit(w,doc[w])}}"
97
+ }
98
+ }
99
+ })
100
+ @db.bulk_save([
101
+ {"wild" => "and random"},
102
+ {"mild" => "yet local"},
103
+ {"another" => ["set","of","keys"]}
104
+ ])
105
+ end
106
+ it "should have the view" do
107
+ @db.get('_design/first')['views']['test']['map'].should include("for(var w in doc)")
108
+ end
109
+ it "should list from the view" do
110
+ rs = @db.view('first/test')
111
+ rs['rows'].select{|r|r['key'] == 'wild' && r['value'] == 'and random'}.length.should == 1
112
+ end
113
+ it "should work with a range" do
114
+ rs = @db.view('first/test', :startkey => "b", :endkey => "z")
115
+ rs['rows'].length.should == 2
116
+ end
117
+ it "should work with a key" do
118
+ rs = @db.view('first/test', :key => "wild")
119
+ rs['rows'].length.should == 1
120
+ end
121
+ it "should work with a limit" do
122
+ rs = @db.view('first/test', :limit => 1)
123
+ rs['rows'].length.should == 1
124
+ end
125
+ it "should work with multi-keys" do
126
+ rs = @db.view('first/test', :keys => ["another", "wild"])
127
+ rs['rows'].length.should == 2
128
+ end
129
+ it "should accept a block" do
130
+ rows = []
131
+ rs = @db.view('first/test', :include_docs => true) do |row|
132
+ rows << row
133
+ end
134
+ rows.length.should == 4
135
+ rs["total_rows"].should == 3
136
+ end
137
+ end
138
+
139
+ describe "GET (document by id) when the doc exists" do
140
+ before(:each) do
141
+ @r = @db.save_doc({'lemons' => 'from texas', 'and' => 'spain'})
142
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
143
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
144
+ end
145
+ it "should get the document" do
146
+ doc = @db.get(@r['id'])
147
+ doc['lemons'].should == 'from texas'
148
+ end
149
+ it "should work with a funky id" do
150
+ @db.get(@docid)['will-exist'].should == 'here'
151
+ end
152
+ end
153
+
154
+ describe "POST (adding bulk documents)" do
155
+ it "should add them without ids" do
156
+ rs = @db.bulk_save([
157
+ {"wild" => "and random"},
158
+ {"mild" => "yet local"},
159
+ {"another" => ["set","of","keys"]}
160
+ ])
161
+ rs.each do |r|
162
+ @db.get(r['id']).rev.should == r["rev"]
163
+ end
164
+ end
165
+
166
+ it "should use uuids when ids aren't provided" do
167
+ @db.server.stub!(:next_uuid).and_return('asdf6sgadkfhgsdfusdf')
168
+
169
+ docs = [{'key' => 'value'}, {'_id' => 'totally-uniq'}]
170
+ id_docs = [{'key' => 'value', '_id' => 'asdf6sgadkfhgsdfusdf'}, {'_id' => 'totally-uniq'}]
171
+ CouchRest.should_receive(:post).with("http://127.0.0.1:5984/couchrest-test/_bulk_docs", {:docs => id_docs})
172
+
173
+ @db.bulk_save(docs)
174
+ end
175
+
176
+ it "should add them with uniq ids" do
177
+ rs = @db.bulk_save([
178
+ {"_id" => "oneB", "wild" => "and random"},
179
+ {"_id" => "twoB", "mild" => "yet local"},
180
+ {"another" => ["set","of","keys"]}
181
+ ])
182
+ rs.each do |r|
183
+ @db.get(r['id']).rev.should == r["rev"]
184
+ end
185
+ end
186
+
187
+ it "should empty the bulk save cache if no documents are given" do
188
+ @db.save_doc({"_id" => "bulk_cache_1", "val" => "test"}, true)
189
+ lambda do
190
+ @db.get('bulk_cache_1')
191
+ end.should raise_error(RestClient::ResourceNotFound)
192
+ @db.bulk_save
193
+ @db.get("bulk_cache_1")["val"].should == "test"
194
+ end
195
+
196
+ it "should raise an error that is useful for recovery" do
197
+ @r = @db.save_doc({"_id" => "taken", "field" => "stuff"})
198
+ begin
199
+ rs = @db.bulk_save([
200
+ {"_id" => "taken", "wild" => "and random"},
201
+ {"_id" => "free", "mild" => "yet local"},
202
+ {"another" => ["set","of","keys"]}
203
+ ])
204
+ rescue RestClient::RequestFailed => e
205
+ # soon CouchDB will provide _which_ docs conflicted
206
+ JSON.parse(e.response.body)['error'].should == 'conflict'
207
+ end
208
+ end
209
+ end
210
+
211
+ describe "new document without an id" do
212
+ it "should start empty" do
213
+ @db.documents["total_rows"].should == 0
214
+ end
215
+ it "should create the document and return the id" do
216
+ r = @db.save_doc({'lemons' => 'from texas', 'and' => 'spain'})
217
+ r2 = @db.get(r['id'])
218
+ r2["lemons"].should == "from texas"
219
+ end
220
+ it "should use PUT with UUIDs" do
221
+ CouchRest.should_receive(:put).and_return({"ok" => true, "id" => "100", "rev" => "55"})
222
+ r = @db.save_doc({'just' => ['another document']})
223
+ end
224
+
225
+ end
226
+
227
+ describe "fetch_attachment" do
228
+ before do
229
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
230
+ @doc = {
231
+ "_id" => "mydocwithattachment",
232
+ "field" => ["some value"],
233
+ "_attachments" => {
234
+ "test.html" => {
235
+ "type" => "text/html",
236
+ "data" => @attach
237
+ }
238
+ }
239
+ }
240
+ @db.save_doc(@doc)
241
+ end
242
+
243
+ # Depreacated
244
+ # it "should get the attachment with the doc's _id" do
245
+ # @db.fetch_attachment("mydocwithattachment", "test.html").should == @attach
246
+ # end
247
+
248
+ it "should get the attachment with the doc itself" do
249
+ @db.fetch_attachment(@db.get('mydocwithattachment'), 'test.html').should == @attach
250
+ end
251
+ end
252
+
253
+ describe "PUT attachment from file" do
254
+ before(:each) do
255
+ filename = FIXTURE_PATH + '/attachments/couchdb.png'
256
+ @file = File.open(filename)
257
+ end
258
+ after(:each) do
259
+ @file.close
260
+ end
261
+ it "should save the attachment to a new doc" do
262
+ r = @db.put_attachment({'_id' => 'attach-this'}, 'couchdb.png', image = @file.read, {:content_type => 'image/png'})
263
+ r['ok'].should == true
264
+ doc = @db.get("attach-this")
265
+ attachment = @db.fetch_attachment(doc,"couchdb.png")
266
+ attachment.should == image
267
+ end
268
+ end
269
+
270
+ describe "PUT document with attachment" do
271
+ before(:each) do
272
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
273
+ doc = {
274
+ "_id" => "mydocwithattachment",
275
+ "field" => ["some value"],
276
+ "_attachments" => {
277
+ "test.html" => {
278
+ "type" => "text/html",
279
+ "data" => @attach
280
+ }
281
+ }
282
+ }
283
+ @db.save_doc(doc)
284
+ @doc = @db.get("mydocwithattachment")
285
+ end
286
+ it "should save and be indicated" do
287
+ @doc['_attachments']['test.html']['length'].should == @attach.length
288
+ end
289
+ it "should be there" do
290
+ attachment = @db.fetch_attachment(@doc,"test.html")
291
+ attachment.should == @attach
292
+ end
293
+ end
294
+
295
+ describe "PUT document with attachment stub" do
296
+ before(:each) do
297
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
298
+ doc = {
299
+ '_id' => 'mydocwithattachment',
300
+ 'field' => ['some_value'],
301
+ '_attachments' => {
302
+ 'test.html' => {
303
+ 'type' => 'text/html', 'data' => @attach
304
+ }
305
+ }
306
+ }
307
+ @db.save_doc(doc)
308
+ doc['_rev'].should_not be_nil
309
+ doc['field'] << 'another value'
310
+ @db.save_doc(doc)["ok"].should be_true
311
+ end
312
+
313
+ it 'should be there' do
314
+ doc = @db.get('mydocwithattachment')
315
+ attachment = @db.fetch_attachment(doc, 'test.html')
316
+ Base64.decode64(attachment).should == @attach
317
+ end
318
+ end
319
+
320
+ describe "PUT document with multiple attachments" do
321
+ before(:each) do
322
+ @attach = "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
323
+ @attach2 = "<html><head><title>Other Doc</title></head><body><p>Has more words.</p></body></html>"
324
+ @doc = {
325
+ "_id" => "mydocwithattachment",
326
+ "field" => ["some value"],
327
+ "_attachments" => {
328
+ "test.html" => {
329
+ "type" => "text/html",
330
+ "data" => @attach
331
+ },
332
+ "other.html" => {
333
+ "type" => "text/html",
334
+ "data" => @attach2
335
+ }
336
+ }
337
+ }
338
+ @db.save_doc(@doc)
339
+ @doc = @db.get("mydocwithattachment")
340
+ end
341
+ it "should save and be indicated" do
342
+ @doc['_attachments']['test.html']['length'].should == @attach.length
343
+ @doc['_attachments']['other.html']['length'].should == @attach2.length
344
+ end
345
+ it "should be there" do
346
+ attachment = @db.fetch_attachment(@doc,"test.html")
347
+ attachment.should == @attach
348
+ end
349
+ it "should be there" do
350
+ attachment = @db.fetch_attachment(@doc,"other.html")
351
+ attachment.should == @attach2
352
+ end
353
+ end
354
+
355
+ describe "DELETE an attachment directly from the database" do
356
+ before(:each) do
357
+ doc = {
358
+ '_id' => 'mydocwithattachment',
359
+ '_attachments' => {
360
+ 'test.html' => {
361
+ 'type' => 'text/html',
362
+ 'data' => "<html><head><title>My Doc</title></head><body><p>Has words.</p></body></html>"
363
+ }
364
+ }
365
+ }
366
+ @db.save_doc(doc)
367
+ @doc = @db.get('mydocwithattachment')
368
+ end
369
+ it "should delete the attachment" do
370
+ lambda { @db.fetch_attachment(@doc,'test.html') }.should_not raise_error
371
+ @db.delete_attachment(@doc, "test.html")
372
+ lambda { @db.fetch_attachment(@doc,'test.html') }.should raise_error(RestClient::ResourceNotFound)
373
+ end
374
+ end
375
+
376
+ describe "POST document with attachment (with funky name)" do
377
+ before(:each) do
378
+ @attach = "<html><head><title>My Funky Doc</title></head><body><p>Has words.</p></body></html>"
379
+ @doc = {
380
+ "field" => ["some other value"],
381
+ "_attachments" => {
382
+ "http://example.com/stuff.cgi?things=and%20stuff" => {
383
+ "type" => "text/html",
384
+ "data" => @attach
385
+ }
386
+ }
387
+ }
388
+ @docid = @db.save_doc(@doc)['id']
389
+ end
390
+ it "should save and be indicated" do
391
+ doc = @db.get(@docid)
392
+ doc['_attachments']['http://example.com/stuff.cgi?things=and%20stuff']['length'].should == @attach.length
393
+ end
394
+ it "should be there" do
395
+ doc = @db.get(@docid)
396
+ attachment = @db.fetch_attachment(doc,"http://example.com/stuff.cgi?things=and%20stuff")
397
+ attachment.should == @attach
398
+ end
399
+ end
400
+
401
+ describe "PUT (new document with url id)" do
402
+ it "should create the document" do
403
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
404
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
405
+ lambda{@db.save_doc({'_id' => @docid})}.should raise_error(RestClient::Request::RequestFailed)
406
+ @db.get(@docid)['will-exist'].should == 'here'
407
+ end
408
+ end
409
+
410
+ describe "PUT (new document with id)" do
411
+ it "should start without the document" do
412
+ # r = @db.save_doc({'lemons' => 'from texas', 'and' => 'spain'})
413
+ @db.documents['rows'].each do |doc|
414
+ doc['id'].should_not == 'my-doc'
415
+ end
416
+ # should_not include({'_id' => 'my-doc'})
417
+ # this needs to be a loop over docs on content with the post
418
+ # or instead make it return something with a fancy <=> method
419
+ end
420
+ it "should create the document" do
421
+ @db.save_doc({'_id' => 'my-doc', 'will-exist' => 'here'})
422
+ lambda{@db.save_doc({'_id' => 'my-doc'})}.should raise_error(RestClient::Request::RequestFailed)
423
+ end
424
+ end
425
+
426
+ describe "PUT (existing document with rev)" do
427
+ before(:each) do
428
+ @db.save_doc({'_id' => 'my-doc', 'will-exist' => 'here'})
429
+ @doc = @db.get('my-doc')
430
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
431
+ @db.save_doc({'_id' => @docid, 'now' => 'save'})
432
+ end
433
+ it "should start with the document" do
434
+ @doc['will-exist'].should == 'here'
435
+ @db.get(@docid)['now'].should == 'save'
436
+ end
437
+ it "should save with url id" do
438
+ doc = @db.get(@docid)
439
+ doc['yaml'] = ['json', 'word.']
440
+ @db.save_doc doc
441
+ @db.get(@docid)['yaml'].should == ['json', 'word.']
442
+ end
443
+ it "should fail to resave without the rev" do
444
+ @doc['them-keys'] = 'huge'
445
+ @doc['_rev'] = 'wrong'
446
+ # @db.save_doc(@doc)
447
+ lambda {@db.save_doc(@doc)}.should raise_error
448
+ end
449
+ it "should update the document" do
450
+ @doc['them-keys'] = 'huge'
451
+ @db.save_doc(@doc)
452
+ now = @db.get('my-doc')
453
+ now['them-keys'].should == 'huge'
454
+ end
455
+ end
456
+
457
+ describe "cached bulk save" do
458
+ it "stores documents in a database-specific cache" do
459
+ td = {"_id" => "btd1", "val" => "test"}
460
+ @db.save_doc(td, true)
461
+ @db.instance_variable_get("@bulk_save_cache").should == [td]
462
+
463
+ end
464
+
465
+ it "doesn't save to the database until the configured cache size is exceded" do
466
+ @db.bulk_save_cache_limit = 3
467
+ td1 = {"_id" => "td1", "val" => true}
468
+ td2 = {"_id" => "td2", "val" => 4}
469
+ @db.save_doc(td1, true)
470
+ @db.save_doc(td2, true)
471
+ lambda do
472
+ @db.get(td1["_id"])
473
+ end.should raise_error(RestClient::ResourceNotFound)
474
+ lambda do
475
+ @db.get(td2["_id"])
476
+ end.should raise_error(RestClient::ResourceNotFound)
477
+ td3 = {"_id" => "td3", "val" => "foo"}
478
+ @db.save_doc(td3, true)
479
+ @db.get(td1["_id"])["val"].should == td1["val"]
480
+ @db.get(td2["_id"])["val"].should == td2["val"]
481
+ @db.get(td3["_id"])["val"].should == td3["val"]
482
+ end
483
+
484
+ it "clears the bulk save cache the first time a non bulk save is requested" do
485
+ td1 = {"_id" => "blah", "val" => true}
486
+ td2 = {"_id" => "steve", "val" => 3}
487
+ @db.bulk_save_cache_limit = 50
488
+ @db.save_doc(td1, true)
489
+ lambda do
490
+ @db.get(td1["_id"])
491
+ end.should raise_error(RestClient::ResourceNotFound)
492
+ @db.save_doc(td2)
493
+ @db.get(td1["_id"])["val"].should == td1["val"]
494
+ @db.get(td2["_id"])["val"].should == td2["val"]
495
+ end
496
+ end
497
+
498
+ describe "DELETE existing document" do
499
+ before(:each) do
500
+ @r = @db.save_doc({'lemons' => 'from texas', 'and' => 'spain'})
501
+ @docid = "http://example.com/stuff.cgi?things=and%20stuff"
502
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
503
+ end
504
+ it "should work" do
505
+ doc = @db.get(@r['id'])
506
+ doc['and'].should == 'spain'
507
+ @db.delete_doc doc
508
+ lambda{@db.get @r['id']}.should raise_error
509
+ end
510
+ it "should work with uri id" do
511
+ doc = @db.get(@docid)
512
+ @db.delete_doc doc
513
+ lambda{@db.get @docid}.should raise_error
514
+ end
515
+ it "should fail without an _id" do
516
+ lambda{@db.delete_doc({"not"=>"a real doc"})}.should raise_error(ArgumentError)
517
+ end
518
+ it "should defer actual deletion when using bulk save" do
519
+ doc = @db.get(@docid)
520
+ @db.delete_doc doc, true
521
+ lambda{@db.get @docid}.should_not raise_error
522
+ @db.bulk_save
523
+ lambda{@db.get @docid}.should raise_error
524
+ end
525
+
526
+ end
527
+
528
+ describe "COPY existing document" do
529
+ before :each do
530
+ @r = @db.save_doc({'artist' => 'Zappa', 'title' => 'Muffin Man'})
531
+ @docid = 'tracks/zappa/muffin-man'
532
+ @doc = @db.get(@r['id'])
533
+ end
534
+ describe "to a new location" do
535
+ it "should work" do
536
+ @db.copy_doc @doc, @docid
537
+ newdoc = @db.get(@docid)
538
+ newdoc['artist'].should == 'Zappa'
539
+ end
540
+ it "should fail without an _id" do
541
+ lambda{@db.copy({"not"=>"a real doc"})}.should raise_error(ArgumentError)
542
+ end
543
+ end
544
+ describe "to an existing location" do
545
+ before :each do
546
+ @db.save_doc({'_id' => @docid, 'will-exist' => 'here'})
547
+ end
548
+ it "should fail without a rev" do
549
+ lambda{@db.copy_doc @doc, @docid}.should raise_error(RestClient::RequestFailed)
550
+ end
551
+ it "should succeed with a rev" do
552
+ @to_be_overwritten = @db.get(@docid)
553
+ @db.copy_doc @doc, "#{@docid}?rev=#{@to_be_overwritten['_rev']}"
554
+ newdoc = @db.get(@docid)
555
+ newdoc['artist'].should == 'Zappa'
556
+ end
557
+ it "should succeed given the doc to overwrite" do
558
+ @to_be_overwritten = @db.get(@docid)
559
+ @db.copy_doc @doc, @to_be_overwritten
560
+ newdoc = @db.get(@docid)
561
+ newdoc['artist'].should == 'Zappa'
562
+ end
563
+ end
564
+ end
565
+
566
+
567
+ it "should list documents" do
568
+ 5.times do
569
+ @db.save_doc({'another' => 'doc', 'will-exist' => 'anywhere'})
570
+ end
571
+ ds = @db.documents
572
+ ds['rows'].should be_an_instance_of(Array)
573
+ ds['rows'][0]['id'].should_not be_nil
574
+ ds['total_rows'].should == 5
575
+ end
576
+
577
+ describe "documents / _all_docs" do
578
+ before(:each) do
579
+ 9.times do |i|
580
+ @db.save_doc({'_id' => "doc#{i}",'another' => 'doc', 'will-exist' => 'here'})
581
+ end
582
+ end
583
+ it "should list documents with keys and such" do
584
+ ds = @db.documents
585
+ ds['rows'].should be_an_instance_of(Array)
586
+ ds['rows'][0]['id'].should == "doc0"
587
+ ds['total_rows'].should == 9
588
+ end
589
+ it "should take query params" do
590
+ ds = @db.documents(:startkey => 'doc0', :endkey => 'doc3')
591
+ ds['rows'].length.should == 4
592
+ ds = @db.documents(:key => 'doc0')
593
+ ds['rows'].length.should == 1
594
+ end
595
+ it "should work with multi-key" do
596
+ rs = @db.documents :keys => ["doc0", "doc7"]
597
+ rs['rows'].length.should == 2
598
+ end
599
+ it "should work with include_docs" do
600
+ ds = @db.documents(:startkey => 'doc0', :endkey => 'doc3', :include_docs => true)
601
+ ds['rows'][0]['doc']['another'].should == "doc"
602
+ end
603
+ it "should have the bulk_load macro" do
604
+ rs = @db.bulk_load ["doc0", "doc7"]
605
+ rs['rows'].length.should == 2
606
+ rs['rows'][0]['doc']['another'].should == "doc"
607
+ end
608
+ end
609
+
610
+
611
+ describe "compacting a database" do
612
+ it "should compact the database" do
613
+ db = @cr.database('couchrest-test')
614
+ # r =
615
+ db.compact!
616
+ # r['ok'].should == true
617
+ end
618
+ end
619
+
620
+ describe "deleting a database" do
621
+ it "should start with the test database" do
622
+ @cr.databases.should include('couchrest-test')
623
+ end
624
+ it "should delete the database" do
625
+ db = @cr.database('couchrest-test')
626
+ # r =
627
+ db.delete!
628
+ # r['ok'].should == true
629
+ @cr.databases.should_not include('couchrest-test')
630
+ end
631
+ end
632
+
633
+ describe "replicating a database" do
634
+ before do
635
+ @db.save_doc({'_id' => 'test_doc', 'some-value' => 'foo'})
636
+ @other_db = @cr.database 'couchrest-test-replication'
637
+ @other_db.delete! rescue nil
638
+ @other_db = @cr.create_db 'couchrest-test-replication'
639
+ end
640
+
641
+ describe "via pulling" do
642
+ before do
643
+ @other_db.replicate_from @db
644
+ end
645
+
646
+ it "contains the document from the original database" do
647
+ doc = @other_db.get('test_doc')
648
+ doc['some-value'].should == 'foo'
649
+ end
650
+ end
651
+
652
+ describe "via pushing" do
653
+ before do
654
+ @db.replicate_to @other_db
655
+ end
656
+
657
+ it "copies the document to the other database" do
658
+ doc = @other_db.get('test_doc')
659
+ doc['some-value'].should == 'foo'
660
+ end
661
+ end
662
+ end
663
+
664
+ describe "creating a database" do
665
+ before(:each) do
666
+ @db = @cr.database('couchrest-test-db_to_create')
667
+ @db.delete! if @cr.databases.include?('couchrest-test-db_to_create')
668
+ end
669
+
670
+ it "should just work fine" do
671
+ @cr.databases.should_not include('couchrest-test-db_to_create')
672
+ @db.create!
673
+ @cr.databases.should include('couchrest-test-db_to_create')
674
+ end
675
+ end
676
+
677
+ describe "recreating a database" do
678
+ before(:each) do
679
+ @db = @cr.database('couchrest-test-db_to_create')
680
+ @db2 = @cr.database('couchrest-test-db_to_recreate')
681
+ @cr.databases.include?(@db.name) ? nil : @db.create!
682
+ @cr.databases.include?(@db2.name) ? @db2.delete! : nil
683
+ end
684
+
685
+ it "should drop and recreate a database" do
686
+ @cr.databases.should include(@db.name)
687
+ @db.recreate!
688
+ @cr.databases.should include(@db.name)
689
+ end
690
+
691
+ it "should recreate a db even tho it doesn't exist" do
692
+ @cr.databases.should_not include(@db2.name)
693
+ begin @db2.recreate! rescue nil end
694
+ @cr.databases.should include(@db2.name)
695
+ end
696
+
697
+ end
698
+
699
+
700
+ end