couchmodel 0.1.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README.rdoc +156 -0
- data/Rakefile +20 -0
- data/lib/core_extension/array.rb +14 -0
- data/lib/core_extension/string.rb +12 -0
- data/lib/couch_model/active_model.rb +86 -0
- data/lib/couch_model/base/accessor.rb +39 -0
- data/lib/couch_model/base/association.rb +63 -0
- data/lib/couch_model/base/finder.rb +28 -0
- data/lib/couch_model/base/setup.rb +88 -0
- data/lib/couch_model/base.rb +117 -0
- data/lib/couch_model/collection.rb +84 -0
- data/lib/couch_model/configuration.rb +68 -0
- data/lib/couch_model/database.rb +64 -0
- data/lib/couch_model/design.rb +92 -0
- data/lib/couch_model/server.rb +44 -0
- data/lib/couch_model/transport.rb +68 -0
- data/lib/couch_model/view.rb +52 -0
- data/lib/couch_model.rb +15 -0
- data/spec/fake_transport.yml +202 -0
- data/spec/fake_transport_helper.rb +27 -0
- data/spec/integration/basic_spec.rb +125 -0
- data/spec/integration/design/membership.design +5 -0
- data/spec/integration/design/user.design +2 -0
- data/spec/lib/core_extension/array_spec.rb +24 -0
- data/spec/lib/core_extension/string_spec.rb +22 -0
- data/spec/lib/couch_model/active_model_spec.rb +228 -0
- data/spec/lib/couch_model/base_spec.rb +169 -0
- data/spec/lib/couch_model/collection_spec.rb +100 -0
- data/spec/lib/couch_model/configuration_spec.rb +117 -0
- data/spec/lib/couch_model/core/accessor_spec.rb +59 -0
- data/spec/lib/couch_model/core/association_spec.rb +114 -0
- data/spec/lib/couch_model/core/finder_spec.rb +24 -0
- data/spec/lib/couch_model/core/setup_spec.rb +88 -0
- data/spec/lib/couch_model/database_spec.rb +165 -0
- data/spec/lib/couch_model/design/association_test_model_one.design +5 -0
- data/spec/lib/couch_model/design/base_test_model.design +10 -0
- data/spec/lib/couch_model/design/setup_test_model.design +10 -0
- data/spec/lib/couch_model/design_spec.rb +144 -0
- data/spec/lib/couch_model/server_spec.rb +64 -0
- data/spec/lib/couch_model/transport_spec.rb +44 -0
- data/spec/lib/couch_model/view_spec.rb +166 -0
- data/spec/lib/couch_model_spec.rb +3 -0
- data/spec/spec_helper.rb +27 -0
- metadata +128 -0
@@ -0,0 +1,84 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "configuration")
|
2
|
+
require File.join(File.dirname(__FILE__), "transport")
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module CouchModel
|
6
|
+
|
7
|
+
class Collection
|
8
|
+
|
9
|
+
REQUEST_PARAMETER_KEYS = [
|
10
|
+
:key, :startkey, :startkey_docid, :endkey, :endkey_docid,
|
11
|
+
:limit, :stale, :descending, :skip, :group, :group_level,
|
12
|
+
:reduce, :inclusive_end
|
13
|
+
].freeze unless defined?(REQUEST_PARAMETER_KEYS)
|
14
|
+
|
15
|
+
ARRAY_METHOD_NAMES = [
|
16
|
+
:[], :at, :collect, :compact, :count, :cycle, :each, :each_index,
|
17
|
+
:empty?, :fetch, :index, :first, :flatten, :include?, :join, :last,
|
18
|
+
:length, :map, :pack, :reject, :reverse, :reverse_each, :rindex,
|
19
|
+
:sample, :shuffle, :size, :slice, :sort, :take, :to_a, :to_ary,
|
20
|
+
:values_at, :zip
|
21
|
+
].freeze unless defined?(ARRAY_METHOD_NAMES)
|
22
|
+
|
23
|
+
attr_reader :url
|
24
|
+
attr_reader :options
|
25
|
+
|
26
|
+
def initialize(url, options = { })
|
27
|
+
@url, @options = url, options
|
28
|
+
end
|
29
|
+
|
30
|
+
def total_count
|
31
|
+
fetch :meta => true unless @total_count
|
32
|
+
@total_count
|
33
|
+
end
|
34
|
+
|
35
|
+
def respond_to?(method_name)
|
36
|
+
ARRAY_METHOD_NAMES.include?(method_name) || super
|
37
|
+
end
|
38
|
+
|
39
|
+
def method_missing(method_name, *arguments, &block)
|
40
|
+
if ARRAY_METHOD_NAMES.include?(method_name)
|
41
|
+
fetch
|
42
|
+
@entries.send method_name, *arguments, &block
|
43
|
+
else
|
44
|
+
super
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def fetch(options = { })
|
51
|
+
meta = options[:meta] || false
|
52
|
+
|
53
|
+
evaluate Transport.request(
|
54
|
+
:get, url,
|
55
|
+
:parameters => request_parameters.merge(meta ? { "limit" => "0" } : { }),
|
56
|
+
:expected_status_code => 200
|
57
|
+
)
|
58
|
+
|
59
|
+
true
|
60
|
+
end
|
61
|
+
|
62
|
+
def evaluate(response)
|
63
|
+
@total_count = response["total_rows"]
|
64
|
+
@entries = response["rows"].select do |row|
|
65
|
+
row["doc"].has_key?(Configuration::CLASS_KEY) && Object.const_defined?(row["doc"][Configuration::CLASS_KEY])
|
66
|
+
end.map do |row|
|
67
|
+
model_class = Object.const_get row["doc"][Configuration::CLASS_KEY]
|
68
|
+
model = model_class.new
|
69
|
+
model.instance_variable_set :@attributes, row["doc"]
|
70
|
+
model
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def request_parameters
|
75
|
+
parameters = { "include_docs" => "true" }
|
76
|
+
REQUEST_PARAMETER_KEYS.each do |key|
|
77
|
+
parameters[ key.to_s ] = @options[key].is_a?(Array) ? JSON.dump(@options[key]) : @options[key].to_s if @options[key]
|
78
|
+
end
|
79
|
+
parameters
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
|
2
|
+
module CouchModel
|
3
|
+
|
4
|
+
class Configuration
|
5
|
+
|
6
|
+
CLASS_KEY = "model_class".freeze unless defined?(CLASS_KEY)
|
7
|
+
CLASS_VIEW_NAME = "all".freeze unless defined?(CLASS_VIEW_NAME)
|
8
|
+
|
9
|
+
class << self
|
10
|
+
|
11
|
+
@@fake_transport = false
|
12
|
+
@@databases = [ ]
|
13
|
+
@@designs = [ ]
|
14
|
+
|
15
|
+
def fake_transport=(value)
|
16
|
+
@@fake_transport = value
|
17
|
+
end
|
18
|
+
|
19
|
+
def fake_transport
|
20
|
+
@@fake_transport
|
21
|
+
end
|
22
|
+
|
23
|
+
def design_directory=(value)
|
24
|
+
@@design_directory = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def design_directory
|
28
|
+
class_variable_defined?(:@@design_directory) ? @@design_directory : ""
|
29
|
+
end
|
30
|
+
|
31
|
+
def register_database(database)
|
32
|
+
result = @@databases.select{ |element| element == database }.first
|
33
|
+
unless result
|
34
|
+
@@databases << database
|
35
|
+
result = database
|
36
|
+
end
|
37
|
+
result
|
38
|
+
end
|
39
|
+
|
40
|
+
def databases
|
41
|
+
@@databases
|
42
|
+
end
|
43
|
+
|
44
|
+
def setup_databases(options = { })
|
45
|
+
@@databases.each do |database|
|
46
|
+
database.setup! options
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def register_design(design)
|
51
|
+
@@designs << design
|
52
|
+
end
|
53
|
+
|
54
|
+
def designs
|
55
|
+
@@designs
|
56
|
+
end
|
57
|
+
|
58
|
+
def setup_designs
|
59
|
+
@@designs.each do |design|
|
60
|
+
design.push
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "transport")
|
2
|
+
require File.join(File.dirname(__FILE__), "server")
|
3
|
+
require File.join(File.dirname(__FILE__), "collection")
|
4
|
+
|
5
|
+
module CouchModel
|
6
|
+
|
7
|
+
class Database
|
8
|
+
|
9
|
+
class Error < StandardError; end
|
10
|
+
|
11
|
+
attr_reader :server
|
12
|
+
attr_reader :name
|
13
|
+
|
14
|
+
def initialize(options = { })
|
15
|
+
@name = options[:name] || raise(ArgumentError, "no database was given")
|
16
|
+
@server = options[:server] || Server.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def ==(other)
|
20
|
+
other.is_a?(self.class) && @name == other.name && @server == other.server
|
21
|
+
end
|
22
|
+
|
23
|
+
def ===(other)
|
24
|
+
object_id == other.object_id
|
25
|
+
end
|
26
|
+
|
27
|
+
def create!
|
28
|
+
Transport.request :put, url, :expected_status_code => 201
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete!
|
32
|
+
Transport.request :delete, url, :expected_status_code => 200
|
33
|
+
end
|
34
|
+
|
35
|
+
def setup!(options = { })
|
36
|
+
delete_if_exists = options[:delete_if_exists] || false
|
37
|
+
|
38
|
+
if delete_if_exists
|
39
|
+
delete! if exists?
|
40
|
+
create!
|
41
|
+
else
|
42
|
+
create! unless exists?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def informations
|
47
|
+
Transport.request :get, url, :expected_status_code => 200
|
48
|
+
end
|
49
|
+
|
50
|
+
def exists?
|
51
|
+
@server.database_names.include? @name
|
52
|
+
end
|
53
|
+
|
54
|
+
def url
|
55
|
+
"#{@server.url}/#{@name}"
|
56
|
+
end
|
57
|
+
|
58
|
+
def documents(options = { })
|
59
|
+
Collection.new url + "/_all_docs", options
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "configuration")
|
2
|
+
require File.join(File.dirname(__FILE__), "transport")
|
3
|
+
require File.join(File.dirname(__FILE__), "base")
|
4
|
+
require File.join(File.dirname(__FILE__), "view")
|
5
|
+
require 'yaml'
|
6
|
+
|
7
|
+
module CouchModel
|
8
|
+
|
9
|
+
class Design
|
10
|
+
|
11
|
+
attr_reader :database
|
12
|
+
attr_reader :model_class
|
13
|
+
attr_accessor :id
|
14
|
+
attr_reader :rev
|
15
|
+
attr_accessor :language
|
16
|
+
attr_reader :views
|
17
|
+
|
18
|
+
def initialize(database, model_class, attributes = { })
|
19
|
+
@database = database
|
20
|
+
@model_class = model_class
|
21
|
+
@language = "javascript"
|
22
|
+
@views = [ ]
|
23
|
+
|
24
|
+
load_file
|
25
|
+
self.id = attributes[:id] if attributes[:id]
|
26
|
+
self.language = attributes[:language] if attributes[:language]
|
27
|
+
self.views = attributes[:views] if attributes[:views]
|
28
|
+
end
|
29
|
+
|
30
|
+
def filename
|
31
|
+
@filename ||= File.join(CouchModel::Configuration.design_directory, "#{model_class.to_s.underscore}.design")
|
32
|
+
end
|
33
|
+
|
34
|
+
def load_file
|
35
|
+
return false unless File.exists?(filename)
|
36
|
+
attributes = YAML::load_file filename
|
37
|
+
self.id = attributes[:id]
|
38
|
+
self.language = attributes[:language]
|
39
|
+
self.views = attributes[:views]
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def views=(view_hash)
|
44
|
+
@views = [ ]
|
45
|
+
view_hash.each do |view_name, view|
|
46
|
+
@views << View.new(self, view.merge(:name => view_name)) if view.is_a?(Hash)
|
47
|
+
end if view_hash.is_a?(Hash)
|
48
|
+
end
|
49
|
+
|
50
|
+
def generate_view(name, options = { })
|
51
|
+
view = View.new self, options.merge(:name => name)
|
52
|
+
@views.insert 0, view
|
53
|
+
view
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_hash
|
57
|
+
hash = {
|
58
|
+
"_id" => "_design/#{self.id}",
|
59
|
+
"language" => self.language,
|
60
|
+
"views" => { }
|
61
|
+
}
|
62
|
+
hash.merge! "_rev" => self.rev if self.rev
|
63
|
+
@views.each { |view| hash["views"].merge! view.to_hash }
|
64
|
+
hash
|
65
|
+
end
|
66
|
+
|
67
|
+
def exists?
|
68
|
+
Transport.request :get, self.url, :expected_status_code => 200
|
69
|
+
true
|
70
|
+
rescue Transport::UnexpectedStatusCodeError
|
71
|
+
false
|
72
|
+
end
|
73
|
+
|
74
|
+
def push
|
75
|
+
response = Transport.request :get, self.url
|
76
|
+
self.rev = response["_rev"] if response["_rev"]
|
77
|
+
|
78
|
+
Transport.request :put, self.url, :json => self.to_hash, :expected_status_code => 201
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
def url
|
83
|
+
"#{@database.url}/_design/#{self.id}"
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
attr_writer :rev
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "transport")
|
2
|
+
|
3
|
+
module CouchModel
|
4
|
+
|
5
|
+
class Server
|
6
|
+
|
7
|
+
class Error < StandardError; end
|
8
|
+
|
9
|
+
attr_reader :host
|
10
|
+
attr_reader :port
|
11
|
+
|
12
|
+
def initialize(options = { })
|
13
|
+
@host = options[:host] || "localhost"
|
14
|
+
@port = options[:port] || "5984"
|
15
|
+
end
|
16
|
+
|
17
|
+
def ==(other)
|
18
|
+
other.is_a?(self.class) && @host == other.host && @port == other.port
|
19
|
+
end
|
20
|
+
|
21
|
+
def informations
|
22
|
+
Transport.request :get, url + "/", :expected_status_code => 200
|
23
|
+
end
|
24
|
+
|
25
|
+
def statistics
|
26
|
+
Transport.request :get, url + "/_stats", :expected_status_code => 200
|
27
|
+
end
|
28
|
+
|
29
|
+
def database_names
|
30
|
+
Transport.request :get, url + "/_all_dbs", :expected_status_code => 200
|
31
|
+
end
|
32
|
+
|
33
|
+
def uuids(count = 1)
|
34
|
+
response = Transport.request :get, url + "/_uuids", :expected_status_code => 200, :parameters => { :count => count }
|
35
|
+
response["uuids"]
|
36
|
+
end
|
37
|
+
|
38
|
+
def url
|
39
|
+
"http://#{@host}:#{@port}"
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module CouchModel
|
6
|
+
|
7
|
+
module Transport
|
8
|
+
|
9
|
+
class Error < StandardError; end
|
10
|
+
|
11
|
+
class UnexpectedStatusCodeError < StandardError
|
12
|
+
|
13
|
+
attr_reader :status_code
|
14
|
+
|
15
|
+
def initialize(status_code)
|
16
|
+
@status_code = status_code
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{super} received status code #{self.status_code}"
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class << self
|
26
|
+
|
27
|
+
def request(http_method, url, options = { })
|
28
|
+
expected_status_code = options[:expected_status_code]
|
29
|
+
|
30
|
+
uri = URI.parse @base_url ? @base_url + url : url
|
31
|
+
|
32
|
+
request_class = request_class http_method
|
33
|
+
request = request_object request_class, uri, options
|
34
|
+
|
35
|
+
response = Net::HTTP.start(uri.host, uri.port) { |connection| connection.request request }
|
36
|
+
|
37
|
+
raise UnexpectedStatusCodeError, response.code.to_i if expected_status_code && expected_status_code.to_s != response.code
|
38
|
+
JSON.parse response.body
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def request_class(http_method)
|
44
|
+
Net::HTTP.const_get http_method.capitalize
|
45
|
+
end
|
46
|
+
|
47
|
+
def request_object(request_class, uri, options)
|
48
|
+
parameters = options[:parameters] || { }
|
49
|
+
json = options[:json]
|
50
|
+
|
51
|
+
case request_class.to_s
|
52
|
+
when "Net::HTTP::Get"
|
53
|
+
request_class.new uri.path +
|
54
|
+
(parameters.empty? ? "" : "?" + parameters.collect{ |key, value| "#{key}=#{URI.escape(value.to_s)}" }.reverse.join("&"))
|
55
|
+
when "Net::HTTP::Post", "Net::HTTP::Put"
|
56
|
+
request = request_class.new uri.path, { "Content-Type" => "application/json" }
|
57
|
+
request.body = JSON.dump(json) if json
|
58
|
+
request
|
59
|
+
else
|
60
|
+
request_class.new uri.path
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "configuration")
|
2
|
+
require File.join(File.dirname(__FILE__), "collection")
|
3
|
+
|
4
|
+
module CouchModel
|
5
|
+
|
6
|
+
class View
|
7
|
+
|
8
|
+
attr_reader :design
|
9
|
+
attr_accessor :name
|
10
|
+
attr_accessor :map
|
11
|
+
attr_accessor :reduce
|
12
|
+
|
13
|
+
def initialize(design, attributes = { })
|
14
|
+
@design = design
|
15
|
+
@name = attributes[:name]
|
16
|
+
|
17
|
+
generate_functions attributes
|
18
|
+
@map = attributes[:map] if attributes[:map]
|
19
|
+
@reduce = attributes[:reduce] if attributes[:reduce]
|
20
|
+
end
|
21
|
+
|
22
|
+
def collection(options = { })
|
23
|
+
Collection.new url, options
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_hash
|
27
|
+
{ self.name => { "map" => self.map, "reduce" => self.reduce } }
|
28
|
+
end
|
29
|
+
|
30
|
+
def url
|
31
|
+
"#{@design.url}/_view/#{@name}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def generate_functions(options = { })
|
35
|
+
keys = [ (options[:keys] || "_id") ].flatten
|
36
|
+
|
37
|
+
emit_values = keys.map{ |key| "document['#{key}']" }
|
38
|
+
check_values = emit_values.select{ |value| value != "document['_id']" }
|
39
|
+
|
40
|
+
@map =
|
41
|
+
"""function(document) {
|
42
|
+
if (document['#{Configuration::CLASS_KEY}'] == '#{@design.model_class.to_s}'#{check_values.empty? ? "" : " && " + check_values.join(" && ")}) {
|
43
|
+
emit(#{emit_values.size == 1 ? emit_values.first : "[ " + emit_values.join(", ") + " ]"}, null);
|
44
|
+
}
|
45
|
+
}
|
46
|
+
"""
|
47
|
+
@reduce = nil
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/couch_model.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
|
3
|
+
require File.join(File.dirname(__FILE__), "couch_model", "configuration")
|
4
|
+
require File.join(File.dirname(__FILE__), "couch_model", "base")
|
5
|
+
|
6
|
+
begin
|
7
|
+
gem 'activemodel'
|
8
|
+
require 'active_model'
|
9
|
+
|
10
|
+
require File.join(File.dirname(__FILE__), "couch_model", "active_model")
|
11
|
+
|
12
|
+
# ActiveModel support is activated
|
13
|
+
rescue Gem::LoadError
|
14
|
+
# ActiveModel support is deactivated
|
15
|
+
end
|
@@ -0,0 +1,202 @@
|
|
1
|
+
-
|
2
|
+
:http_method: "get"
|
3
|
+
:url: "http://localhost:5984/"
|
4
|
+
:response:
|
5
|
+
:code: "200"
|
6
|
+
:json:
|
7
|
+
"couchdb": "Welcome"
|
8
|
+
"version": "0.10.0"
|
9
|
+
-
|
10
|
+
:http_method: "get"
|
11
|
+
:url: "http://localhost:5984/_stats"
|
12
|
+
:response:
|
13
|
+
:code: "200"
|
14
|
+
:json:
|
15
|
+
"httpd_status_codes": "..."
|
16
|
+
"httpd_request_methods": "..."
|
17
|
+
-
|
18
|
+
:http_method: "get"
|
19
|
+
:url: "http://localhost:5984/_all_dbs"
|
20
|
+
:response:
|
21
|
+
:code: "200"
|
22
|
+
:json: [ "development", "test" ]
|
23
|
+
-
|
24
|
+
:http_method: "get"
|
25
|
+
:url: "http://localhost:5984/_uuids"
|
26
|
+
:parameters:
|
27
|
+
:count: 3
|
28
|
+
:response:
|
29
|
+
:code: "200"
|
30
|
+
:json:
|
31
|
+
"uuids": [ "uuid_1", "uuid_2", "uuid_3" ]
|
32
|
+
-
|
33
|
+
:http_method: "get"
|
34
|
+
:url: "http://localhost:5984/test"
|
35
|
+
:response:
|
36
|
+
:code: "200"
|
37
|
+
:json:
|
38
|
+
"db_name": "test"
|
39
|
+
"doc_count": "0"
|
40
|
+
-
|
41
|
+
:http_method: "get"
|
42
|
+
:url: "http://localhost:5984/new_database"
|
43
|
+
:response:
|
44
|
+
:code: "404"
|
45
|
+
:json:
|
46
|
+
-
|
47
|
+
:http_method: "get"
|
48
|
+
:url: "http://localhost:5984/test/test_model_1"
|
49
|
+
:response:
|
50
|
+
:code: "200"
|
51
|
+
:json:
|
52
|
+
"_id": "test_model_1"
|
53
|
+
"_rev": "0"
|
54
|
+
"model_class": "BaseTestModel"
|
55
|
+
"name": "phil"
|
56
|
+
"related_id": "test_model_2"
|
57
|
+
-
|
58
|
+
:http_method: "get"
|
59
|
+
:url: "http://localhost:5984/test/test_model_2"
|
60
|
+
:response:
|
61
|
+
:code: "200"
|
62
|
+
:json:
|
63
|
+
"_id": "test_model_2"
|
64
|
+
"_rev": "0"
|
65
|
+
"model_class": "BaseTestModel"
|
66
|
+
"name": "keppla"
|
67
|
+
-
|
68
|
+
:http_method: "get"
|
69
|
+
:url: "http://localhost:5984/test/invalid"
|
70
|
+
:response:
|
71
|
+
:code: "404"
|
72
|
+
-
|
73
|
+
:http_method: "post"
|
74
|
+
:url: "http://localhost:5984/test"
|
75
|
+
:response:
|
76
|
+
:code: "201"
|
77
|
+
:json:
|
78
|
+
"ok": true
|
79
|
+
"id": "test_model_2"
|
80
|
+
"rev": "0"
|
81
|
+
-
|
82
|
+
:http_method: "put"
|
83
|
+
:url: "http://localhost:5984/test/test_model_1"
|
84
|
+
:response:
|
85
|
+
:code: "200"
|
86
|
+
:json:
|
87
|
+
"ok": true
|
88
|
+
"id": "test_model_1"
|
89
|
+
"rev": "1"
|
90
|
+
-
|
91
|
+
:http_method: "delete"
|
92
|
+
:url: "http://localhost:5984/test/test_model_1"
|
93
|
+
:parameters:
|
94
|
+
"rev": "0"
|
95
|
+
:response:
|
96
|
+
:code: "200"
|
97
|
+
:json:
|
98
|
+
"ok": true
|
99
|
+
"id": "test_model_1"
|
100
|
+
"rev": "1"
|
101
|
+
-
|
102
|
+
:http_method: "get"
|
103
|
+
:url: "http://localhost:5984/test/_design/test_design"
|
104
|
+
:response:
|
105
|
+
:code: "200"
|
106
|
+
:json:
|
107
|
+
"_id": "_design/test_design"
|
108
|
+
"_rev": "0"
|
109
|
+
"language": "javascript"
|
110
|
+
"views":
|
111
|
+
"test_view":
|
112
|
+
"map": "function(document) { };"
|
113
|
+
"reduce": "function(key, values, rereduce) { };"
|
114
|
+
-
|
115
|
+
:http_method: "put"
|
116
|
+
:url: "http://localhost:5984/test/_design/test_design"
|
117
|
+
:response:
|
118
|
+
:code: "201"
|
119
|
+
:json:
|
120
|
+
"ok": true
|
121
|
+
"id": "_design/test_design"
|
122
|
+
"rev": "1"
|
123
|
+
-
|
124
|
+
:http_method: "get"
|
125
|
+
:url: "http://localhost:5984/test/_all_docs"
|
126
|
+
:parameters:
|
127
|
+
"include_docs": "true"
|
128
|
+
"limit": "1"
|
129
|
+
:response:
|
130
|
+
:code: "200"
|
131
|
+
:json:
|
132
|
+
"total_rows": 1
|
133
|
+
"offset": 0
|
134
|
+
"rows":
|
135
|
+
-
|
136
|
+
"id": "test_model_1"
|
137
|
+
"key": "test_model_1"
|
138
|
+
"value":
|
139
|
+
"rev": "0"
|
140
|
+
"doc":
|
141
|
+
"_id": "test_model_1"
|
142
|
+
"_rev": "0"
|
143
|
+
"model_class": "CollectionTestModel"
|
144
|
+
"name": "phil"
|
145
|
+
-
|
146
|
+
:http_method: "get"
|
147
|
+
:url: "http://localhost:5984/test/_all_docs"
|
148
|
+
:parameters:
|
149
|
+
"include_docs": "true"
|
150
|
+
"limit": "0"
|
151
|
+
:response:
|
152
|
+
:code: "200"
|
153
|
+
:json:
|
154
|
+
"total_rows": 1
|
155
|
+
"offset": 0
|
156
|
+
"rows": [ ]
|
157
|
+
-
|
158
|
+
:http_method: "get"
|
159
|
+
:url: "http://localhost:5984/test/_design/association_test_model_one/_view/by_related_id_and_name"
|
160
|
+
:parameters:
|
161
|
+
"include_docs": "true"
|
162
|
+
"startkey": "[\"test_model_2\",null]"
|
163
|
+
"endkey": "[\"test_model_2\",{}]"
|
164
|
+
:response:
|
165
|
+
:code: "200"
|
166
|
+
:json:
|
167
|
+
"total_rows": 1
|
168
|
+
"offset": 0
|
169
|
+
"rows":
|
170
|
+
-
|
171
|
+
"id": "test_model_1"
|
172
|
+
"key": "test_model_2"
|
173
|
+
"value":
|
174
|
+
"rev": "0"
|
175
|
+
"doc":
|
176
|
+
"_id": "test_model_1"
|
177
|
+
"_rev": "0"
|
178
|
+
"model_class": "AssociationTestModelOne"
|
179
|
+
"name": "phil"
|
180
|
+
-
|
181
|
+
:http_method: "get"
|
182
|
+
:url: "http://localhost:5984/test/_design/association_test_model_one/_view/by_related_id_and_name"
|
183
|
+
:parameters:
|
184
|
+
"include_docs": "true"
|
185
|
+
"startkey": "[\"test_model_2\",\"phil\"]"
|
186
|
+
"endkey": "[\"test_model_2\",\"phil\"]"
|
187
|
+
:response:
|
188
|
+
:code: "200"
|
189
|
+
:json:
|
190
|
+
"total_rows": 1
|
191
|
+
"offset": 0
|
192
|
+
"rows":
|
193
|
+
-
|
194
|
+
"id": "test_model_1"
|
195
|
+
"key": "test_model_2"
|
196
|
+
"value":
|
197
|
+
"rev": "0"
|
198
|
+
"doc":
|
199
|
+
"_id": "test_model_1"
|
200
|
+
"_rev": "0"
|
201
|
+
"model_class": "AssociationTestModelOne"
|
202
|
+
"name": "phil"
|