couchmodel 0.1.0.beta3 → 0.1.0.beta4
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 +22 -7
- data/lib/core_extension/array.rb +18 -2
- data/lib/core_extension/string.rb +12 -2
- data/lib/couch_model/active_model.rb +31 -8
- data/lib/couch_model/base/accessor.rb +8 -5
- data/lib/couch_model/base/association.rb +36 -15
- data/lib/couch_model/base/finder.rb +1 -0
- data/lib/couch_model/base/setup.rb +6 -1
- data/lib/couch_model/base.rb +55 -17
- data/lib/couch_model/collection.rb +41 -21
- data/lib/couch_model/configuration.rb +42 -46
- data/lib/couch_model/database.rb +2 -2
- data/lib/couch_model/design.rb +18 -14
- data/lib/couch_model/row.rb +34 -0
- data/lib/couch_model/server.rb +2 -2
- data/lib/couch_model/transport.rb +55 -34
- data/lib/couch_model/view.rb +9 -5
- data/spec/fake_transport.yml +84 -29
- data/spec/fake_transport_helper.rb +5 -3
- data/spec/integration/basic_spec.rb +26 -12
- data/spec/integration/design/membership.design +1 -1
- data/spec/integration/design/user.design +12 -0
- data/spec/lib/core_extension/array_spec.rb +24 -0
- data/spec/lib/couch_model/active_model_spec.rb +51 -0
- data/spec/lib/couch_model/base_spec.rb +30 -1
- data/spec/lib/couch_model/collection_spec.rb +31 -7
- data/spec/lib/couch_model/configuration_spec.rb +2 -2
- data/spec/lib/couch_model/core/accessor_spec.rb +11 -3
- data/spec/lib/couch_model/core/association_spec.rb +26 -0
- data/spec/lib/couch_model/core/setup_spec.rb +8 -0
- data/spec/lib/couch_model/design_spec.rb +1 -5
- data/spec/lib/couch_model/row_spec.rb +71 -0
- data/spec/lib/couch_model/transport_spec.rb +18 -1
- data/spec/lib/couch_model/view_spec.rb +2 -2
- data/spec/spec_helper.rb +1 -1
- metadata +6 -3
@@ -1,70 +1,66 @@
|
|
1
1
|
|
2
2
|
module CouchModel
|
3
3
|
|
4
|
-
|
4
|
+
module Configuration
|
5
5
|
|
6
6
|
CLASS_KEY = "model_class".freeze unless defined?(CLASS_KEY)
|
7
7
|
CLASS_VIEW_NAME = "all".freeze unless defined?(CLASS_VIEW_NAME)
|
8
8
|
|
9
|
-
|
9
|
+
@fake_transport = false
|
10
|
+
@databases = [ ]
|
11
|
+
@designs = [ ]
|
10
12
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
def fake_transport=(value)
|
16
|
-
@@fake_transport = value
|
17
|
-
end
|
13
|
+
def self.fake_transport=(value)
|
14
|
+
@fake_transport = value
|
15
|
+
end
|
18
16
|
|
19
|
-
|
20
|
-
|
21
|
-
|
17
|
+
def self.fake_transport
|
18
|
+
@fake_transport
|
19
|
+
end
|
22
20
|
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
def self.design_directory=(value)
|
22
|
+
@design_directory = value
|
23
|
+
end
|
26
24
|
|
27
|
-
|
28
|
-
|
29
|
-
|
25
|
+
def self.design_directory
|
26
|
+
instance_variable_defined?(:@design_directory) ? @design_directory : ""
|
27
|
+
end
|
30
28
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
end
|
37
|
-
result
|
29
|
+
def self.register_database(database)
|
30
|
+
result = @databases.select{ |element| element == database }.first
|
31
|
+
unless result
|
32
|
+
@databases << database
|
33
|
+
result = database
|
38
34
|
end
|
35
|
+
result
|
36
|
+
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
38
|
+
def self.databases
|
39
|
+
@databases
|
40
|
+
end
|
43
41
|
|
44
|
-
|
45
|
-
|
46
|
-
|
42
|
+
def self.setup_databases(options = { })
|
43
|
+
delete_if_exists = options[:delete_if_exists] || false
|
44
|
+
create_if_missing = options[:create_if_missing] || false
|
47
45
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
46
|
+
@databases.each do |database|
|
47
|
+
database.delete_if_exists! if delete_if_exists
|
48
|
+
database.create_if_missing! if create_if_missing
|
52
49
|
end
|
50
|
+
end
|
53
51
|
|
54
|
-
|
55
|
-
|
56
|
-
|
52
|
+
def self.register_design(design)
|
53
|
+
@designs << design
|
54
|
+
end
|
57
55
|
|
58
|
-
|
59
|
-
|
60
|
-
|
56
|
+
def self.designs
|
57
|
+
@designs
|
58
|
+
end
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
60
|
+
def self.setup_designs
|
61
|
+
@designs.each do |design|
|
62
|
+
design.push
|
66
63
|
end
|
67
|
-
|
68
64
|
end
|
69
65
|
|
70
66
|
end
|
data/lib/couch_model/database.rb
CHANGED
@@ -4,10 +4,10 @@ require File.join(File.dirname(__FILE__), "collection")
|
|
4
4
|
|
5
5
|
module CouchModel
|
6
6
|
|
7
|
+
# The Database class provides methods create, delete and retrieve informations
|
8
|
+
# of a CouchDB database.
|
7
9
|
class Database
|
8
10
|
|
9
|
-
class Error < StandardError; end
|
10
|
-
|
11
11
|
attr_reader :server
|
12
12
|
attr_reader :name
|
13
13
|
|
data/lib/couch_model/design.rb
CHANGED
@@ -6,6 +6,7 @@ require 'yaml'
|
|
6
6
|
|
7
7
|
module CouchModel
|
8
8
|
|
9
|
+
# The Design class acts as a wrapper for CouchDB design documents.
|
9
10
|
class Design
|
10
11
|
|
11
12
|
attr_reader :database
|
@@ -22,9 +23,9 @@ module CouchModel
|
|
22
23
|
@views = [ ]
|
23
24
|
|
24
25
|
load_file
|
25
|
-
self.id = attributes[:id] if attributes
|
26
|
-
self.language = attributes[:language] if attributes
|
27
|
-
self.views = attributes[:views] if attributes
|
26
|
+
self.id = attributes[:id] if attributes.has_key?(:id)
|
27
|
+
self.language = attributes[:language] if attributes.has_key?(:language)
|
28
|
+
self.views = attributes[:views] if attributes.has_key?(:views)
|
28
29
|
end
|
29
30
|
|
30
31
|
def filename
|
@@ -32,34 +33,33 @@ module CouchModel
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def load_file
|
35
|
-
|
36
|
-
attributes = YAML::load_file filename
|
37
|
-
self.id = attributes[:id]
|
38
|
-
self.language = attributes[:language]
|
39
|
-
self.views = attributes[:views]
|
36
|
+
self.id, self.language, self.views = YAML::load_file(self.filename).values_at(:id, :language, :views)
|
40
37
|
true
|
38
|
+
rescue Errno::ENOENT
|
39
|
+
false
|
41
40
|
end
|
42
41
|
|
43
42
|
def views=(view_hash)
|
44
43
|
@views = [ ]
|
45
44
|
view_hash.each do |view_name, view|
|
46
|
-
@views << View.new(self, view.merge(:name => view_name)) if view.is_a?(Hash)
|
45
|
+
@views << View.new(self, view.merge(:name => view_name.to_s)) if view.is_a?(Hash)
|
47
46
|
end if view_hash.is_a?(Hash)
|
48
47
|
end
|
49
48
|
|
50
49
|
def generate_view(name, options = { })
|
51
|
-
view = View.new self, options.merge(:name => name)
|
50
|
+
view = View.new self, options.merge(:name => name.to_s)
|
52
51
|
@views.insert 0, view
|
53
52
|
view
|
54
53
|
end
|
55
54
|
|
56
55
|
def to_hash
|
56
|
+
rev = self.rev
|
57
57
|
hash = {
|
58
58
|
"_id" => "_design/#{self.id}",
|
59
59
|
"language" => self.language,
|
60
60
|
"views" => { }
|
61
61
|
}
|
62
|
-
hash.merge! "_rev" =>
|
62
|
+
hash.merge! "_rev" => rev if rev
|
63
63
|
@views.each { |view| hash["views"].merge! view.to_hash }
|
64
64
|
hash
|
65
65
|
end
|
@@ -72,10 +72,10 @@ module CouchModel
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def push
|
75
|
-
|
76
|
-
|
75
|
+
url = self.url
|
76
|
+
evaluate Transport.request(:get, url)
|
77
77
|
|
78
|
-
Transport.request :put,
|
78
|
+
Transport.request :put, url, :body => self.to_hash, :expected_status_code => 201
|
79
79
|
true
|
80
80
|
end
|
81
81
|
|
@@ -87,6 +87,10 @@ module CouchModel
|
|
87
87
|
|
88
88
|
attr_writer :rev
|
89
89
|
|
90
|
+
def evaluate(response)
|
91
|
+
self.rev = response["_rev"] if response.has_key?("_rev")
|
92
|
+
end
|
93
|
+
|
90
94
|
end
|
91
95
|
|
92
96
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "configuration")
|
2
|
+
|
3
|
+
module CouchModel
|
4
|
+
|
5
|
+
# The Row class acts as a wrapper for a CouchDB view result row.
|
6
|
+
class Row
|
7
|
+
|
8
|
+
attr_reader :id
|
9
|
+
attr_reader :key
|
10
|
+
attr_reader :value
|
11
|
+
attr_reader :document
|
12
|
+
|
13
|
+
def initialize(attributes = { })
|
14
|
+
@id, @key, @value, @document = attributes.values_at "id", "key", "value", "doc"
|
15
|
+
end
|
16
|
+
|
17
|
+
def model
|
18
|
+
return nil unless @document && @document.has_key?(Configuration::CLASS_KEY)
|
19
|
+
|
20
|
+
model_class_name = document[Configuration::CLASS_KEY]
|
21
|
+
raise StandardError, "no class defined with name [#{model_class_name}]" unless Object.const_defined?(model_class_name)
|
22
|
+
instanciate_model model_class_name
|
23
|
+
end
|
24
|
+
|
25
|
+
def instanciate_model(model_class_name)
|
26
|
+
model_class = Object.const_get model_class_name
|
27
|
+
model = model_class.new
|
28
|
+
model.instance_variable_set :@attributes, @document
|
29
|
+
model
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
data/lib/couch_model/server.rb
CHANGED
@@ -2,10 +2,10 @@ require File.join(File.dirname(__FILE__), "transport")
|
|
2
2
|
|
3
3
|
module CouchModel
|
4
4
|
|
5
|
+
# The Server class provides methods to retrieve informations and statistics
|
6
|
+
# of a CouchDB server.
|
5
7
|
class Server
|
6
8
|
|
7
|
-
class Error < StandardError; end
|
8
|
-
|
9
9
|
attr_reader :host
|
10
10
|
attr_reader :port
|
11
11
|
|
@@ -6,8 +6,8 @@ module CouchModel
|
|
6
6
|
|
7
7
|
module Transport
|
8
8
|
|
9
|
-
|
10
|
-
|
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
11
|
class UnexpectedStatusCodeError < StandardError
|
12
12
|
|
13
13
|
attr_reader :status_code
|
@@ -22,47 +22,68 @@ module CouchModel
|
|
22
22
|
|
23
23
|
end
|
24
24
|
|
25
|
-
|
25
|
+
def self.request(http_method, url, options = { })
|
26
|
+
expected_status_code = options[:expected_status_code]
|
26
27
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
uri = URI.parse @base_url ? @base_url + url : url
|
28
|
+
uri = URI.parse url
|
29
|
+
response = perform request_object(http_method, uri, options), uri
|
31
30
|
|
32
|
-
|
33
|
-
|
31
|
+
check_status_code response, expected_status_code if expected_status_code
|
32
|
+
parse response
|
33
|
+
end
|
34
34
|
|
35
|
-
|
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")
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
+
end
|
40
43
|
|
41
|
-
|
44
|
+
def self.get_request_object(path, parameters, headers)
|
45
|
+
Net::HTTP::Get.new path + serialize_parameters(parameters),
|
46
|
+
headers
|
47
|
+
end
|
42
48
|
|
43
|
-
|
44
|
-
|
45
|
-
|
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)
|
52
|
+
end
|
53
|
+
|
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)
|
57
|
+
end
|
46
58
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
59
|
+
def self.delete_request_object(path, parameters, headers)
|
60
|
+
Net::HTTP::Delete.new path + serialize_parameters(parameters),
|
61
|
+
headers
|
62
|
+
end
|
63
|
+
|
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("&")
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.perform(request, uri)
|
73
|
+
Net::HTTP.start(uri.host, uri.port) do |connection|
|
74
|
+
connection.request request
|
62
75
|
end
|
76
|
+
end
|
77
|
+
|
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
|
81
|
+
end
|
63
82
|
|
83
|
+
def self.parse(response)
|
84
|
+
JSON.parse response.body
|
64
85
|
end
|
65
|
-
|
86
|
+
|
66
87
|
end
|
67
88
|
|
68
|
-
end
|
89
|
+
end
|
data/lib/couch_model/view.rb
CHANGED
@@ -3,6 +3,8 @@ require File.join(File.dirname(__FILE__), "collection")
|
|
3
3
|
|
4
4
|
module CouchModel
|
5
5
|
|
6
|
+
# The View class acts as a wrapper for the views that are in the CouchDB design document. It also
|
7
|
+
# provides methods to generate simple view javascript functions.
|
6
8
|
class View
|
7
9
|
|
8
10
|
attr_reader :design
|
@@ -15,8 +17,8 @@ module CouchModel
|
|
15
17
|
@name = attributes[:name]
|
16
18
|
|
17
19
|
generate_functions attributes
|
18
|
-
@map = attributes[:map] if attributes
|
19
|
-
@reduce = attributes[:reduce] if attributes
|
20
|
+
@map = attributes[:map] if attributes.has_key?(:map)
|
21
|
+
@reduce = attributes[:reduce] if attributes.has_key?(:reduce)
|
20
22
|
end
|
21
23
|
|
22
24
|
def collection(options = { })
|
@@ -33,18 +35,20 @@ module CouchModel
|
|
33
35
|
|
34
36
|
def generate_functions(options = { })
|
35
37
|
keys = [ (options[:keys] || "_id") ].flatten
|
38
|
+
@map = self.class.generate_map_function @design.model_class, keys
|
39
|
+
@reduce = nil
|
40
|
+
end
|
36
41
|
|
42
|
+
def self.generate_map_function(model_class, keys)
|
37
43
|
emit_values = keys.map{ |key| "document['#{key}']" }
|
38
44
|
check_values = emit_values.select{ |value| value != "document['_id']" }
|
39
45
|
|
40
|
-
@map =
|
41
46
|
"""function(document) {
|
42
|
-
if (document['#{Configuration::CLASS_KEY}'] == '#{
|
47
|
+
if (document['#{Configuration::CLASS_KEY}'] == '#{model_class.to_s}'#{check_values.empty? ? "" : " && " + check_values.join(" && ")}) {
|
43
48
|
emit(#{emit_values.size == 1 ? emit_values.first : "[ " + emit_values.join(", ") + " ]"}, null);
|
44
49
|
}
|
45
50
|
}
|
46
51
|
"""
|
47
|
-
@reduce = nil
|
48
52
|
end
|
49
53
|
|
50
54
|
end
|
data/spec/fake_transport.yml
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
:url: "http://localhost:5984/"
|
4
4
|
:response:
|
5
5
|
:code: "200"
|
6
|
-
:
|
6
|
+
:body:
|
7
7
|
"couchdb": "Welcome"
|
8
8
|
"version": "0.10.0"
|
9
9
|
-
|
@@ -11,7 +11,7 @@
|
|
11
11
|
:url: "http://localhost:5984/_stats"
|
12
12
|
:response:
|
13
13
|
:code: "200"
|
14
|
-
:
|
14
|
+
:body:
|
15
15
|
"httpd_status_codes": "..."
|
16
16
|
"httpd_request_methods": "..."
|
17
17
|
-
|
@@ -19,7 +19,7 @@
|
|
19
19
|
:url: "http://localhost:5984/_all_dbs"
|
20
20
|
:response:
|
21
21
|
:code: "200"
|
22
|
-
:
|
22
|
+
:body: [ "development", "test" ]
|
23
23
|
-
|
24
24
|
:http_method: "get"
|
25
25
|
:url: "http://localhost:5984/_uuids"
|
@@ -27,14 +27,14 @@
|
|
27
27
|
:count: 3
|
28
28
|
:response:
|
29
29
|
:code: "200"
|
30
|
-
:
|
30
|
+
:body:
|
31
31
|
"uuids": [ "uuid_1", "uuid_2", "uuid_3" ]
|
32
32
|
-
|
33
33
|
:http_method: "get"
|
34
34
|
:url: "http://localhost:5984/test"
|
35
35
|
:response:
|
36
36
|
:code: "200"
|
37
|
-
:
|
37
|
+
:body:
|
38
38
|
"db_name": "test"
|
39
39
|
"doc_count": "0"
|
40
40
|
-
|
@@ -42,13 +42,13 @@
|
|
42
42
|
:url: "http://localhost:5984/new_database"
|
43
43
|
:response:
|
44
44
|
:code: "404"
|
45
|
-
:
|
45
|
+
:body:
|
46
46
|
-
|
47
47
|
:http_method: "get"
|
48
48
|
:url: "http://localhost:5984/test/test_model_1"
|
49
49
|
:response:
|
50
50
|
:code: "200"
|
51
|
-
:
|
51
|
+
:body:
|
52
52
|
"_id": "test_model_1"
|
53
53
|
"_rev": "0"
|
54
54
|
"model_class": "BaseTestModel"
|
@@ -59,7 +59,7 @@
|
|
59
59
|
:url: "http://localhost:5984/test/test_model_2"
|
60
60
|
:response:
|
61
61
|
:code: "200"
|
62
|
-
:
|
62
|
+
:body:
|
63
63
|
"_id": "test_model_2"
|
64
64
|
"_rev": "0"
|
65
65
|
"model_class": "BaseTestModel"
|
@@ -74,7 +74,7 @@
|
|
74
74
|
:url: "http://localhost:5984/test"
|
75
75
|
:response:
|
76
76
|
:code: "201"
|
77
|
-
:
|
77
|
+
:body:
|
78
78
|
"ok": true
|
79
79
|
"id": "test_model_2"
|
80
80
|
"rev": "0"
|
@@ -83,18 +83,18 @@
|
|
83
83
|
:url: "http://localhost:5984/test/test_model_1"
|
84
84
|
:response:
|
85
85
|
:code: "201"
|
86
|
-
:
|
86
|
+
:body:
|
87
87
|
"ok": true
|
88
88
|
"id": "test_model_1"
|
89
89
|
"rev": "1"
|
90
90
|
-
|
91
91
|
:http_method: "delete"
|
92
92
|
:url: "http://localhost:5984/test/test_model_1"
|
93
|
-
:
|
94
|
-
"
|
93
|
+
:headers:
|
94
|
+
"If-Match": "0"
|
95
95
|
:response:
|
96
96
|
:code: "200"
|
97
|
-
:
|
97
|
+
:body:
|
98
98
|
"ok": true
|
99
99
|
"id": "test_model_1"
|
100
100
|
"rev": "1"
|
@@ -103,7 +103,7 @@
|
|
103
103
|
:url: "http://localhost:5984/test/_design/test_design"
|
104
104
|
:response:
|
105
105
|
:code: "200"
|
106
|
-
:
|
106
|
+
:body:
|
107
107
|
"_id": "_design/test_design"
|
108
108
|
"_rev": "0"
|
109
109
|
"language": "javascript"
|
@@ -116,7 +116,7 @@
|
|
116
116
|
:url: "http://localhost:5984/test/_design/test_design"
|
117
117
|
:response:
|
118
118
|
:code: "201"
|
119
|
-
:
|
119
|
+
:body:
|
120
120
|
"ok": true
|
121
121
|
"id": "_design/test_design"
|
122
122
|
"rev": "1"
|
@@ -124,11 +124,11 @@
|
|
124
124
|
:http_method: "get"
|
125
125
|
:url: "http://localhost:5984/test/_all_docs"
|
126
126
|
:parameters:
|
127
|
-
|
128
|
-
|
127
|
+
:include_docs: true
|
128
|
+
:limit: 1
|
129
129
|
:response:
|
130
130
|
:code: "200"
|
131
|
-
:
|
131
|
+
:body:
|
132
132
|
"total_rows": 1
|
133
133
|
"offset": 0
|
134
134
|
"rows":
|
@@ -146,24 +146,80 @@
|
|
146
146
|
:http_method: "get"
|
147
147
|
:url: "http://localhost:5984/test/_all_docs"
|
148
148
|
:parameters:
|
149
|
-
|
150
|
-
"limit": "0"
|
149
|
+
:limit: 1
|
151
150
|
:response:
|
152
151
|
:code: "200"
|
153
|
-
:
|
152
|
+
:body:
|
154
153
|
"total_rows": 1
|
155
154
|
"offset": 0
|
155
|
+
"rows":
|
156
|
+
-
|
157
|
+
"id": "test_model_1"
|
158
|
+
"key": "test_model_1"
|
159
|
+
"value":
|
160
|
+
"rev": "0"
|
161
|
+
"doc":
|
162
|
+
"_id": "test_model_1"
|
163
|
+
"_rev": "0"
|
164
|
+
"model_class": "CollectionTestModel"
|
165
|
+
"name": "phil"
|
166
|
+
-
|
167
|
+
:http_method: "get"
|
168
|
+
:url: "http://localhost:5984/test/_all_docs"
|
169
|
+
:parameters:
|
170
|
+
:include_docs: true
|
171
|
+
:limit: 0
|
172
|
+
:response:
|
173
|
+
:code: "200"
|
174
|
+
:body:
|
175
|
+
"total_rows": 1
|
176
|
+
"offset": 0
|
177
|
+
"rows": [ ]
|
178
|
+
-
|
179
|
+
:http_method: "get"
|
180
|
+
:url: "http://localhost:5984/test/_design/setup_test_model/_view/all"
|
181
|
+
:parameters:
|
182
|
+
:include_docs: true
|
183
|
+
:limit: 0
|
184
|
+
:response:
|
185
|
+
:code: "200"
|
186
|
+
:body:
|
187
|
+
"total_rows": 14
|
188
|
+
"offset": 0
|
156
189
|
"rows": [ ]
|
157
190
|
-
|
158
191
|
:http_method: "get"
|
159
192
|
:url: "http://localhost:5984/test/_design/association_test_model_one/_view/by_related_id_and_name"
|
160
193
|
:parameters:
|
161
|
-
|
162
|
-
|
163
|
-
|
194
|
+
:include_docs: true
|
195
|
+
:startkey: [ "test_model_2", null ]
|
196
|
+
:endkey: [ "test_model_2", { } ]
|
197
|
+
:response:
|
198
|
+
:code: "200"
|
199
|
+
:body:
|
200
|
+
"total_rows": 1
|
201
|
+
"offset": 0
|
202
|
+
"rows":
|
203
|
+
-
|
204
|
+
"id": "test_model_1"
|
205
|
+
"key": "test_model_2"
|
206
|
+
"value":
|
207
|
+
"rev": "0"
|
208
|
+
"doc":
|
209
|
+
"_id": "test_model_1"
|
210
|
+
"_rev": "0"
|
211
|
+
"model_class": "AssociationTestModelOne"
|
212
|
+
"name": "phil"
|
213
|
+
-
|
214
|
+
:http_method: "get"
|
215
|
+
:url: "http://localhost:5984/test/_design/association_test_model_one/_view/by_related_id_and_name"
|
216
|
+
:parameters:
|
217
|
+
:include_docs: true
|
218
|
+
:startkey: [ "test_model_2", "phil" ]
|
219
|
+
:endkey: [ "test_model_2", "phil" ]
|
164
220
|
:response:
|
165
221
|
:code: "200"
|
166
|
-
:
|
222
|
+
:body:
|
167
223
|
"total_rows": 1
|
168
224
|
"offset": 0
|
169
225
|
"rows":
|
@@ -181,12 +237,11 @@
|
|
181
237
|
:http_method: "get"
|
182
238
|
:url: "http://localhost:5984/test/_design/association_test_model_one/_view/by_related_id_and_name"
|
183
239
|
:parameters:
|
184
|
-
"
|
185
|
-
|
186
|
-
"endkey": "[\"test_model_2\",\"phil\"]"
|
240
|
+
:startkey: [ "test_model_2", "phil" ]
|
241
|
+
:endkey: [ "test_model_2", "phil" ]
|
187
242
|
:response:
|
188
243
|
:code: "200"
|
189
|
-
:
|
244
|
+
:body:
|
190
245
|
"total_rows": 1
|
191
246
|
"offset": 0
|
192
247
|
"rows":
|
@@ -9,16 +9,18 @@ module CouchModel
|
|
9
9
|
self.stub!(:request).and_return do |http_method, url, options|
|
10
10
|
options ||= { }
|
11
11
|
parameters = options[:parameters]
|
12
|
+
headers = options[:headers]
|
12
13
|
expected_status_code = options[:expected_status_code]
|
13
14
|
|
14
15
|
request = @@fake.detect do |hash|
|
15
16
|
hash[:http_method].to_s == http_method.to_s &&
|
16
17
|
hash[:url].to_s == url.to_s &&
|
17
|
-
hash[:parameters] == parameters
|
18
|
+
hash[:parameters] == parameters &&
|
19
|
+
hash[:headers] == headers
|
18
20
|
end
|
19
|
-
raise StandardError, "no fake request found for [#{http_method} #{url} #{parameters.inspect}]" unless request
|
21
|
+
raise StandardError, "no fake request found for [#{http_method} #{url} #{parameters.inspect} #{headers.inspect}]" unless request
|
20
22
|
raise UnexpectedStatusCodeError, request[:response][:code].to_i if expected_status_code && expected_status_code.to_s != request[:response][:code]
|
21
|
-
request[:response][:
|
23
|
+
request[:response][:body].dup
|
22
24
|
end
|
23
25
|
end
|
24
26
|
|