mattetti-couchrest 0.22 → 0.23
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/Rakefile +10 -1
- data/lib/couchrest/core/database.rb +1 -1
- data/lib/couchrest/core/design.rb +7 -17
- data/lib/couchrest/core/document.rb +0 -9
- data/lib/couchrest/core/server.rb +20 -5
- data/lib/couchrest/mixins/class_proxy.rb +108 -0
- data/lib/couchrest/mixins/design_doc.rb +30 -9
- data/lib/couchrest/mixins/document_queries.rb +2 -2
- data/lib/couchrest/mixins/extended_document_mixins.rb +2 -1
- data/lib/couchrest/mixins/properties.rb +1 -1
- data/lib/couchrest/mixins/validation.rb +4 -1
- data/lib/couchrest/mixins/views.rb +27 -20
- data/lib/couchrest/monkeypatches.rb +0 -6
- data/lib/couchrest/more/extended_document.rb +3 -2
- data/lib/couchrest/validation/validation_errors.rb +1 -1
- data/lib/couchrest.rb +1 -1
- data/spec/couchrest/core/database_spec.rb +9 -1
- data/spec/couchrest/core/design_spec.rb +12 -5
- data/spec/couchrest/core/server_spec.rb +30 -0
- data/spec/couchrest/more/extended_doc_subclass_spec.rb +44 -0
- data/spec/couchrest/more/extended_doc_view_spec.rb +158 -10
- data/spec/couchrest/more/property_spec.rb +6 -0
- metadata +2 -21
data/Rakefile
CHANGED
|
@@ -35,7 +35,7 @@ spec = Gem::Specification.new do |s|
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
|
|
38
|
-
desc "
|
|
38
|
+
desc "Create .gemspec file (useful for github)"
|
|
39
39
|
task :gemspec do
|
|
40
40
|
filename = "#{spec.name}.gemspec"
|
|
41
41
|
File.open(filename, "w") do |f|
|
|
@@ -43,6 +43,15 @@ task :gemspec do
|
|
|
43
43
|
end
|
|
44
44
|
end
|
|
45
45
|
|
|
46
|
+
Rake::GemPackageTask.new(spec) do |pkg|
|
|
47
|
+
pkg.gem_spec = spec
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
desc "Install the gem locally"
|
|
51
|
+
task :install => [:package] do
|
|
52
|
+
sh %{sudo gem install pkg/couchrest-#{CouchRest::VERSION}}
|
|
53
|
+
end
|
|
54
|
+
|
|
46
55
|
desc "Run all specs"
|
|
47
56
|
Spec::Rake::SpecTask.new('spec') do |t|
|
|
48
57
|
t.spec_files = FileList['spec/**/*_spec.rb']
|
|
@@ -17,7 +17,7 @@ module CouchRest
|
|
|
17
17
|
@name = name
|
|
18
18
|
@server = server
|
|
19
19
|
@host = server.uri
|
|
20
|
-
@uri = @root = "#{host}/#{name}"
|
|
20
|
+
@uri = @root = "#{host}/#{name.gsub('/','%2F')}"
|
|
21
21
|
@streamer = Streamer.new(self)
|
|
22
22
|
@bulk_save_cache = []
|
|
23
23
|
@bulk_save_cache_limit = 500 # must be smaller than the uuid count
|
|
@@ -35,11 +35,17 @@ JAVASCRIPT
|
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
# Dispatches to any named view.
|
|
38
|
+
# (using the database where this design doc was saved)
|
|
38
39
|
def view view_name, query={}, &block
|
|
40
|
+
view_on database, view_name, query, &block
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Dispatches to any named view in a specific database
|
|
44
|
+
def view_on db, view_name, query={}, &block
|
|
39
45
|
view_name = view_name.to_s
|
|
40
46
|
view_slug = "#{name}/#{view_name}"
|
|
41
47
|
defaults = (self['views'][view_name] && self['views'][view_name]["couchrest-defaults"]) || {}
|
|
42
|
-
|
|
48
|
+
db.view(view_slug, defaults.merge(query), &block)
|
|
43
49
|
end
|
|
44
50
|
|
|
45
51
|
def name
|
|
@@ -64,22 +70,6 @@ JAVASCRIPT
|
|
|
64
70
|
(self['views'][view]["couchrest-defaults"]||{})
|
|
65
71
|
end
|
|
66
72
|
|
|
67
|
-
# def fetch_view_with_docs name, opts, raw=false, &block
|
|
68
|
-
# if raw
|
|
69
|
-
# fetch_view name, opts, &block
|
|
70
|
-
# else
|
|
71
|
-
# begin
|
|
72
|
-
# view = fetch_view name, opts.merge({:include_docs => true}), &block
|
|
73
|
-
# view['rows'].collect{|r|new(r['doc'])} if view['rows']
|
|
74
|
-
# rescue
|
|
75
|
-
# # fallback for old versions of couchdb that don't
|
|
76
|
-
# # have include_docs support
|
|
77
|
-
# view = fetch_view name, opts, &block
|
|
78
|
-
# view['rows'].collect{|r|new(database.get(r['id']))} if view['rows']
|
|
79
|
-
# end
|
|
80
|
-
# end
|
|
81
|
-
# end
|
|
82
|
-
|
|
83
73
|
def fetch_view view_name, opts, &block
|
|
84
74
|
database.view(view_name, opts, &block)
|
|
85
75
|
end
|
|
@@ -65,15 +65,6 @@ module CouchRest
|
|
|
65
65
|
result['ok']
|
|
66
66
|
end
|
|
67
67
|
|
|
68
|
-
# moves the document to a new id. If the destination id currently exists, a rev must be provided.
|
|
69
|
-
# <tt>dest</tt> can take one of two forms if overwriting: "id_to_overwrite?rev=revision" or the actual doc
|
|
70
|
-
# hash with a '_rev' key
|
|
71
|
-
def move(dest)
|
|
72
|
-
raise ArgumentError, "doc.database required to copy" unless database
|
|
73
|
-
result = database.move_doc(self, dest)
|
|
74
|
-
result['ok']
|
|
75
|
-
end
|
|
76
|
-
|
|
77
68
|
# Returns the CouchDB uri for the document
|
|
78
69
|
def uri(append_rev = false)
|
|
79
70
|
return nil if new_document?
|
|
@@ -2,9 +2,19 @@ module CouchRest
|
|
|
2
2
|
class Server
|
|
3
3
|
attr_accessor :uri, :uuid_batch_count, :available_databases
|
|
4
4
|
def initialize(server = 'http://127.0.0.1:5984', uuid_batch_count = 1000)
|
|
5
|
-
|
|
5
|
+
case server
|
|
6
|
+
when %r{\A(http://[^/]+)/(.*)\z}
|
|
7
|
+
@uri, @prefix = $1, $2
|
|
8
|
+
else
|
|
9
|
+
@uri, @prefix = server, ""
|
|
10
|
+
end
|
|
6
11
|
@uuid_batch_count = uuid_batch_count
|
|
7
12
|
end
|
|
13
|
+
|
|
14
|
+
# Add default prefix to database name
|
|
15
|
+
def expand(name)
|
|
16
|
+
@prefix + name
|
|
17
|
+
end
|
|
8
18
|
|
|
9
19
|
# Lists all "available" databases.
|
|
10
20
|
# An available database, is a database that was specified
|
|
@@ -32,7 +42,7 @@ module CouchRest
|
|
|
32
42
|
# @couch.available_database?(:default)
|
|
33
43
|
#
|
|
34
44
|
def available_database?(ref_or_name)
|
|
35
|
-
ref_or_name.is_a?(Symbol) ? available_databases.keys.include?(ref_or_name) : available_databases.values.map{|db| db.name}.include?(ref_or_name)
|
|
45
|
+
ref_or_name.is_a?(Symbol) ? available_databases.keys.include?(ref_or_name) : available_databases.values.map{|db| db.name}.include?(expand(ref_or_name))
|
|
36
46
|
end
|
|
37
47
|
|
|
38
48
|
def default_database=(name, create_unless_exists = true)
|
|
@@ -45,12 +55,17 @@ module CouchRest
|
|
|
45
55
|
|
|
46
56
|
# Lists all databases on the server
|
|
47
57
|
def databases
|
|
48
|
-
CouchRest.get "#{@uri}/_all_dbs"
|
|
58
|
+
dbs = CouchRest.get "#{@uri}/_all_dbs"
|
|
59
|
+
unless @prefix.empty?
|
|
60
|
+
pfx = @prefix.gsub('/','%2F')
|
|
61
|
+
dbs.reject! { |db| db.index(pfx) != 0 }
|
|
62
|
+
end
|
|
63
|
+
dbs
|
|
49
64
|
end
|
|
50
65
|
|
|
51
66
|
# Returns a CouchRest::Database for the given name
|
|
52
67
|
def database(name)
|
|
53
|
-
CouchRest::Database.new(self, name)
|
|
68
|
+
CouchRest::Database.new(self, expand(name))
|
|
54
69
|
end
|
|
55
70
|
|
|
56
71
|
# Creates the database if it doesn't exist
|
|
@@ -66,7 +81,7 @@ module CouchRest
|
|
|
66
81
|
|
|
67
82
|
# Create a database
|
|
68
83
|
def create_db(name)
|
|
69
|
-
CouchRest.put "#{@uri}/#{name}"
|
|
84
|
+
CouchRest.put "#{@uri}/#{expand(name).gsub('/','%2F')}"
|
|
70
85
|
database(name)
|
|
71
86
|
end
|
|
72
87
|
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
module CouchRest
|
|
2
|
+
module Mixins
|
|
3
|
+
module ClassProxy
|
|
4
|
+
|
|
5
|
+
def self.included(base)
|
|
6
|
+
base.extend(ClassMethods)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
module ClassMethods
|
|
10
|
+
|
|
11
|
+
# Return a proxy object which represents a model class on a
|
|
12
|
+
# chosen database instance. This allows you to DRY operations
|
|
13
|
+
# where a database is chosen dynamically.
|
|
14
|
+
#
|
|
15
|
+
# ==== Example:
|
|
16
|
+
#
|
|
17
|
+
# db = CouchRest::Database.new(...)
|
|
18
|
+
# articles = Article.on(db)
|
|
19
|
+
#
|
|
20
|
+
# articles.all { ... }
|
|
21
|
+
# articles.by_title { ... }
|
|
22
|
+
#
|
|
23
|
+
# u = articles.get("someid")
|
|
24
|
+
#
|
|
25
|
+
# u = articles.new(:title => "I like plankton")
|
|
26
|
+
# u.save # saved on the correct database
|
|
27
|
+
|
|
28
|
+
def on(database)
|
|
29
|
+
Proxy.new(self, database)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
class Proxy #:nodoc:
|
|
34
|
+
def initialize(klass, database)
|
|
35
|
+
@klass = klass
|
|
36
|
+
@database = database
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# ExtendedDocument
|
|
40
|
+
|
|
41
|
+
def new(*args)
|
|
42
|
+
doc = @klass.new(*args)
|
|
43
|
+
doc.database = @database
|
|
44
|
+
doc
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def method_missing(m, *args, &block)
|
|
48
|
+
if has_view?(m)
|
|
49
|
+
query = args.shift || {}
|
|
50
|
+
view(m, query, *args, &block)
|
|
51
|
+
else
|
|
52
|
+
super
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Mixins::DocumentQueries
|
|
57
|
+
|
|
58
|
+
def all(opts = {}, &block)
|
|
59
|
+
@klass.all({:database => @database}.merge(opts), &block)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def first(opts = {})
|
|
63
|
+
@klass.first({:database => @database}.merge(opts))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def get(id)
|
|
67
|
+
@klass.get(id, @database)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Mixins::Views
|
|
71
|
+
|
|
72
|
+
def has_view?(view)
|
|
73
|
+
@klass.has_view?(view)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def view(name, query={}, &block)
|
|
77
|
+
@klass.view(name, {:database => @database}.merge(query), &block)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def all_design_doc_versions
|
|
81
|
+
@klass.all_design_doc_versions(@database)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def cleanup_design_docs!
|
|
85
|
+
@klass.cleanup_design_docs!(@database)
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Mixins::DesignDoc
|
|
89
|
+
|
|
90
|
+
def design_doc
|
|
91
|
+
@klass.design_doc
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def design_doc_fresh
|
|
95
|
+
@klass.design_doc_fresh
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def refresh_design_doc
|
|
99
|
+
@klass.refresh_design_doc
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def save_design_doc
|
|
103
|
+
@klass.save_design_doc_on(@database)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
@@ -16,7 +16,7 @@ module CouchRest
|
|
|
16
16
|
def design_doc_slug
|
|
17
17
|
return design_doc_slug_cache if (design_doc_slug_cache && design_doc_fresh)
|
|
18
18
|
funcs = []
|
|
19
|
-
design_doc ||= Design.new(default_design_doc)
|
|
19
|
+
self.design_doc ||= Design.new(default_design_doc)
|
|
20
20
|
design_doc['views'].each do |name, view|
|
|
21
21
|
funcs << "#{name}/#{view['map']}#{view['reduce']}"
|
|
22
22
|
end
|
|
@@ -40,21 +40,42 @@ module CouchRest
|
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def refresh_design_doc
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
design_doc['_id'] = design_doc_id
|
|
44
|
+
design_doc.delete('_rev')
|
|
45
|
+
#design_doc.database = nil
|
|
46
|
+
self.design_doc_fresh = true
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Save the design doc onto the default database, and update the
|
|
50
|
+
# design_doc attribute
|
|
51
|
+
def save_design_doc
|
|
52
|
+
refresh_design_doc unless design_doc_fresh
|
|
53
|
+
self.design_doc = update_design_doc(design_doc)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Save the design doc onto a target database in a thread-safe way,
|
|
57
|
+
# not modifying the model's design_doc
|
|
58
|
+
def save_design_doc_on(db)
|
|
59
|
+
update_design_doc(Design.new(design_doc), db)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
private
|
|
63
|
+
|
|
64
|
+
# Writes out a design_doc to a given database, returning the
|
|
65
|
+
# updated design doc
|
|
66
|
+
def update_design_doc(design_doc, db = database)
|
|
67
|
+
saved = db.get(design_doc['_id']) rescue nil
|
|
45
68
|
if saved
|
|
46
69
|
design_doc['views'].each do |name, view|
|
|
47
70
|
saved['views'][name] = view
|
|
48
71
|
end
|
|
49
|
-
|
|
50
|
-
|
|
72
|
+
db.save_doc(saved)
|
|
73
|
+
saved
|
|
51
74
|
else
|
|
52
|
-
design_doc
|
|
53
|
-
design_doc.delete('_rev')
|
|
54
|
-
design_doc.database = database
|
|
75
|
+
design_doc.database = db
|
|
55
76
|
design_doc.save
|
|
77
|
+
design_doc
|
|
56
78
|
end
|
|
57
|
-
self.design_doc_fresh = true
|
|
58
79
|
end
|
|
59
80
|
|
|
60
81
|
end # module ClassMethods
|
|
@@ -3,4 +3,5 @@ require File.join(File.dirname(__FILE__), 'document_queries')
|
|
|
3
3
|
require File.join(File.dirname(__FILE__), 'views')
|
|
4
4
|
require File.join(File.dirname(__FILE__), 'design_doc')
|
|
5
5
|
require File.join(File.dirname(__FILE__), 'validation')
|
|
6
|
-
require File.join(File.dirname(__FILE__), 'extended_attachments')
|
|
6
|
+
require File.join(File.dirname(__FILE__), 'extended_attachments')
|
|
7
|
+
require File.join(File.dirname(__FILE__), 'class_proxy')
|
|
@@ -9,7 +9,7 @@ module CouchRest
|
|
|
9
9
|
|
|
10
10
|
def self.included(base)
|
|
11
11
|
base.class_eval <<-EOS, __FILE__, __LINE__
|
|
12
|
-
extlib_inheritable_accessor(:properties)
|
|
12
|
+
extlib_inheritable_accessor(:properties) unless self.respond_to?(:properties)
|
|
13
13
|
self.properties ||= []
|
|
14
14
|
EOS
|
|
15
15
|
base.extend(ClassMethods)
|
|
@@ -63,7 +63,10 @@ module CouchRest
|
|
|
63
63
|
|
|
64
64
|
# share the validations with subclasses
|
|
65
65
|
def self.inherited(subklass)
|
|
66
|
-
|
|
66
|
+
self.validators.contexts.each do |k, v|
|
|
67
|
+
subklass.validators.contexts[k] = v.dup
|
|
68
|
+
end
|
|
69
|
+
super
|
|
67
70
|
end
|
|
68
71
|
EOS
|
|
69
72
|
|
|
@@ -4,12 +4,14 @@ module CouchRest
|
|
|
4
4
|
|
|
5
5
|
def self.included(base)
|
|
6
6
|
base.extend(ClassMethods)
|
|
7
|
-
base.send(:extlib_inheritable_accessor, :design_doc)
|
|
8
|
-
base.send(:extlib_inheritable_accessor, :design_doc_slug_cache)
|
|
9
|
-
base.send(:extlib_inheritable_accessor, :design_doc_fresh)
|
|
10
7
|
end
|
|
11
8
|
|
|
12
9
|
module ClassMethods
|
|
10
|
+
attr_accessor :design_doc, :design_doc_slug_cache, :design_doc_fresh
|
|
11
|
+
|
|
12
|
+
def design_doc
|
|
13
|
+
@design_doc ||= Design.new(default_design_doc)
|
|
14
|
+
end
|
|
13
15
|
|
|
14
16
|
# Define a CouchDB view. The name of the view will be the concatenation
|
|
15
17
|
# of <tt>by</tt> and the keys joined by <tt>_and_</tt>
|
|
@@ -57,6 +59,10 @@ module CouchRest
|
|
|
57
59
|
# themselves. By default <tt>Post.by_date</tt> will return the
|
|
58
60
|
# documents included in the generated view.
|
|
59
61
|
#
|
|
62
|
+
# Calling with :database => [instance of CouchRest::Database] will
|
|
63
|
+
# send the query to a specific database, otherwise it will go to
|
|
64
|
+
# the model's default database (use_database)
|
|
65
|
+
#
|
|
60
66
|
# CouchRest::Database#view options can be applied at view definition
|
|
61
67
|
# time as defaults, and they will be curried and used at view query
|
|
62
68
|
# time. Or they can be overridden at query time.
|
|
@@ -70,12 +76,11 @@ module CouchRest
|
|
|
70
76
|
# that model won't be available until generation is complete. This can
|
|
71
77
|
# take some time with large databases. Strategies are in the works.
|
|
72
78
|
#
|
|
73
|
-
# To understand the capabilities of this view system more
|
|
79
|
+
# To understand the capabilities of this view system more completely,
|
|
74
80
|
# it is recommended that you read the RSpec file at
|
|
75
81
|
# <tt>spec/core/model_spec.rb</tt>.
|
|
76
82
|
|
|
77
83
|
def view_by(*keys)
|
|
78
|
-
self.design_doc ||= Design.new(default_design_doc)
|
|
79
84
|
opts = keys.pop if keys.last.is_a?(Hash)
|
|
80
85
|
opts ||= {}
|
|
81
86
|
ducktype = opts.delete(:ducktype)
|
|
@@ -100,12 +105,13 @@ module CouchRest
|
|
|
100
105
|
refresh_design_doc
|
|
101
106
|
end
|
|
102
107
|
query[:raw] = true if query[:reduce]
|
|
108
|
+
db = query.delete(:database) || database
|
|
103
109
|
raw = query.delete(:raw)
|
|
104
|
-
fetch_view_with_docs(name, query, raw, &block)
|
|
110
|
+
fetch_view_with_docs(db, name, query, raw, &block)
|
|
105
111
|
end
|
|
106
112
|
|
|
107
|
-
def all_design_doc_versions
|
|
108
|
-
|
|
113
|
+
def all_design_doc_versions(db = database)
|
|
114
|
+
db.documents :startkey => "_design/#{self.to_s}-",
|
|
109
115
|
:endkey => "_design/#{self.to_s}-\u9999"
|
|
110
116
|
end
|
|
111
117
|
|
|
@@ -114,11 +120,11 @@ module CouchRest
|
|
|
114
120
|
# and consistently using the latest code, is the way to clear out old design
|
|
115
121
|
# docs. Running it to early could mean that live code has to regenerate
|
|
116
122
|
# potentially large indexes.
|
|
117
|
-
def cleanup_design_docs!
|
|
118
|
-
ddocs = all_design_doc_versions
|
|
123
|
+
def cleanup_design_docs!(db = database)
|
|
124
|
+
ddocs = all_design_doc_versions(db)
|
|
119
125
|
ddocs["rows"].each do |row|
|
|
120
126
|
if (row['id'] != design_doc_id)
|
|
121
|
-
|
|
127
|
+
db.delete_doc({
|
|
122
128
|
"_id" => row['id'],
|
|
123
129
|
"_rev" => row['value']['rev']
|
|
124
130
|
})
|
|
@@ -128,30 +134,31 @@ module CouchRest
|
|
|
128
134
|
|
|
129
135
|
private
|
|
130
136
|
|
|
131
|
-
def fetch_view_with_docs(name, opts, raw=false, &block)
|
|
137
|
+
def fetch_view_with_docs(db, name, opts, raw=false, &block)
|
|
132
138
|
if raw || (opts.has_key?(:include_docs) && opts[:include_docs] == false)
|
|
133
|
-
fetch_view(name, opts, &block)
|
|
139
|
+
fetch_view(db, name, opts, &block)
|
|
134
140
|
else
|
|
135
141
|
begin
|
|
136
|
-
view = fetch_view name, opts.merge({:include_docs => true}), &block
|
|
142
|
+
view = fetch_view db, name, opts.merge({:include_docs => true}), &block
|
|
137
143
|
view['rows'].collect{|r|new(r['doc'])} if view['rows']
|
|
138
144
|
rescue
|
|
139
145
|
# fallback for old versions of couchdb that don't
|
|
140
146
|
# have include_docs support
|
|
141
|
-
view = fetch_view(name, opts, &block)
|
|
142
|
-
view['rows'].collect{|r|new(
|
|
147
|
+
view = fetch_view(db, name, opts, &block)
|
|
148
|
+
view['rows'].collect{|r|new(db.get(r['id']))} if view['rows']
|
|
143
149
|
end
|
|
144
150
|
end
|
|
145
151
|
end
|
|
146
152
|
|
|
147
|
-
def fetch_view view_name, opts, &block
|
|
153
|
+
def fetch_view(db, view_name, opts, &block)
|
|
154
|
+
raise "A view needs a database to operate on (specify :database option, or use_database in the #{self.class} class)" unless db
|
|
148
155
|
retryable = true
|
|
149
156
|
begin
|
|
150
|
-
design_doc.
|
|
151
|
-
# the design doc
|
|
157
|
+
design_doc.view_on(db, view_name, opts, &block)
|
|
158
|
+
# the design doc may not have been saved yet on this database
|
|
152
159
|
rescue RestClient::ResourceNotFound => e
|
|
153
160
|
if retryable
|
|
154
|
-
|
|
161
|
+
save_design_doc_on(db)
|
|
155
162
|
retryable = false
|
|
156
163
|
retry
|
|
157
164
|
else
|
|
@@ -11,6 +11,7 @@ module CouchRest
|
|
|
11
11
|
include CouchRest::Mixins::Views
|
|
12
12
|
include CouchRest::Mixins::DesignDoc
|
|
13
13
|
include CouchRest::Mixins::ExtendedAttachments
|
|
14
|
+
include CouchRest::Mixins::ClassProxy
|
|
14
15
|
|
|
15
16
|
def self.inherited(subklass)
|
|
16
17
|
subklass.send(:include, CouchRest::Mixins::Properties)
|
|
@@ -77,10 +78,10 @@ module CouchRest
|
|
|
77
78
|
end
|
|
78
79
|
|
|
79
80
|
# Temp solution to make the view_by methods available
|
|
80
|
-
def self.method_missing(m, *args)
|
|
81
|
+
def self.method_missing(m, *args, &block)
|
|
81
82
|
if has_view?(m)
|
|
82
83
|
query = args.shift || {}
|
|
83
|
-
view(m, query, *args)
|
|
84
|
+
view(m, query, *args, &block)
|
|
84
85
|
else
|
|
85
86
|
super
|
|
86
87
|
end
|
|
@@ -89,7 +89,7 @@ module CouchRest
|
|
|
89
89
|
#
|
|
90
90
|
# @param <Symbol> field_name the name of the field you want an error for
|
|
91
91
|
def on(field_name)
|
|
92
|
-
errors_for_field = errors[field_name]
|
|
92
|
+
errors_for_field = errors[field_name.to_sym]
|
|
93
93
|
errors_for_field.blank? ? nil : errors_for_field
|
|
94
94
|
end
|
|
95
95
|
|
data/lib/couchrest.rb
CHANGED
|
@@ -28,7 +28,7 @@ require 'couchrest/monkeypatches'
|
|
|
28
28
|
|
|
29
29
|
# = CouchDB, close to the metal
|
|
30
30
|
module CouchRest
|
|
31
|
-
VERSION = '0.
|
|
31
|
+
VERSION = '0.23' unless self.const_defined?("VERSION")
|
|
32
32
|
|
|
33
33
|
autoload :Server, 'couchrest/core/server'
|
|
34
34
|
autoload :Database, 'couchrest/core/database'
|
|
@@ -7,7 +7,15 @@ describe CouchRest::Database do
|
|
|
7
7
|
@db.delete! rescue nil
|
|
8
8
|
@db = @cr.create_db(TESTDB) rescue nil
|
|
9
9
|
end
|
|
10
|
-
|
|
10
|
+
|
|
11
|
+
describe "database name including slash" do
|
|
12
|
+
it "should escape the name in the URI" do
|
|
13
|
+
db = @cr.database("foo/bar")
|
|
14
|
+
db.name.should == "foo/bar"
|
|
15
|
+
db.uri.should == "#{COUCHHOST}/foo%2Fbar"
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
11
19
|
describe "map query with _temp_view in Javascript" do
|
|
12
20
|
before(:each) do
|
|
13
21
|
@db.bulk_save([
|
|
@@ -14,7 +14,7 @@ describe CouchRest::Design do
|
|
|
14
14
|
describe "with an unsaved view" do
|
|
15
15
|
before(:each) do
|
|
16
16
|
@des = CouchRest::Design.new
|
|
17
|
-
|
|
17
|
+
@des.view_by :name
|
|
18
18
|
end
|
|
19
19
|
it "should accept a name" do
|
|
20
20
|
@des.name = "mytest"
|
|
@@ -31,7 +31,7 @@ describe CouchRest::Design do
|
|
|
31
31
|
describe "saving" do
|
|
32
32
|
before(:each) do
|
|
33
33
|
@des = CouchRest::Design.new
|
|
34
|
-
|
|
34
|
+
@des.view_by :name
|
|
35
35
|
@des.database = reset_test_db!
|
|
36
36
|
end
|
|
37
37
|
it "should fail without a name" do
|
|
@@ -49,7 +49,7 @@ describe CouchRest::Design do
|
|
|
49
49
|
@db.bulk_save([{"name" => "x"},{"name" => "y"}])
|
|
50
50
|
@des = CouchRest::Design.new
|
|
51
51
|
@des.database = @db
|
|
52
|
-
|
|
52
|
+
@des.view_by :name
|
|
53
53
|
end
|
|
54
54
|
it "should by queryable when it's saved" do
|
|
55
55
|
@des.name = "mydesign"
|
|
@@ -57,6 +57,13 @@ describe CouchRest::Design do
|
|
|
57
57
|
res = @des.view :by_name
|
|
58
58
|
res["rows"][0]["key"].should == "x"
|
|
59
59
|
end
|
|
60
|
+
it "should be queryable on specified database" do
|
|
61
|
+
@des.name = "mydesign"
|
|
62
|
+
@des.save
|
|
63
|
+
@des.database = nil
|
|
64
|
+
res = @des.view_on @db, :by_name
|
|
65
|
+
res["rows"][0]["key"].should == "x"
|
|
66
|
+
end
|
|
60
67
|
end
|
|
61
68
|
|
|
62
69
|
describe "from a saved document" do
|
|
@@ -92,7 +99,7 @@ describe CouchRest::Design do
|
|
|
92
99
|
@db = reset_test_db!
|
|
93
100
|
@des = CouchRest::Design.new
|
|
94
101
|
@des.name = "test"
|
|
95
|
-
|
|
102
|
+
@des.view_by :name, :descending => true
|
|
96
103
|
@des.database = @db
|
|
97
104
|
@des.save
|
|
98
105
|
@db.bulk_save([{"name" => "a"},{"name" => "z"}])
|
|
@@ -116,7 +123,7 @@ describe CouchRest::Design do
|
|
|
116
123
|
@db = reset_test_db!
|
|
117
124
|
@des = CouchRest::Design.new
|
|
118
125
|
@des.name = "test"
|
|
119
|
-
|
|
126
|
+
@des.view_by :name, :age
|
|
120
127
|
@des.database = @db
|
|
121
128
|
@des.save
|
|
122
129
|
@db.bulk_save([{"name" => "a", "age" => 2},
|
|
@@ -2,6 +2,36 @@ require File.dirname(__FILE__) + '/../../spec_helper'
|
|
|
2
2
|
|
|
3
3
|
describe CouchRest::Server do
|
|
4
4
|
|
|
5
|
+
describe "named databases" do
|
|
6
|
+
it "should generate database without prefix" do
|
|
7
|
+
couch = CouchRest::Server.new "http://192.0.2.1:1234"
|
|
8
|
+
db = couch.database("foo")
|
|
9
|
+
db.name.should == "foo"
|
|
10
|
+
db.uri.should == "http://192.0.2.1:1234/foo"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should generate database with prefix" do
|
|
14
|
+
couch = CouchRest::Server.new "http://192.0.2.1:1234/dev"
|
|
15
|
+
db = couch.database("foo")
|
|
16
|
+
db.name.should == "devfoo"
|
|
17
|
+
db.uri.should == "http://192.0.2.1:1234/devfoo"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "should generate database with prefix and slash" do
|
|
21
|
+
couch = CouchRest::Server.new "http://192.0.2.1:1234/dev/"
|
|
22
|
+
db = couch.database("foo")
|
|
23
|
+
db.name.should == "dev/foo"
|
|
24
|
+
db.uri.should == "http://192.0.2.1:1234/dev%2Ffoo"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "should generate database with slashes" do
|
|
28
|
+
couch = CouchRest::Server.new "http://192.0.2.1:1234/dev/sample/"
|
|
29
|
+
db = couch.database("foo/bar")
|
|
30
|
+
db.name.should == "dev/sample/foo/bar"
|
|
31
|
+
db.uri.should == "http://192.0.2.1:1234/dev%2Fsample%2Ffoo%2Fbar"
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
5
35
|
describe "available databases" do
|
|
6
36
|
before(:each) do
|
|
7
37
|
@couch = CouchRest::Server.new
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
require File.dirname(__FILE__) + '/../../spec_helper'
|
|
2
2
|
require File.join(FIXTURE_PATH, 'more', 'card')
|
|
3
|
+
require File.join(FIXTURE_PATH, 'more', 'course')
|
|
3
4
|
|
|
4
5
|
# add a default value
|
|
5
6
|
Card.property :bg_color, :default => '#ccc'
|
|
@@ -13,6 +14,18 @@ class DesignBusinessCard < BusinessCard
|
|
|
13
14
|
property :bg_color, :default => '#eee'
|
|
14
15
|
end
|
|
15
16
|
|
|
17
|
+
class OnlineCourse < Course
|
|
18
|
+
property :url
|
|
19
|
+
view_by :url
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
class Animal < CouchRest::ExtendedDocument
|
|
23
|
+
use_database TEST_SERVER.default_database
|
|
24
|
+
property :name
|
|
25
|
+
view_by :name
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Dog < Animal; end
|
|
16
29
|
|
|
17
30
|
describe "Subclassing an ExtendedDocument" do
|
|
18
31
|
|
|
@@ -42,6 +55,12 @@ describe "Subclassing an ExtendedDocument" do
|
|
|
42
55
|
validated_fields.should include(:job_title)
|
|
43
56
|
end
|
|
44
57
|
|
|
58
|
+
it "should not add to the parent's validations" do
|
|
59
|
+
validated_fields = Card.validators.contexts[:default].map{|v| v.field_name}
|
|
60
|
+
validated_fields.should_not include(:extension_code)
|
|
61
|
+
validated_fields.should_not include(:job_title)
|
|
62
|
+
end
|
|
63
|
+
|
|
45
64
|
it "should inherit default property values" do
|
|
46
65
|
@card.bg_color.should == '#ccc'
|
|
47
66
|
end
|
|
@@ -50,5 +69,30 @@ describe "Subclassing an ExtendedDocument" do
|
|
|
50
69
|
DesignBusinessCard.new.bg_color.should == '#eee'
|
|
51
70
|
end
|
|
52
71
|
|
|
72
|
+
it "should have a design doc slug based on the subclass name" do
|
|
73
|
+
Course.refresh_design_doc
|
|
74
|
+
OnlineCourse.design_doc_slug.should =~ /^OnlineCourse/
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
it "should have its own design_doc_fresh" do
|
|
78
|
+
Animal.refresh_design_doc
|
|
79
|
+
Dog.design_doc_fresh.should_not == true
|
|
80
|
+
Dog.refresh_design_doc
|
|
81
|
+
Dog.design_doc_fresh.should == true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "should not add views to the parent's design_doc" do
|
|
85
|
+
Course.design_doc['views'].keys.should_not include('by_url')
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should not add the parent's views to its design doc" do
|
|
89
|
+
Course.refresh_design_doc
|
|
90
|
+
OnlineCourse.refresh_design_doc
|
|
91
|
+
OnlineCourse.design_doc['views'].keys.should_not include('by_title')
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "should have an all view with a guard clause for couchrest-type == subclass name in the map function" do
|
|
95
|
+
OnlineCourse.design_doc['views']['all']['map'].should =~ /if \(doc\['couchrest-type'\] == 'OnlineCourse'\)/
|
|
96
|
+
end
|
|
53
97
|
end
|
|
54
98
|
|
|
@@ -3,6 +3,14 @@ require File.join(FIXTURE_PATH, 'more', 'article')
|
|
|
3
3
|
require File.join(FIXTURE_PATH, 'more', 'course')
|
|
4
4
|
|
|
5
5
|
describe "ExtendedDocument views" do
|
|
6
|
+
|
|
7
|
+
class Unattached < CouchRest::ExtendedDocument
|
|
8
|
+
# Note: no use_database here
|
|
9
|
+
property :title
|
|
10
|
+
property :questions
|
|
11
|
+
property :professor
|
|
12
|
+
view_by :title
|
|
13
|
+
end
|
|
6
14
|
|
|
7
15
|
describe "a model with simple views and a default param" do
|
|
8
16
|
before(:all) do
|
|
@@ -75,12 +83,18 @@ describe "ExtendedDocument views" do
|
|
|
75
83
|
end
|
|
76
84
|
it "should yield" do
|
|
77
85
|
courses = []
|
|
78
|
-
rs = Course.by_title # remove me
|
|
79
86
|
Course.view(:by_title) do |course|
|
|
80
87
|
courses << course
|
|
81
88
|
end
|
|
82
89
|
courses[0]["doc"]["title"].should =='aaa'
|
|
83
90
|
end
|
|
91
|
+
it "should yield with by_key method" do
|
|
92
|
+
courses = []
|
|
93
|
+
Course.by_title do |course|
|
|
94
|
+
courses << course
|
|
95
|
+
end
|
|
96
|
+
courses[0]["doc"]["title"].should =='aaa'
|
|
97
|
+
end
|
|
84
98
|
end
|
|
85
99
|
|
|
86
100
|
|
|
@@ -103,6 +117,144 @@ describe "ExtendedDocument views" do
|
|
|
103
117
|
end
|
|
104
118
|
end
|
|
105
119
|
|
|
120
|
+
describe "a model class not tied to a database" do
|
|
121
|
+
before(:all) do
|
|
122
|
+
reset_test_db!
|
|
123
|
+
@db = TEST_SERVER.default_database
|
|
124
|
+
%w{aaa bbb ddd eee}.each do |title|
|
|
125
|
+
u = Unattached.new(:title => title)
|
|
126
|
+
u.database = @db
|
|
127
|
+
u.save
|
|
128
|
+
@first_id ||= u.id
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
it "should barf on all if no database given" do
|
|
132
|
+
lambda{Unattached.all}.should raise_error
|
|
133
|
+
end
|
|
134
|
+
it "should query all" do
|
|
135
|
+
rs = Unattached.all :database=>@db
|
|
136
|
+
rs.length.should == 4
|
|
137
|
+
end
|
|
138
|
+
it "should barf on query if no database given" do
|
|
139
|
+
lambda{Unattached.view :by_title}.should raise_error
|
|
140
|
+
end
|
|
141
|
+
it "should make the design doc upon first query" do
|
|
142
|
+
Unattached.by_title :database=>@db
|
|
143
|
+
doc = Unattached.design_doc
|
|
144
|
+
doc['views']['all']['map'].should include('Unattached')
|
|
145
|
+
end
|
|
146
|
+
it "should merge query params" do
|
|
147
|
+
rs = Unattached.by_title :database=>@db, :startkey=>"bbb", :endkey=>"eee"
|
|
148
|
+
rs.length.should == 3
|
|
149
|
+
end
|
|
150
|
+
it "should query via view" do
|
|
151
|
+
view = Unattached.view :by_title, :database=>@db
|
|
152
|
+
designed = Unattached.by_title :database=>@db
|
|
153
|
+
view.should == designed
|
|
154
|
+
end
|
|
155
|
+
it "should yield" do
|
|
156
|
+
things = []
|
|
157
|
+
Unattached.view(:by_title, :database=>@db) do |thing|
|
|
158
|
+
things << thing
|
|
159
|
+
end
|
|
160
|
+
things[0]["doc"]["title"].should =='aaa'
|
|
161
|
+
end
|
|
162
|
+
it "should yield with by_key method" do
|
|
163
|
+
things = []
|
|
164
|
+
Unattached.by_title(:database=>@db) do |thing|
|
|
165
|
+
things << thing
|
|
166
|
+
end
|
|
167
|
+
things[0]["doc"]["title"].should =='aaa'
|
|
168
|
+
end
|
|
169
|
+
it "should barf on get if no database given" do
|
|
170
|
+
lambda{Unattached.get("aaa")}.should raise_error
|
|
171
|
+
end
|
|
172
|
+
it "should get from specific database" do
|
|
173
|
+
u = Unattached.get(@first_id, @db)
|
|
174
|
+
u.title.should == "aaa"
|
|
175
|
+
end
|
|
176
|
+
it "should barf on first if no database given" do
|
|
177
|
+
lambda{Unattached.first}.should raise_error
|
|
178
|
+
end
|
|
179
|
+
it "should get first" do
|
|
180
|
+
u = Unattached.first :database=>@db
|
|
181
|
+
u.title.should =~ /\A...\z/
|
|
182
|
+
end
|
|
183
|
+
it "should barf on all_design_doc_versions if no database given" do
|
|
184
|
+
lambda{Unattached.all_design_doc_versions}.should raise_error
|
|
185
|
+
end
|
|
186
|
+
it "should clean up design docs left around on specific database" do
|
|
187
|
+
Unattached.by_title :database=>@db
|
|
188
|
+
Unattached.all_design_doc_versions(@db)["rows"].length.should == 1
|
|
189
|
+
Unattached.view_by :questions
|
|
190
|
+
Unattached.by_questions :database=>@db
|
|
191
|
+
Unattached.all_design_doc_versions(@db)["rows"].length.should == 2
|
|
192
|
+
Unattached.cleanup_design_docs!(@db)
|
|
193
|
+
Unattached.all_design_doc_versions(@db)["rows"].length.should == 1
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
describe "class proxy" do
|
|
198
|
+
before(:all) do
|
|
199
|
+
reset_test_db!
|
|
200
|
+
@us = Unattached.on(TEST_SERVER.default_database)
|
|
201
|
+
%w{aaa bbb ddd eee}.each do |title|
|
|
202
|
+
u = @us.new(:title => title)
|
|
203
|
+
u.save
|
|
204
|
+
@first_id ||= u.id
|
|
205
|
+
end
|
|
206
|
+
end
|
|
207
|
+
it "should query all" do
|
|
208
|
+
rs = @us.all
|
|
209
|
+
rs.length.should == 4
|
|
210
|
+
end
|
|
211
|
+
it "should make the design doc upon first query" do
|
|
212
|
+
@us.by_title
|
|
213
|
+
doc = @us.design_doc
|
|
214
|
+
doc['views']['all']['map'].should include('Unattached')
|
|
215
|
+
end
|
|
216
|
+
it "should merge query params" do
|
|
217
|
+
rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
|
|
218
|
+
rs.length.should == 3
|
|
219
|
+
end
|
|
220
|
+
it "should query via view" do
|
|
221
|
+
view = @us.view :by_title
|
|
222
|
+
designed = @us.by_title
|
|
223
|
+
view.should == designed
|
|
224
|
+
end
|
|
225
|
+
it "should yield" do
|
|
226
|
+
things = []
|
|
227
|
+
@us.view(:by_title) do |thing|
|
|
228
|
+
things << thing
|
|
229
|
+
end
|
|
230
|
+
things[0]["doc"]["title"].should =='aaa'
|
|
231
|
+
end
|
|
232
|
+
it "should yield with by_key method" do
|
|
233
|
+
things = []
|
|
234
|
+
@us.by_title do |thing|
|
|
235
|
+
things << thing
|
|
236
|
+
end
|
|
237
|
+
things[0]["doc"]["title"].should =='aaa'
|
|
238
|
+
end
|
|
239
|
+
it "should get from specific database" do
|
|
240
|
+
u = @us.get(@first_id)
|
|
241
|
+
u.title.should == "aaa"
|
|
242
|
+
end
|
|
243
|
+
it "should get first" do
|
|
244
|
+
u = @us.first
|
|
245
|
+
u.title.should =~ /\A...\z/
|
|
246
|
+
end
|
|
247
|
+
it "should clean up design docs left around on specific database" do
|
|
248
|
+
@us.by_title
|
|
249
|
+
@us.all_design_doc_versions["rows"].length.should == 1
|
|
250
|
+
Unattached.view_by :professor
|
|
251
|
+
@us.by_professor
|
|
252
|
+
@us.all_design_doc_versions["rows"].length.should == 2
|
|
253
|
+
@us.cleanup_design_docs!
|
|
254
|
+
@us.all_design_doc_versions["rows"].length.should == 1
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
106
258
|
describe "a model with a compound key view" do
|
|
107
259
|
before(:all) do
|
|
108
260
|
Article.design_doc_fresh = false
|
|
@@ -177,14 +329,11 @@ describe "ExtendedDocument views" do
|
|
|
177
329
|
newdocs["rows"].length.should == @design_docs["rows"].length
|
|
178
330
|
end
|
|
179
331
|
it "should create a new version of the design document on view access" do
|
|
180
|
-
|
|
332
|
+
ddocs = Article.all_design_doc_versions["rows"].length
|
|
181
333
|
Article.view_by :updated_at
|
|
182
334
|
Article.by_updated_at
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
doc = Article.database.documents(:key => @design_docs["rows"].first["key"], :include_docs => true)["rows"][0]["doc"]
|
|
186
|
-
doc["_rev"].should_not == old_design_doc["_rev"]
|
|
187
|
-
doc["views"].keys.should include("by_updated_at")
|
|
335
|
+
Article.all_design_doc_versions["rows"].length.should == ddocs + 1
|
|
336
|
+
Article.design_doc["views"].keys.should include("by_updated_at")
|
|
188
337
|
end
|
|
189
338
|
end
|
|
190
339
|
|
|
@@ -196,12 +345,11 @@ describe "ExtendedDocument views" do
|
|
|
196
345
|
Article.by_field
|
|
197
346
|
end
|
|
198
347
|
it "should clean them up" do
|
|
199
|
-
ddocs = Article.all_design_doc_versions
|
|
200
348
|
Article.view_by :stream
|
|
201
349
|
Article.by_stream
|
|
350
|
+
Article.all_design_doc_versions["rows"].length.should > 1
|
|
202
351
|
Article.cleanup_design_docs!
|
|
203
|
-
|
|
204
|
-
ddocs["rows"].length.should == 1
|
|
352
|
+
Article.all_design_doc_versions["rows"].length.should == 1
|
|
205
353
|
end
|
|
206
354
|
end
|
|
207
355
|
end
|
|
@@ -59,6 +59,12 @@ describe "ExtendedDocument properties" do
|
|
|
59
59
|
@card.errors.should_not be_empty
|
|
60
60
|
@card.errors.on(:first_name).should == ["First name must not be blank"]
|
|
61
61
|
end
|
|
62
|
+
|
|
63
|
+
it "should let you look up errors for a field by a string name" do
|
|
64
|
+
@card.first_name = nil
|
|
65
|
+
@card.should_not be_valid
|
|
66
|
+
@card.errors.on('first_name').should == ["First name must not be blank"]
|
|
67
|
+
end
|
|
62
68
|
|
|
63
69
|
it "should validate the presence of 2 attributes" do
|
|
64
70
|
@invoice.clear
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mattetti-couchrest
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: "0.
|
|
4
|
+
version: "0.23"
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- J. Chris Anderson
|
|
@@ -93,6 +93,7 @@ files:
|
|
|
93
93
|
- lib/couchrest/mixins
|
|
94
94
|
- lib/couchrest/mixins/attachments.rb
|
|
95
95
|
- lib/couchrest/mixins/callbacks.rb
|
|
96
|
+
- lib/couchrest/mixins/class_proxy.rb
|
|
96
97
|
- lib/couchrest/mixins/design_doc.rb
|
|
97
98
|
- lib/couchrest/mixins/document_queries.rb
|
|
98
99
|
- lib/couchrest/mixins/extended_attachments.rb
|
|
@@ -149,26 +150,6 @@ files:
|
|
|
149
150
|
- spec/fixtures/attachments/couchdb.png
|
|
150
151
|
- spec/fixtures/attachments/README
|
|
151
152
|
- spec/fixtures/attachments/test.html
|
|
152
|
-
- spec/fixtures/couchapp
|
|
153
|
-
- spec/fixtures/couchapp/_attachments
|
|
154
|
-
- spec/fixtures/couchapp/_attachments/index.html
|
|
155
|
-
- spec/fixtures/couchapp/doc.json
|
|
156
|
-
- spec/fixtures/couchapp/foo
|
|
157
|
-
- spec/fixtures/couchapp/foo/bar.txt
|
|
158
|
-
- spec/fixtures/couchapp/foo/test.json
|
|
159
|
-
- spec/fixtures/couchapp/test.json
|
|
160
|
-
- spec/fixtures/couchapp/views
|
|
161
|
-
- spec/fixtures/couchapp/views/example-map.js
|
|
162
|
-
- spec/fixtures/couchapp/views/example-reduce.js
|
|
163
|
-
- spec/fixtures/couchapp-test
|
|
164
|
-
- spec/fixtures/couchapp-test/my-app
|
|
165
|
-
- spec/fixtures/couchapp-test/my-app/_attachments
|
|
166
|
-
- spec/fixtures/couchapp-test/my-app/_attachments/index.html
|
|
167
|
-
- spec/fixtures/couchapp-test/my-app/foo
|
|
168
|
-
- spec/fixtures/couchapp-test/my-app/foo/bar.txt
|
|
169
|
-
- spec/fixtures/couchapp-test/my-app/views
|
|
170
|
-
- spec/fixtures/couchapp-test/my-app/views/example-map.js
|
|
171
|
-
- spec/fixtures/couchapp-test/my-app/views/example-reduce.js
|
|
172
153
|
- spec/fixtures/more
|
|
173
154
|
- spec/fixtures/more/article.rb
|
|
174
155
|
- spec/fixtures/more/card.rb
|