couchmodel 0.1.0.beta4 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +8 -8
- data/Rakefile +34 -0
- data/lib/code_smells.reek +3 -0
- data/lib/couch_model/base.rb +8 -8
- data/lib/couch_model/collection.rb +2 -2
- data/lib/couch_model/database.rb +3 -3
- data/lib/couch_model/design.rb +14 -4
- data/lib/couch_model/server.rb +4 -4
- data/lib/couch_model/transport.rb +137 -48
- data/spec/fake_transport_helper.rb +28 -19
- data/spec/integration/basic_spec.rb +6 -1
- data/spec/integration/design/membership.design +5 -5
- data/spec/integration/design/user.design +6 -6
- data/spec/lib/couch_model/base_spec.rb +4 -4
- data/spec/lib/couch_model/collection_spec.rb +2 -2
- data/spec/lib/couch_model/database_spec.rb +4 -4
- data/spec/lib/couch_model/design/association_test_model_one.design +5 -5
- data/spec/lib/couch_model/design/base_test_model.design +6 -6
- data/spec/lib/couch_model/design/setup_test_model.design +6 -6
- data/spec/lib/couch_model/transport_spec.rb +70 -17
- data/spec/spec_helper.rb +4 -5
- metadata +13 -19
data/README.rdoc
CHANGED
@@ -66,20 +66,20 @@ a design document will be created (but not saved to the file). The design ducume
|
|
66
66
|
|
67
67
|
A design document should look like this
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
69
|
+
id: "test_design"
|
70
|
+
language: "javascript"
|
71
|
+
views:
|
72
|
+
view_name_1:
|
73
|
+
map:
|
74
74
|
function(document) {
|
75
75
|
...
|
76
76
|
};
|
77
|
-
|
77
|
+
reduce:
|
78
78
|
function(key, values, rereduce) {
|
79
79
|
...
|
80
80
|
};
|
81
|
-
|
82
|
-
|
81
|
+
view_name_2:
|
82
|
+
keys: [ "key_one", "key_two" ]
|
83
83
|
...
|
84
84
|
|
85
85
|
It will create the methods <tt>Model.view_name_1</tt> and <tt>Model.view_name_2</tt>, which returns the result of the
|
data/Rakefile
CHANGED
@@ -1,10 +1,44 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
gem 'rspec'
|
3
3
|
require 'spec'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
require 'rake/gempackagetask'
|
4
6
|
require 'spec/rake/spectask'
|
5
7
|
|
6
8
|
task :default => :spec
|
7
9
|
|
10
|
+
specification = Gem::Specification.new do |specification|
|
11
|
+
specification.name = "couchmodel"
|
12
|
+
specification.version = "0.1.0"
|
13
|
+
specification.date = "2010-03-31"
|
14
|
+
|
15
|
+
specification.authors = [ "Philipp Bruell" ]
|
16
|
+
specification.email = "b.phifty@gmail.com"
|
17
|
+
specification.homepage = "http://github.com/phifty/couchmodel"
|
18
|
+
specification.rubyforge_project = "couchmodel"
|
19
|
+
|
20
|
+
specification.summary = "CouchModel provides an interface to easly handle CouchDB documents."
|
21
|
+
specification.description = "CouchModel provides an interface to easly handle CouchDB documents. It also comes with a ActiveModel implementation to integrate into an Rails 3 application."
|
22
|
+
|
23
|
+
specification.has_rdoc = true
|
24
|
+
specification.files = [ "README.rdoc", "LICENSE", "Rakefile" ] + Dir["lib/**/*"] + Dir["spec/**/*"]
|
25
|
+
specification.extra_rdoc_files = [ "README.rdoc" ]
|
26
|
+
specification.require_path = "lib"
|
27
|
+
|
28
|
+
specification.test_files = Dir["spec/**/*_spec.rb"]
|
29
|
+
end
|
30
|
+
|
31
|
+
Rake::GemPackageTask.new(specification) do |package|
|
32
|
+
package.gem_spec = specification
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "Generate the rdoc"
|
36
|
+
Rake::RDocTask.new do |rdoc|
|
37
|
+
rdoc.rdoc_files.add [ "README.rdoc", "lib/**/*.rb" ]
|
38
|
+
rdoc.main = "README.rdoc"
|
39
|
+
rdoc.title = "CouchModel interface to handle CouchDB documents."
|
40
|
+
end
|
41
|
+
|
8
42
|
desc "Run all specs in spec directory"
|
9
43
|
Spec::Rake::SpecTask.new do |task|
|
10
44
|
task.spec_files = FileList["spec/lib/**/*_spec.rb"]
|
data/lib/couch_model/base.rb
CHANGED
@@ -63,9 +63,9 @@ module CouchModel
|
|
63
63
|
end
|
64
64
|
|
65
65
|
def load
|
66
|
-
load_response
|
66
|
+
load_response ExtendedTransport.request(:get, url, :expected_status_code => 200)
|
67
67
|
true
|
68
|
-
rescue
|
68
|
+
rescue ExtendedTransport::UnexpectedStatusCodeError => error
|
69
69
|
upgrade_unexpected_status_error error
|
70
70
|
end
|
71
71
|
|
@@ -77,10 +77,10 @@ module CouchModel
|
|
77
77
|
|
78
78
|
def destroy
|
79
79
|
return false if new?
|
80
|
-
|
80
|
+
ExtendedTransport.request :delete, self.url, :headers => { "If-Match" => self.rev }, :expected_status_code => 200
|
81
81
|
clear_rev
|
82
82
|
true
|
83
|
-
rescue
|
83
|
+
rescue ExtendedTransport::UnexpectedStatusCodeError => error
|
84
84
|
upgrade_unexpected_status_error error
|
85
85
|
end
|
86
86
|
|
@@ -105,19 +105,19 @@ module CouchModel
|
|
105
105
|
end
|
106
106
|
|
107
107
|
def create
|
108
|
-
response =
|
108
|
+
response = ExtendedTransport.request :post, self.database.url, :body => self.attributes, :expected_status_code => 201
|
109
109
|
self.id = response["id"]
|
110
110
|
self.rev = response["rev"]
|
111
111
|
true
|
112
|
-
rescue
|
112
|
+
rescue ExtendedTransport::UnexpectedStatusCodeError
|
113
113
|
false
|
114
114
|
end
|
115
115
|
|
116
116
|
def update
|
117
|
-
response =
|
117
|
+
response = ExtendedTransport.request :put, self.url, :body => self.attributes, :expected_status_code => 201
|
118
118
|
self.rev = response["rev"]
|
119
119
|
true
|
120
|
-
rescue
|
120
|
+
rescue ExtendedTransport::UnexpectedStatusCodeError
|
121
121
|
false
|
122
122
|
end
|
123
123
|
|
@@ -64,7 +64,7 @@ module CouchModel
|
|
64
64
|
end
|
65
65
|
|
66
66
|
def fetch_response
|
67
|
-
@response =
|
67
|
+
@response = ExtendedTransport.request(
|
68
68
|
:get, url,
|
69
69
|
:parameters => request_parameters,
|
70
70
|
:expected_status_code => 200
|
@@ -72,7 +72,7 @@ module CouchModel
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def fetch_meta_response
|
75
|
-
@response =
|
75
|
+
@response = ExtendedTransport.request(
|
76
76
|
:get, url,
|
77
77
|
:parameters => request_parameters.merge(:limit => 0),
|
78
78
|
:expected_status_code => 200
|
data/lib/couch_model/database.rb
CHANGED
@@ -25,7 +25,7 @@ module CouchModel
|
|
25
25
|
end
|
26
26
|
|
27
27
|
def create!
|
28
|
-
|
28
|
+
ExtendedTransport.request :put, url, :expected_status_code => 201
|
29
29
|
end
|
30
30
|
|
31
31
|
def create_if_missing!
|
@@ -33,7 +33,7 @@ module CouchModel
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def delete!
|
36
|
-
|
36
|
+
ExtendedTransport.request :delete, url, :expected_status_code => 200
|
37
37
|
end
|
38
38
|
|
39
39
|
def delete_if_exists!
|
@@ -41,7 +41,7 @@ module CouchModel
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def informations
|
44
|
-
|
44
|
+
ExtendedTransport.request :get, url, :expected_status_code => 200
|
45
45
|
end
|
46
46
|
|
47
47
|
def exists?
|
data/lib/couch_model/design.rb
CHANGED
@@ -33,7 +33,9 @@ module CouchModel
|
|
33
33
|
end
|
34
34
|
|
35
35
|
def load_file
|
36
|
-
|
36
|
+
hash = YAML::load_file self.filename
|
37
|
+
symbolize_hash_keys hash
|
38
|
+
self.id, self.language, self.views = hash.values_at(:id, :language, :views)
|
37
39
|
true
|
38
40
|
rescue Errno::ENOENT
|
39
41
|
false
|
@@ -65,7 +67,7 @@ module CouchModel
|
|
65
67
|
end
|
66
68
|
|
67
69
|
def exists?
|
68
|
-
|
70
|
+
ExtendedTransport.request :get, self.url, :expected_status_code => 200
|
69
71
|
true
|
70
72
|
rescue Transport::UnexpectedStatusCodeError
|
71
73
|
false
|
@@ -73,9 +75,9 @@ module CouchModel
|
|
73
75
|
|
74
76
|
def push
|
75
77
|
url = self.url
|
76
|
-
evaluate
|
78
|
+
evaluate ExtendedTransport.request(:get, url)
|
77
79
|
|
78
|
-
|
80
|
+
ExtendedTransport.request :put, url, :body => self.to_hash, :expected_status_code => 201
|
79
81
|
true
|
80
82
|
end
|
81
83
|
|
@@ -87,6 +89,14 @@ module CouchModel
|
|
87
89
|
|
88
90
|
attr_writer :rev
|
89
91
|
|
92
|
+
def symbolize_hash_keys(hash)
|
93
|
+
hash.keys.each do |key|
|
94
|
+
value = hash.delete key
|
95
|
+
symbolize_hash_keys value if value.is_a?(Hash)
|
96
|
+
hash[(key.to_sym rescue key) || key] = value
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
90
100
|
def evaluate(response)
|
91
101
|
self.rev = response["_rev"] if response.has_key?("_rev")
|
92
102
|
end
|
data/lib/couch_model/server.rb
CHANGED
@@ -19,19 +19,19 @@ module CouchModel
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def informations
|
22
|
-
|
22
|
+
ExtendedTransport.request :get, url + "/", :expected_status_code => 200
|
23
23
|
end
|
24
24
|
|
25
25
|
def statistics
|
26
|
-
|
26
|
+
ExtendedTransport.request :get, url + "/_stats", :expected_status_code => 200
|
27
27
|
end
|
28
28
|
|
29
29
|
def database_names
|
30
|
-
|
30
|
+
ExtendedTransport.request :get, url + "/_all_dbs", :expected_status_code => 200
|
31
31
|
end
|
32
32
|
|
33
33
|
def uuids(count = 1)
|
34
|
-
response =
|
34
|
+
response = ExtendedTransport.request :get, url + "/_uuids", :expected_status_code => 200, :parameters => { :count => count }
|
35
35
|
response["uuids"]
|
36
36
|
end
|
37
37
|
|
@@ -1,89 +1,178 @@
|
|
1
1
|
require 'uri'
|
2
|
+
require 'cgi'
|
2
3
|
require 'net/http'
|
3
4
|
require 'json'
|
4
5
|
|
5
6
|
module CouchModel
|
6
7
|
|
7
|
-
|
8
|
+
# Common transport layer for http transfers.
|
9
|
+
class Transport
|
10
|
+
|
11
|
+
attr_reader :http_method
|
12
|
+
attr_reader :url
|
13
|
+
attr_reader :options
|
14
|
+
attr_reader :headers
|
15
|
+
attr_reader :parameters
|
16
|
+
attr_reader :body
|
17
|
+
attr_reader :response
|
18
|
+
|
19
|
+
def initialize(http_method, url, options = { })
|
20
|
+
@http_method = http_method
|
21
|
+
@uri = URI.parse url
|
22
|
+
@headers = options[:headers] || { }
|
23
|
+
@parameters = options[:parameters] || { }
|
24
|
+
@body = options[:body]
|
25
|
+
end
|
8
26
|
|
9
|
-
|
10
|
-
|
11
|
-
|
27
|
+
def perform
|
28
|
+
initialize_request_class
|
29
|
+
initialize_request_path
|
30
|
+
initialize_request
|
31
|
+
initialize_request_body
|
32
|
+
perform_request
|
33
|
+
end
|
12
34
|
|
13
|
-
|
35
|
+
private
|
36
|
+
|
37
|
+
def initialize_request_class
|
38
|
+
request_class_name = @http_method.to_s.capitalize
|
39
|
+
raise NotImplementedError, "the request method #{http_method} is not implemented" unless Net::HTTP.const_defined?(request_class_name)
|
40
|
+
@request_class = Net::HTTP.const_get request_class_name
|
41
|
+
end
|
14
42
|
|
15
|
-
|
16
|
-
|
43
|
+
def initialize_request_path
|
44
|
+
serialize_parameters
|
45
|
+
@request_path = @uri.path + @serialized_parameters
|
46
|
+
end
|
47
|
+
|
48
|
+
def serialize_parameters
|
49
|
+
quote_parameters
|
50
|
+
@serialized_parameters = if @parameters.nil? || @parameters.empty?
|
51
|
+
""
|
52
|
+
else
|
53
|
+
"?" + @quoted_parameters.collect do |key, value|
|
54
|
+
value.is_a?(Array) ?
|
55
|
+
value.map{ |element| "#{key}=#{element}" }.join("&") :
|
56
|
+
"#{key}=#{value}"
|
57
|
+
end.join("&")
|
17
58
|
end
|
59
|
+
end
|
18
60
|
|
19
|
-
|
20
|
-
|
61
|
+
def quote_parameters
|
62
|
+
@quoted_parameters = { }
|
63
|
+
@parameters.each do |key, value|
|
64
|
+
encoded_key = CGI.escape(key.to_s)
|
65
|
+
@quoted_parameters[encoded_key] = value.is_a?(Array) ? value.map{ |element| CGI.escape element } : CGI.escape(value)
|
21
66
|
end
|
67
|
+
end
|
22
68
|
|
69
|
+
def initialize_request
|
70
|
+
@request = @request_class.new @request_path, @headers
|
23
71
|
end
|
24
72
|
|
25
|
-
def
|
26
|
-
|
73
|
+
def initialize_request_body
|
74
|
+
return unless [ :post, :put ].include?(@http_method.to_sym)
|
75
|
+
@request.body = @body ? @body : @serialized_parameters.sub(/^\?/, "")
|
76
|
+
end
|
27
77
|
|
28
|
-
|
29
|
-
response =
|
78
|
+
def perform_request
|
79
|
+
@response = Net::HTTP.start(@uri.host, @uri.port) do |connection|
|
80
|
+
connection.request @request
|
81
|
+
end
|
82
|
+
end
|
30
83
|
|
31
|
-
|
32
|
-
|
84
|
+
def self.request(http_method, url, options = { })
|
85
|
+
transport = new http_method, url, options
|
86
|
+
transport.perform
|
87
|
+
transport.response
|
33
88
|
end
|
34
89
|
|
35
|
-
|
36
|
-
|
37
|
-
|
90
|
+
end
|
91
|
+
|
92
|
+
# Extended transport layer for http transfers. Basic authorization and JSON transfers are supported.
|
93
|
+
class ExtendedTransport < Transport
|
94
|
+
|
95
|
+
# The UnexpectedStatusCodeError is raised if the :expected_status_code option is given to
|
96
|
+
# the :request method and the responded status code is different from the expected one.
|
97
|
+
class UnexpectedStatusCodeError < StandardError
|
98
|
+
|
99
|
+
attr_reader :status_code
|
100
|
+
attr_reader :message
|
101
|
+
|
102
|
+
def initialize(status_code, message = nil)
|
103
|
+
@status_code, @message = status_code, message
|
104
|
+
end
|
105
|
+
|
106
|
+
def to_s
|
107
|
+
"#{super} received status code #{self.status_code}" + (@message ? " [#{@message}]" : "")
|
108
|
+
end
|
38
109
|
|
39
|
-
request_object = send :"#{http_method}_request_object", uri.path, (options[:parameters] || { }), (options[:headers] || { })
|
40
|
-
request_object.body = options[:body].to_json if options.has_key?(:body)
|
41
|
-
request_object
|
42
110
|
end
|
43
111
|
|
44
|
-
|
45
|
-
|
46
|
-
|
112
|
+
attr_reader :expected_status_code
|
113
|
+
attr_reader :auth_type
|
114
|
+
attr_reader :username
|
115
|
+
attr_reader :password
|
116
|
+
|
117
|
+
def initialize(http_method, url, options = { })
|
118
|
+
super http_method, url, options
|
119
|
+
@expected_status_code = options[:expected_status_code]
|
120
|
+
@auth_type = options[:auth_type]
|
121
|
+
@username = options[:username]
|
122
|
+
@password = options[:password]
|
47
123
|
end
|
48
124
|
|
49
|
-
def
|
50
|
-
|
51
|
-
|
125
|
+
def perform
|
126
|
+
initialize_headers
|
127
|
+
super
|
128
|
+
check_status_code
|
129
|
+
parse_response
|
52
130
|
end
|
53
131
|
|
54
|
-
|
55
|
-
|
56
|
-
|
132
|
+
private
|
133
|
+
|
134
|
+
def initialize_headers
|
135
|
+
@headers["Accept"] = "application/json"
|
57
136
|
end
|
58
137
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
138
|
+
def initialize_request
|
139
|
+
super
|
140
|
+
if @auth_type == :basic
|
141
|
+
@request.basic_auth @username, @password
|
142
|
+
elsif @auth_type
|
143
|
+
raise NotImplementedError, "the given auth_type [#{@auth_type}] is not implemented"
|
144
|
+
end
|
62
145
|
end
|
63
146
|
|
64
|
-
def
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end.reverse.join("&")
|
147
|
+
def quote_parameters
|
148
|
+
@parameters.each do |key, value|
|
149
|
+
@parameters[key] = value.to_json if value.respond_to?(:to_json)
|
150
|
+
end
|
151
|
+
super
|
70
152
|
end
|
71
153
|
|
72
|
-
def
|
73
|
-
|
74
|
-
|
154
|
+
def initialize_request_body
|
155
|
+
super
|
156
|
+
if @body
|
157
|
+
@request.body = @body.to_json
|
158
|
+
@request["Content-Type"] = "application/json"
|
75
159
|
end
|
76
160
|
end
|
77
161
|
|
78
|
-
def
|
79
|
-
|
80
|
-
|
162
|
+
def check_status_code
|
163
|
+
return unless @expected_status_code
|
164
|
+
response_code = @response.code
|
165
|
+
response_body = @response.body
|
166
|
+
raise UnexpectedStatusCodeError.new(response_code.to_i, response_body) if @expected_status_code.to_s != response_code
|
81
167
|
end
|
82
168
|
|
83
|
-
def
|
84
|
-
|
169
|
+
def parse_response
|
170
|
+
body = @response.body
|
171
|
+
@response = body.nil? ? nil : JSON.parse(body)
|
172
|
+
rescue JSON::ParserError
|
173
|
+
@response = body.to_s
|
85
174
|
end
|
86
175
|
|
87
176
|
end
|
88
177
|
|
89
|
-
end
|
178
|
+
end
|
@@ -1,29 +1,38 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
|
-
module
|
3
|
+
module FakeTransport
|
4
4
|
|
5
|
-
|
5
|
+
def self.enable!
|
6
|
+
@enabled = true
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.disable!
|
10
|
+
@enabled = false
|
11
|
+
end
|
6
12
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
13
|
+
def self.transport_class
|
14
|
+
CouchModel::ExtendedTransport
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.fake!
|
18
|
+
return unless @enabled
|
19
|
+
@@fake ||= YAML::load_file File.join(File.dirname(__FILE__), "fake_transport.yml")
|
20
|
+
transport_class.stub!(:request).and_return do |http_method, url, options|
|
21
|
+
options ||= { }
|
22
|
+
parameters = options[:parameters]
|
23
|
+
headers = options[:headers]
|
24
|
+
expected_status_code = options[:expected_status_code]
|
14
25
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
raise StandardError, "no fake request found for [#{http_method} #{url} #{parameters.inspect} #{headers.inspect}]" unless request
|
22
|
-
raise UnexpectedStatusCodeError, request[:response][:code].to_i if expected_status_code && expected_status_code.to_s != request[:response][:code]
|
23
|
-
request[:response][:body].dup
|
26
|
+
request = @@fake.detect do |hash|
|
27
|
+
hash[:http_method].to_s == http_method.to_s &&
|
28
|
+
hash[:url].to_s == url.to_s &&
|
29
|
+
hash[:parameters] == parameters &&
|
30
|
+
hash[:headers] == headers
|
24
31
|
end
|
32
|
+
raise StandardError, "no fake request found for [#{http_method} #{url} #{parameters.inspect} #{headers.inspect}]" unless request
|
33
|
+
raise transport_class::UnexpectedStatusCodeError.new(request[:response][:code].to_i, request[:response][:body]) if expected_status_code && expected_status_code.to_s != request[:response][:code]
|
34
|
+
request[:response][:body].dup
|
25
35
|
end
|
26
|
-
|
27
36
|
end
|
28
37
|
|
29
38
|
end
|
@@ -121,7 +121,12 @@ describe "integration" do
|
|
121
121
|
describe "all" do
|
122
122
|
|
123
123
|
it "should include the saved user" do
|
124
|
-
|
124
|
+
begin
|
125
|
+
User.all.should include(@user_one)
|
126
|
+
rescue Object => error
|
127
|
+
puts error.backtrace
|
128
|
+
raise error
|
129
|
+
end
|
125
130
|
User.all.should include(@user_two)
|
126
131
|
end
|
127
132
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
id: "membership"
|
2
|
+
language: "javascript"
|
3
|
+
views:
|
4
|
+
by_user_id_and_created_at:
|
5
|
+
keys: [ "user_id", "created_at" ]
|
@@ -1,14 +1,14 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
id: "user"
|
2
|
+
language: "javascript"
|
3
|
+
views:
|
4
|
+
user_count:
|
5
|
+
map:
|
6
6
|
function(document) {
|
7
7
|
if (document['model_class'] == 'User') {
|
8
8
|
emit('user_count', 1);
|
9
9
|
}
|
10
10
|
}
|
11
|
-
|
11
|
+
reduce:
|
12
12
|
function(keys, values, rereduce) {
|
13
13
|
return sum(values);
|
14
14
|
}
|
@@ -93,7 +93,7 @@ describe BaseTestModel do
|
|
93
93
|
end
|
94
94
|
|
95
95
|
it "should return false on wrong status code" do
|
96
|
-
CouchModel::
|
96
|
+
CouchModel::ExtendedTransport.stub!(:request).and_raise(CouchModel::ExtendedTransport::UnexpectedStatusCodeError.new(404))
|
97
97
|
do_save.should be_false
|
98
98
|
end
|
99
99
|
|
@@ -110,7 +110,7 @@ describe BaseTestModel do
|
|
110
110
|
end
|
111
111
|
|
112
112
|
it "should return false on wrong status code" do
|
113
|
-
CouchModel::
|
113
|
+
CouchModel::ExtendedTransport.stub!(:request).and_raise(CouchModel::ExtendedTransport::UnexpectedStatusCodeError.new(404))
|
114
114
|
do_save.should be_false
|
115
115
|
end
|
116
116
|
|
@@ -143,7 +143,7 @@ describe BaseTestModel do
|
|
143
143
|
end
|
144
144
|
|
145
145
|
it "should raise NotFoundError on wrong status code" do
|
146
|
-
CouchModel::
|
146
|
+
CouchModel::ExtendedTransport.stub!(:request).and_raise(CouchModel::ExtendedTransport::UnexpectedStatusCodeError.new(404))
|
147
147
|
lambda do
|
148
148
|
do_destroy
|
149
149
|
end.should raise_error(CouchModel::Base::NotFoundError)
|
@@ -175,7 +175,7 @@ describe BaseTestModel do
|
|
175
175
|
end
|
176
176
|
|
177
177
|
it "should return nil on error" do
|
178
|
-
CouchModel::
|
178
|
+
CouchModel::ExtendedTransport.stub!(:request).and_raise(CouchModel::ExtendedTransport::UnexpectedStatusCodeError.new(500))
|
179
179
|
model = BaseTestModel.create :id => "test_model_1"
|
180
180
|
model.should be_nil
|
181
181
|
end
|
@@ -41,7 +41,7 @@ describe CouchModel::Collection do
|
|
41
41
|
describe "without a previously performed fetch" do
|
42
42
|
|
43
43
|
it "should perform a meta fetch (with a limit of zero)" do
|
44
|
-
CouchModel::
|
44
|
+
CouchModel::ExtendedTransport.should_receive(:request).with(anything, anything,
|
45
45
|
hash_including(:parameters => { :include_docs => true, :limit => 0 }))
|
46
46
|
@collection.total_count
|
47
47
|
end
|
@@ -59,7 +59,7 @@ describe CouchModel::Collection do
|
|
59
59
|
end
|
60
60
|
|
61
61
|
it "should not perform another fetch" do
|
62
|
-
CouchModel::
|
62
|
+
CouchModel::ExtendedTransport.should_not_receive(:request)
|
63
63
|
@collection.total_count
|
64
64
|
end
|
65
65
|
|
@@ -49,11 +49,11 @@ describe CouchModel::Database do
|
|
49
49
|
|
50
50
|
before :each do
|
51
51
|
@response = { :code => "201" }
|
52
|
-
CouchModel::
|
52
|
+
CouchModel::ExtendedTransport.stub!(:request).and_return(@response)
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should create the database" do
|
56
|
-
CouchModel::
|
56
|
+
CouchModel::ExtendedTransport.should_receive(:request).with(:put, /test$/, anything).and_return(@response)
|
57
57
|
@database.create!
|
58
58
|
end
|
59
59
|
|
@@ -83,11 +83,11 @@ describe CouchModel::Database do
|
|
83
83
|
|
84
84
|
before :each do
|
85
85
|
@response = { :code => "200" }
|
86
|
-
CouchModel::
|
86
|
+
CouchModel::ExtendedTransport.stub!(:request).and_return(@response)
|
87
87
|
end
|
88
88
|
|
89
89
|
it "should delete the database" do
|
90
|
-
CouchModel::
|
90
|
+
CouchModel::ExtendedTransport.should_receive(:request).with(:delete, /test$/, anything).and_return(@response)
|
91
91
|
@database.delete!
|
92
92
|
end
|
93
93
|
|
@@ -1,5 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
1
|
+
id: "test_design"
|
2
|
+
language: "javascript"
|
3
|
+
views:
|
4
|
+
by_related_id_and_name:
|
5
|
+
keys: [ "related_id", "name" ]
|
@@ -3,19 +3,19 @@ require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "li
|
|
3
3
|
|
4
4
|
describe CouchModel::Transport do
|
5
5
|
|
6
|
-
|
6
|
+
use_real_transport!
|
7
7
|
|
8
|
-
|
8
|
+
describe "request" do
|
9
9
|
|
10
10
|
before :each do
|
11
11
|
@http_method = :get
|
12
12
|
@url = "http://localhost:5984/"
|
13
13
|
@options = { }
|
14
14
|
|
15
|
-
@request = Net::HTTP::Get.new "/"
|
15
|
+
@request = Net::HTTP::Get.new "/", { }
|
16
16
|
@response = Object.new
|
17
17
|
@response.stub!(:code).and_return("200")
|
18
|
-
@response.stub!(:body).and_return("
|
18
|
+
@response.stub!(:body).and_return("test")
|
19
19
|
Net::HTTP.stub!(:start).and_return(@response)
|
20
20
|
end
|
21
21
|
|
@@ -33,29 +33,82 @@ describe CouchModel::Transport do
|
|
33
33
|
do_request
|
34
34
|
end
|
35
35
|
|
36
|
-
it "should
|
37
|
-
|
38
|
-
|
39
|
-
|
36
|
+
it "should return the response" do
|
37
|
+
do_request.body.should == "test"
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with parameters" do
|
41
|
+
|
42
|
+
before :each do
|
43
|
+
@options.merge! :parameters => { :foo => "bar", :test => [ "value1", "value2" ] }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should initialize the correct request object" do
|
47
|
+
Net::HTTP::Get.should_receive(:new).with(
|
48
|
+
"/?foo=bar&test=value1&test=value2", { }
|
49
|
+
).and_return(@request)
|
50
|
+
do_request
|
51
|
+
end
|
52
|
+
|
40
53
|
end
|
41
54
|
|
42
55
|
end
|
43
56
|
|
44
|
-
|
57
|
+
end
|
58
|
+
|
59
|
+
describe CouchModel::ExtendedTransport do
|
60
|
+
|
61
|
+
use_real_transport!
|
62
|
+
|
63
|
+
describe "request" do
|
45
64
|
|
46
65
|
before :each do
|
47
|
-
@
|
66
|
+
@http_method = :get
|
67
|
+
@url = "http://localhost:5984/"
|
68
|
+
@options = {
|
69
|
+
:auth_type => :basic,
|
70
|
+
:username => "test",
|
71
|
+
:password => "test",
|
72
|
+
:expected_status_code => 200
|
73
|
+
}
|
74
|
+
|
75
|
+
@request = Net::HTTP::Get.new "/", { }
|
76
|
+
@response = Object.new
|
77
|
+
@response.stub!(:code).and_return("200")
|
78
|
+
@response.stub!(:body).and_return("{\"test\":\"test\"}")
|
79
|
+
Net::HTTP.stub!(:start).and_return(@response)
|
48
80
|
end
|
49
81
|
|
50
|
-
|
51
|
-
CouchModel::
|
82
|
+
def do_request(options = { })
|
83
|
+
CouchModel::ExtendedTransport.request @http_method, @url, @options.merge(options)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "should initialize the correct request object" do
|
87
|
+
Net::HTTP::Get.should_receive(:new).with("/", { "Accept" => "application/json" }).and_return(@request)
|
88
|
+
do_request
|
52
89
|
end
|
53
|
-
|
54
|
-
it "should
|
55
|
-
|
56
|
-
|
90
|
+
|
91
|
+
it "should perform the request" do
|
92
|
+
Net::HTTP.should_receive(:start).and_return(@response)
|
93
|
+
do_request
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should return the parsed response" do
|
97
|
+
do_request.should == { "test" => "test" }
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should raise NotImplementedError if the given auth_type is wrong" do
|
101
|
+
lambda do
|
102
|
+
do_request :auth_type => :invalid
|
103
|
+
end.should raise_error(NotImplementedError)
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should raise UnexpectedStatusCodeError if responded status code is wrong" do
|
107
|
+
lambda do
|
108
|
+
do_request :expected_status_code => 201
|
109
|
+
end.should raise_error(CouchModel::ExtendedTransport::UnexpectedStatusCodeError)
|
57
110
|
end
|
58
111
|
|
59
112
|
end
|
60
113
|
|
61
|
-
end
|
114
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -2,13 +2,12 @@ require 'rubygems'
|
|
2
2
|
gem 'rspec', '1.3.0'
|
3
3
|
require 'spec'
|
4
4
|
|
5
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "couch_model", "configuration"))
|
6
5
|
require File.join(File.dirname(__FILE__), "fake_transport_helper")
|
7
6
|
|
8
|
-
|
7
|
+
FakeTransport.enable!
|
9
8
|
Spec::Runner.configure do |configuration|
|
10
9
|
configuration.before :each do
|
11
|
-
|
10
|
+
FakeTransport.fake!
|
12
11
|
end
|
13
12
|
end
|
14
13
|
|
@@ -16,11 +15,11 @@ def use_real_transport!
|
|
16
15
|
class_eval do
|
17
16
|
|
18
17
|
before :all do
|
19
|
-
|
18
|
+
FakeTransport.disable!
|
20
19
|
end
|
21
20
|
|
22
21
|
after :all do
|
23
|
-
|
22
|
+
FakeTransport.enable!
|
24
23
|
end
|
25
24
|
|
26
25
|
end
|
metadata
CHANGED
@@ -1,21 +1,20 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: couchmodel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 1
|
8
8
|
- 0
|
9
|
-
|
10
|
-
version: 0.1.0.beta4
|
9
|
+
version: 0.1.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
|
-
-
|
12
|
+
- Philipp Bruell
|
14
13
|
autorequire:
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date: 2010-03-
|
17
|
+
date: 2010-03-31 00:00:00 +02:00
|
19
18
|
default_executable:
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -48,6 +47,7 @@ files:
|
|
48
47
|
- lib/couch_model.rb
|
49
48
|
- lib/core_extension/string.rb
|
50
49
|
- lib/core_extension/array.rb
|
50
|
+
- lib/code_smells.reek
|
51
51
|
- spec/spec_helper.rb
|
52
52
|
- spec/lib/couch_model/view_spec.rb
|
53
53
|
- spec/lib/couch_model/server_spec.rb
|
@@ -79,10 +79,8 @@ homepage: http://github.com/phifty/couchmodel
|
|
79
79
|
licenses: []
|
80
80
|
|
81
81
|
post_install_message:
|
82
|
-
rdoc_options:
|
83
|
-
|
84
|
-
- --main
|
85
|
-
- README.rdoc
|
82
|
+
rdoc_options: []
|
83
|
+
|
86
84
|
require_paths:
|
87
85
|
- lib
|
88
86
|
required_ruby_version: !ruby/object:Gem::Requirement
|
@@ -90,22 +88,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
90
88
|
- - ">="
|
91
89
|
- !ruby/object:Gem::Version
|
92
90
|
segments:
|
93
|
-
-
|
94
|
-
|
95
|
-
- 1
|
96
|
-
version: 1.9.1
|
91
|
+
- 0
|
92
|
+
version: "0"
|
97
93
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
98
94
|
requirements:
|
99
|
-
- - "
|
95
|
+
- - ">="
|
100
96
|
- !ruby/object:Gem::Version
|
101
97
|
segments:
|
102
|
-
-
|
103
|
-
|
104
|
-
- 1
|
105
|
-
version: 1.3.1
|
98
|
+
- 0
|
99
|
+
version: "0"
|
106
100
|
requirements: []
|
107
101
|
|
108
|
-
rubyforge_project:
|
102
|
+
rubyforge_project: couchmodel
|
109
103
|
rubygems_version: 1.3.6
|
110
104
|
signing_key:
|
111
105
|
specification_version: 3
|