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 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
- :id: "test_design"
70
- :language: "javascript"
71
- :views:
72
- :view_name_1:
73
- :map:
69
+ id: "test_design"
70
+ language: "javascript"
71
+ views:
72
+ view_name_1:
73
+ map:
74
74
  function(document) {
75
75
  ...
76
76
  };
77
- :reduce:
77
+ reduce:
78
78
  function(key, values, rereduce) {
79
79
  ...
80
80
  };
81
- :view_name_2:
82
- :keys: [ "key_one", "key_two" ]
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"]
@@ -0,0 +1,3 @@
1
+ ---
2
+ LongMethod:
3
+ max_statements: 9
@@ -63,9 +63,9 @@ module CouchModel
63
63
  end
64
64
 
65
65
  def load
66
- load_response Transport.request(:get, url, :expected_status_code => 200)
66
+ load_response ExtendedTransport.request(:get, url, :expected_status_code => 200)
67
67
  true
68
- rescue Transport::UnexpectedStatusCodeError => error
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
- Transport.request :delete, self.url, :headers => { "If-Match" => self.rev }, :expected_status_code => 200
80
+ ExtendedTransport.request :delete, self.url, :headers => { "If-Match" => self.rev }, :expected_status_code => 200
81
81
  clear_rev
82
82
  true
83
- rescue Transport::UnexpectedStatusCodeError => error
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 = Transport.request :post, self.database.url, :body => self.attributes, :expected_status_code => 201
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 Transport::UnexpectedStatusCodeError
112
+ rescue ExtendedTransport::UnexpectedStatusCodeError
113
113
  false
114
114
  end
115
115
 
116
116
  def update
117
- response = Transport.request :put, self.url, :body => self.attributes, :expected_status_code => 201
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 Transport::UnexpectedStatusCodeError
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 = Transport.request(
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 = Transport.request(
75
+ @response = ExtendedTransport.request(
76
76
  :get, url,
77
77
  :parameters => request_parameters.merge(:limit => 0),
78
78
  :expected_status_code => 200
@@ -25,7 +25,7 @@ module CouchModel
25
25
  end
26
26
 
27
27
  def create!
28
- Transport.request :put, url, :expected_status_code => 201
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
- Transport.request :delete, url, :expected_status_code => 200
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
- Transport.request :get, url, :expected_status_code => 200
44
+ ExtendedTransport.request :get, url, :expected_status_code => 200
45
45
  end
46
46
 
47
47
  def exists?
@@ -33,7 +33,9 @@ module CouchModel
33
33
  end
34
34
 
35
35
  def load_file
36
- self.id, self.language, self.views = YAML::load_file(self.filename).values_at(:id, :language, :views)
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
- Transport.request :get, self.url, :expected_status_code => 200
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 Transport.request(:get, url)
78
+ evaluate ExtendedTransport.request(:get, url)
77
79
 
78
- Transport.request :put, url, :body => self.to_hash, :expected_status_code => 201
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
@@ -19,19 +19,19 @@ module CouchModel
19
19
  end
20
20
 
21
21
  def informations
22
- Transport.request :get, url + "/", :expected_status_code => 200
22
+ ExtendedTransport.request :get, url + "/", :expected_status_code => 200
23
23
  end
24
24
 
25
25
  def statistics
26
- Transport.request :get, url + "/_stats", :expected_status_code => 200
26
+ ExtendedTransport.request :get, url + "/_stats", :expected_status_code => 200
27
27
  end
28
28
 
29
29
  def database_names
30
- Transport.request :get, url + "/_all_dbs", :expected_status_code => 200
30
+ ExtendedTransport.request :get, url + "/_all_dbs", :expected_status_code => 200
31
31
  end
32
32
 
33
33
  def uuids(count = 1)
34
- response = Transport.request :get, url + "/_uuids", :expected_status_code => 200, :parameters => { :count => count }
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
- module Transport
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
- # The UnexpectedStatusCodeError is raised if the :expected_status_code option is given to
10
- # the :request method and the responded status code is different from the expected one.
11
- class UnexpectedStatusCodeError < StandardError
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
- attr_reader :status_code
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
- def initialize(status_code)
16
- @status_code = status_code
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
- def to_s
20
- "#{super} received status code #{self.status_code}"
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 self.request(http_method, url, options = { })
26
- expected_status_code = options[:expected_status_code]
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
- uri = URI.parse url
29
- response = perform request_object(http_method, uri, options), uri
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
- check_status_code response, expected_status_code if expected_status_code
32
- parse response
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
- def self.request_object(http_method, uri, options)
36
- raise NotImplementedError, "the request method #{http_method} is not implemented" unless
37
- self.respond_to?(:"#{http_method}_request_object")
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
- def self.get_request_object(path, parameters, headers)
45
- Net::HTTP::Get.new path + serialize_parameters(parameters),
46
- headers
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 self.post_request_object(path, parameters, headers)
50
- Net::HTTP::Post.new path + serialize_parameters(parameters),
51
- { "Content-Type" => "application/json" }.merge(headers)
125
+ def perform
126
+ initialize_headers
127
+ super
128
+ check_status_code
129
+ parse_response
52
130
  end
53
131
 
54
- def self.put_request_object(path, parameters, headers)
55
- Net::HTTP::Put.new path + serialize_parameters(parameters),
56
- { "Content-Type" => "application/json" }.merge(headers)
132
+ private
133
+
134
+ def initialize_headers
135
+ @headers["Accept"] = "application/json"
57
136
  end
58
137
 
59
- def self.delete_request_object(path, parameters, headers)
60
- Net::HTTP::Delete.new path + serialize_parameters(parameters),
61
- headers
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 self.serialize_parameters(parameters)
65
- return "" if parameters.empty?
66
- "?" + parameters.collect do |key, value|
67
- value = value.respond_to?(:to_json) ? value.to_json : value.to_s
68
- "#{key}=#{URI.escape(value)}"
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 self.perform(request, uri)
73
- Net::HTTP.start(uri.host, uri.port) do |connection|
74
- connection.request request
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 self.check_status_code(response, expected_status_code)
79
- response_code = response.code
80
- raise UnexpectedStatusCodeError, response_code.to_i if expected_status_code.to_s != response_code
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 self.parse(response)
84
- JSON.parse response.body
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 CouchModel
3
+ module FakeTransport
4
4
 
5
- module Transport
5
+ def self.enable!
6
+ @enabled = true
7
+ end
8
+
9
+ def self.disable!
10
+ @enabled = false
11
+ end
6
12
 
7
- def self.fake!
8
- @@fake ||= YAML::load_file File.join(File.dirname(__FILE__), "fake_transport.yml")
9
- self.stub!(:request).and_return do |http_method, url, options|
10
- options ||= { }
11
- parameters = options[:parameters]
12
- headers = options[:headers]
13
- expected_status_code = options[:expected_status_code]
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
- request = @@fake.detect do |hash|
16
- hash[:http_method].to_s == http_method.to_s &&
17
- hash[:url].to_s == url.to_s &&
18
- hash[:parameters] == parameters &&
19
- hash[:headers] == headers
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
- User.all.should include(@user_one)
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
- :id: "membership"
2
- :language: "javascript"
3
- :views:
4
- :by_user_id_and_created_at:
5
- :keys: [ "user_id", "created_at" ]
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
- :id: "user"
2
- :language: "javascript"
3
- :views:
4
- :user_count:
5
- :map:
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
- :reduce:
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::Transport.stub!(:request).and_raise(CouchModel::Transport::UnexpectedStatusCodeError.new(404))
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::Transport.stub!(:request).and_raise(CouchModel::Transport::UnexpectedStatusCodeError.new(404))
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::Transport.stub!(:request).and_raise(CouchModel::Transport::UnexpectedStatusCodeError.new(404))
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::Transport.stub!(:request).and_raise(CouchModel::Transport::UnexpectedStatusCodeError.new(500))
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::Transport.should_receive(:request).with(anything, anything,
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::Transport.should_not_receive(:request)
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::Transport.stub!(:request).and_return(@response)
52
+ CouchModel::ExtendedTransport.stub!(:request).and_return(@response)
53
53
  end
54
54
 
55
55
  it "should create the database" do
56
- CouchModel::Transport.should_receive(:request).with(:put, /test$/, anything).and_return(@response)
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::Transport.stub!(:request).and_return(@response)
86
+ CouchModel::ExtendedTransport.stub!(:request).and_return(@response)
87
87
  end
88
88
 
89
89
  it "should delete the database" do
90
- CouchModel::Transport.should_receive(:request).with(:delete, /test$/, anything).and_return(@response)
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
- :id: "test_design"
2
- :language: "javascript"
3
- :views:
4
- "by_related_id_and_name":
5
- :keys: [ "related_id", "name" ]
1
+ id: "test_design"
2
+ language: "javascript"
3
+ views:
4
+ by_related_id_and_name:
5
+ keys: [ "related_id", "name" ]
@@ -1,10 +1,10 @@
1
- :id: "test_design"
2
- :language: "javascript"
3
- :views:
4
- "test_view":
5
- :map:
1
+ id: "test_design"
2
+ language: "javascript"
3
+ views:
4
+ test_view:
5
+ map:
6
6
  function(document) {
7
7
  };
8
- :reduce:
8
+ reduce:
9
9
  function(key, values, rereduce) {
10
10
  };
@@ -1,10 +1,10 @@
1
- :id: "test_design"
2
- :language: "javascript"
3
- :views:
4
- "test_view":
5
- :map:
1
+ id: "test_design"
2
+ language: "javascript"
3
+ views:
4
+ test_view:
5
+ map:
6
6
  function(document) {
7
7
  };
8
- :reduce:
8
+ reduce:
9
9
  function(key, values, rereduce) {
10
10
  };
@@ -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
- describe "request" do
6
+ use_real_transport!
7
7
 
8
- use_real_transport!
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("{\"couchdb\":\"Welcome\",\"version\":\"0.10.0\"}")
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 raise UnexpectedStatusCodeError if an unexpected status id returned" do
37
- lambda do
38
- do_request :expected_status_code => 201
39
- end.should raise_error(CouchModel::Transport::UnexpectedStatusCodeError)
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
- describe "serialize_parameters" do
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
- @parameters = { :test => [ :test, 1, 2, 3 ], :another_test => :test }
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
- it "should return an empty string on empty parameter hash" do
51
- CouchModel::Transport.send(:serialize_parameters, { }).should == ""
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 serialize the given parameters" do
55
- CouchModel::Transport.send(:serialize_parameters, @parameters).should ==
56
- "?another_test=%22test%22&test=[%22test%22,1,2,3]"
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
- CouchModel::Configuration.fake_transport = true
7
+ FakeTransport.enable!
9
8
  Spec::Runner.configure do |configuration|
10
9
  configuration.before :each do
11
- CouchModel::Transport.fake! if CouchModel::Configuration.fake_transport
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
- CouchModel::Configuration.fake_transport = false
18
+ FakeTransport.disable!
20
19
  end
21
20
 
22
21
  after :all do
23
- CouchModel::Configuration.fake_transport = true
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: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
8
  - 0
9
- - beta4
10
- version: 0.1.0.beta4
9
+ version: 0.1.0
11
10
  platform: ruby
12
11
  authors:
13
- - "Philipp Br\xC3\xBCll"
12
+ - Philipp Bruell
14
13
  autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-03-25 00:00:00 +01:00
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
- - --line-numbers
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
- - 1
94
- - 9
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
- - 1
103
- - 3
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