couchmodel 0.1.0.beta4 → 0.1.0
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.
- 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
|