couchmodel 0.1.1 → 0.1.2
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 +1 -1
- data/Rakefile +5 -5
- data/lib/core_extension/string.rb +10 -7
- data/lib/couch_model/base.rb +9 -9
- data/lib/couch_model/base/accessor.rb +2 -0
- data/lib/couch_model/collection.rb +3 -3
- data/lib/couch_model/database.rb +4 -4
- data/lib/couch_model/design.rb +11 -11
- data/lib/couch_model/server.rb +5 -5
- data/lib/transport/base.rb +65 -0
- data/lib/transport/json.rb +69 -0
- data/lib/transport/request/builder.rb +59 -0
- data/lib/transport/request/parameter/serializer.rb +60 -0
- data/spec/fake_transport_helper.rb +7 -2
- data/spec/lib/couch_model/active_model_spec.rb +6 -1
- data/spec/lib/couch_model/{core → base}/accessor_spec.rb +21 -9
- data/spec/lib/couch_model/{core → base}/association_spec.rb +0 -0
- data/spec/lib/couch_model/{core → base}/finder_spec.rb +0 -0
- data/spec/lib/couch_model/{core → base}/setup_spec.rb +0 -0
- 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/transport/base_spec.rb +49 -0
- data/spec/lib/transport/json_spec.rb +56 -0
- data/spec/lib/transport/request/builder_spec.rb +51 -0
- data/spec/lib/transport/request/parameter/serializer_spec.rb +16 -0
- metadata +26 -15
- data/lib/couch_model/transport.rb +0 -178
- data/spec/lib/couch_model/transport_spec.rb +0 -114
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'cgi'
|
2
|
+
|
3
|
+
module Transport
|
4
|
+
|
5
|
+
module Request
|
6
|
+
|
7
|
+
module Parameter
|
8
|
+
|
9
|
+
# Serializer for transport http parameters
|
10
|
+
class Serializer
|
11
|
+
|
12
|
+
def initialize(parameters = nil)
|
13
|
+
@parameters = parameters || { }
|
14
|
+
end
|
15
|
+
|
16
|
+
def query
|
17
|
+
return @serialized_parameters if @serialized_parameters
|
18
|
+
|
19
|
+
serialize_parameters
|
20
|
+
@serialized_parameters
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def serialize_parameters
|
26
|
+
quote_parameters
|
27
|
+
@serialized_parameters = if @parameters.nil? || @parameters.empty?
|
28
|
+
nil
|
29
|
+
else
|
30
|
+
@quoted_parameters.collect do |key, value|
|
31
|
+
self.class.pair key, value
|
32
|
+
end.join("&")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def quote_parameters
|
37
|
+
@quoted_parameters = { }
|
38
|
+
@parameters.each do |key, value|
|
39
|
+
encoded_key = CGI.escape(key.to_s)
|
40
|
+
@quoted_parameters[encoded_key] = self.class.escape value
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.pair(key, value)
|
45
|
+
value.is_a?(Array) ?
|
46
|
+
value.map{ |element| "#{key}=#{element}" }.join("&") :
|
47
|
+
"#{key}=#{value}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.escape(value)
|
51
|
+
value.is_a?(Array) ? value.map{ |element| CGI.escape element } : CGI.escape(value)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "lib", "transport", "json"))
|
1
2
|
require 'yaml'
|
2
3
|
|
3
4
|
module FakeTransport
|
@@ -11,7 +12,11 @@ module FakeTransport
|
|
11
12
|
end
|
12
13
|
|
13
14
|
def self.transport_class
|
14
|
-
|
15
|
+
Transport::JSON
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.unexpected_status_code_error_class
|
19
|
+
Transport::UnexpectedStatusCodeError
|
15
20
|
end
|
16
21
|
|
17
22
|
def self.fake!
|
@@ -30,7 +35,7 @@ module FakeTransport
|
|
30
35
|
hash[:headers] == headers
|
31
36
|
end
|
32
37
|
raise StandardError, "no fake request found for [#{http_method} #{url} #{parameters.inspect} #{headers.inspect}]" unless request
|
33
|
-
raise
|
38
|
+
raise unexpected_status_code_error_class.new(request[:response][:code].to_i, request[:response][:body]) if expected_status_code && expected_status_code.to_s != request[:response][:code]
|
34
39
|
request[:response][:body].dup
|
35
40
|
end
|
36
41
|
end
|
@@ -254,7 +254,12 @@ describe ActiveTestModel do
|
|
254
254
|
end
|
255
255
|
|
256
256
|
it "should return all attributes as xml" do
|
257
|
-
@model.to_xml
|
257
|
+
xml = @model.to_xml
|
258
|
+
xml.should =~ /^<\?xml version=.+1\.0.+ encoding=.+UTF-8.+\?>/
|
259
|
+
xml.should =~ /<model-class>ActiveTestModel<\/model-class>/
|
260
|
+
xml.should =~ /<-id>test_model_1<\/-id>/
|
261
|
+
xml.should =~ /<name>test<\/name>/
|
262
|
+
xml.should =~ /<email>test<\/email>/
|
258
263
|
end
|
259
264
|
|
260
265
|
end
|
@@ -5,6 +5,9 @@ class AccessorTestModel < CouchModel::Base
|
|
5
5
|
|
6
6
|
setup_database :url => "http://localhost:5984/test"
|
7
7
|
|
8
|
+
key_reader :test_one, :default => "test default"
|
9
|
+
key_writer :test_two, :default => "test default"
|
10
|
+
key_accessor :test_three, :default => "test default"
|
8
11
|
end
|
9
12
|
|
10
13
|
describe AccessorTestModel do
|
@@ -16,16 +19,21 @@ describe AccessorTestModel do
|
|
16
19
|
describe "key_reader" do
|
17
20
|
|
18
21
|
before :each do
|
19
|
-
AccessorTestModel.key_reader :test, :default => "test default"
|
20
22
|
@model = AccessorTestModel.new
|
21
23
|
end
|
22
24
|
|
23
25
|
it "should define a reader method" do
|
24
|
-
@model.should respond_to(:
|
26
|
+
@model.should respond_to(:test_one)
|
25
27
|
end
|
26
28
|
|
27
29
|
it "should set a default value" do
|
28
|
-
@model.
|
30
|
+
@model.test_one.should == "test default"
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should raise an exception if the reader method is already defined" do
|
34
|
+
lambda do
|
35
|
+
AccessorTestModel.key_reader :test_one
|
36
|
+
end.should raise_error(ArgumentError)
|
29
37
|
end
|
30
38
|
|
31
39
|
end
|
@@ -33,16 +41,21 @@ describe AccessorTestModel do
|
|
33
41
|
describe "key_writer" do
|
34
42
|
|
35
43
|
before :each do
|
36
|
-
AccessorTestModel.key_writer :test, :default => "test default"
|
37
44
|
@model = AccessorTestModel.new
|
38
45
|
end
|
39
46
|
|
40
47
|
it "should define a writer method" do
|
41
|
-
@model.should respond_to(:
|
48
|
+
@model.should respond_to(:test_two=)
|
42
49
|
end
|
43
50
|
|
44
51
|
it "should set a default value" do
|
45
|
-
|
52
|
+
AccessorTestModel.defaults["test_two"].should == "test default"
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should raise an exception if the writer method is already defined" do
|
56
|
+
lambda do
|
57
|
+
AccessorTestModel.key_writer :test_two
|
58
|
+
end.should raise_error(ArgumentError)
|
46
59
|
end
|
47
60
|
|
48
61
|
end
|
@@ -50,16 +63,15 @@ describe AccessorTestModel do
|
|
50
63
|
describe "key_accessor" do
|
51
64
|
|
52
65
|
before :each do
|
53
|
-
AccessorTestModel.key_accessor(:test, :default => "test default")
|
54
66
|
@model = AccessorTestModel.new
|
55
67
|
end
|
56
68
|
|
57
69
|
it "should define a reader method" do
|
58
|
-
@model.should respond_to(:
|
70
|
+
@model.should respond_to(:test_three)
|
59
71
|
end
|
60
72
|
|
61
73
|
it "should define a writer method" do
|
62
|
-
@model.should respond_to(:
|
74
|
+
@model.should respond_to(:test_three=)
|
63
75
|
end
|
64
76
|
|
65
77
|
end
|
File without changes
|
File without changes
|
File without changes
|
@@ -93,7 +93,7 @@ describe BaseTestModel do
|
|
93
93
|
end
|
94
94
|
|
95
95
|
it "should return false on wrong status code" do
|
96
|
-
|
96
|
+
Transport::JSON.stub!(:request).and_raise(Transport::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
|
-
|
113
|
+
Transport::JSON.stub!(:request).and_raise(Transport::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
|
-
|
146
|
+
Transport::JSON.stub!(:request).and_raise(Transport::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
|
-
|
178
|
+
Transport::JSON.stub!(:request).and_raise(Transport::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
|
-
|
44
|
+
Transport::JSON.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
|
-
|
62
|
+
Transport::JSON.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
|
-
|
52
|
+
Transport::JSON.stub!(:request).and_return(@response)
|
53
53
|
end
|
54
54
|
|
55
55
|
it "should create the database" do
|
56
|
-
|
56
|
+
Transport::JSON.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
|
-
|
86
|
+
Transport::JSON.stub!(:request).and_return(@response)
|
87
87
|
end
|
88
88
|
|
89
89
|
it "should delete the database" do
|
90
|
-
|
90
|
+
Transport::JSON.should_receive(:request).with(:delete, /test$/, anything).and_return(@response)
|
91
91
|
@database.delete!
|
92
92
|
end
|
93
93
|
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "transport", "base"))
|
3
|
+
|
4
|
+
describe Transport::Base do
|
5
|
+
|
6
|
+
use_real_transport!
|
7
|
+
|
8
|
+
describe "request" do
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@http_method = :get
|
12
|
+
@url = "http://localhost:5984/"
|
13
|
+
@options = { }
|
14
|
+
|
15
|
+
@request_builder = Transport::Request::Builder.new @http_method, @url, @options
|
16
|
+
|
17
|
+
@response = Object.new
|
18
|
+
@response.stub!(:code).and_return("200")
|
19
|
+
@response.stub!(:body).and_return("test")
|
20
|
+
Net::HTTP.stub!(:start).and_return(@response)
|
21
|
+
end
|
22
|
+
|
23
|
+
def do_request(options = { })
|
24
|
+
Transport::Base.request @http_method, @url, @options.merge(options)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should initialize the correct request builder" do
|
28
|
+
Transport::Request::Builder.should_receive(:new).with(@http_method, @url, @options).and_return(@request_builder)
|
29
|
+
do_request
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should perform the request" do
|
33
|
+
Net::HTTP.should_receive(:start).and_return(@response)
|
34
|
+
do_request
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should return the response" do
|
38
|
+
do_request.body.should == "test"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should raise UnexpectedStatusCodeError if responded status code is wrong" do
|
42
|
+
lambda do
|
43
|
+
do_request :expected_status_code => 201
|
44
|
+
end.should raise_error(Transport::UnexpectedStatusCodeError)
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "spec_helper"))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "lib", "transport", "json"))
|
3
|
+
|
4
|
+
describe Transport::JSON do
|
5
|
+
|
6
|
+
use_real_transport!
|
7
|
+
|
8
|
+
describe "request" do
|
9
|
+
|
10
|
+
before :each do
|
11
|
+
@http_method = :get
|
12
|
+
@url = "http://localhost:5984/"
|
13
|
+
@options = {
|
14
|
+
:auth_type => :basic,
|
15
|
+
:username => "test",
|
16
|
+
:password => "test",
|
17
|
+
:body => "test"
|
18
|
+
}
|
19
|
+
|
20
|
+
@request_builder = Transport::Request::Builder.new @http_method, @url, @options
|
21
|
+
|
22
|
+
@response = Object.new
|
23
|
+
@response.stub!(:code).and_return("200")
|
24
|
+
@response.stub!(:body).and_return("{\"test\":\"test\"}")
|
25
|
+
Net::HTTP.stub!(:start).and_return(@response)
|
26
|
+
end
|
27
|
+
|
28
|
+
def do_request(options = { })
|
29
|
+
Transport::JSON.request @http_method, @url, @options.merge(options)
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should initialize the correct request object" do
|
33
|
+
Transport::Request::Builder.should_receive(:new).with(
|
34
|
+
@http_method, @url, hash_including(:headers => { "Accept" => "application/json", "Content-Type" => "application/json" })
|
35
|
+
).and_return(@request_builder)
|
36
|
+
do_request
|
37
|
+
end
|
38
|
+
|
39
|
+
it "should perform the request" do
|
40
|
+
Net::HTTP.should_receive(:start).and_return(@response)
|
41
|
+
do_request
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return the parsed response" do
|
45
|
+
do_request.should == { "test" => "test" }
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should raise NotImplementedError if the given auth_type is wrong" do
|
49
|
+
lambda do
|
50
|
+
do_request :auth_type => :invalid
|
51
|
+
end.should raise_error(NotImplementedError)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "spec_helper"))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "lib", "transport", "request", "builder"))
|
3
|
+
|
4
|
+
describe Transport::Request::Builder do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@builder = Transport::Request::Builder.new :get,
|
8
|
+
"http://localhost:5984/test",
|
9
|
+
:headers => { "Test-Header" => "test" },
|
10
|
+
:parameters => { "test_parameter" => "test" }
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "uri" do
|
14
|
+
|
15
|
+
before :each do
|
16
|
+
@uri = @builder.uri
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should build an uri with the correct host, port and path" do
|
20
|
+
@uri.host.should == "localhost"
|
21
|
+
@uri.port.should == 5984
|
22
|
+
@uri.path.should == "/test"
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
describe "request" do
|
28
|
+
|
29
|
+
before :each do
|
30
|
+
@request = @builder.request
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should have the correct class" do
|
34
|
+
@request.should be_instance_of(Net::HTTP::Get)
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have the correct headers" do
|
38
|
+
@request["Test-Header"].should == "test"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should point to the correct path" do
|
42
|
+
@request.path.should == "/test?test_parameter=test"
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have the correct body" do
|
46
|
+
@request.body.should be_nil
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "spec_helper"))
|
2
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "..", "..", "..", "lib", "transport", "request", "parameter", "serializer"))
|
3
|
+
|
4
|
+
describe Transport::Request::Parameter::Serializer do
|
5
|
+
|
6
|
+
it "should return nil on an empty parameter hash" do
|
7
|
+
serializer = Transport::Request::Parameter::Serializer.new
|
8
|
+
serializer.query.should be_nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should return a correctly encoded query string" do
|
12
|
+
serializer = Transport::Request::Parameter::Serializer.new :foo => "bar", :test => [ "value1", "value2" ]
|
13
|
+
serializer.query.should == "foo=bar&test=value1&test=value2"
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|