mattly-exegesis 0.0.10 → 0.2.0
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/LICENSE +22 -0
- data/README.rdoc +51 -7
- data/VERSION.yml +2 -2
- data/lib/exegesis.rb +22 -29
- data/lib/exegesis/database.rb +109 -0
- data/lib/exegesis/design.rb +123 -52
- data/lib/exegesis/document.rb +72 -132
- data/lib/exegesis/model.rb +142 -0
- data/lib/exegesis/server.rb +28 -0
- data/lib/exegesis/utils/http.rb +38 -0
- data/lib/monkeypatches/time.rb +5 -0
- data/test/database_test.rb +161 -0
- data/test/design_test.rb +154 -74
- data/test/document_test.rb +159 -0
- data/test/fixtures/designs/tags/views/by_tag/map.js +8 -0
- data/test/fixtures/designs/tags/views/by_tag/reduce.js +3 -0
- data/test/http_test.rb +79 -0
- data/test/model_test.rb +230 -0
- data/test/server_test.rb +26 -0
- data/test/test_helper.rb +12 -8
- metadata +25 -12
- data/lib/exegesis/design/design_docs.rb +0 -92
- data/test/design_doc_test.rb +0 -120
- data/test/document_class_definitions_test.rb +0 -284
- data/test/document_instance_methods_test.rb +0 -40
- data/test/exegesis_test.rb +0 -28
data/test/model_test.rb
ADDED
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
|
2
|
+
|
|
3
|
+
class FooTestModel
|
|
4
|
+
include Exegesis::Model
|
|
5
|
+
expose :ref, :as => :reference
|
|
6
|
+
end
|
|
7
|
+
class BarTestModel
|
|
8
|
+
include Exegesis::Model
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
class WithDefaultTestModel
|
|
12
|
+
include Exegesis::Model
|
|
13
|
+
default :foo => 'bar'
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
class ModelTestDocument
|
|
17
|
+
include Exegesis::Model
|
|
18
|
+
attr_accessor :database
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
class ExposeTestModel
|
|
22
|
+
include Exegesis::Model
|
|
23
|
+
expose :foo, :bar
|
|
24
|
+
expose :read_only, :writer => false
|
|
25
|
+
expose :custom_writer, :writer => lambda {|val| {'value' => val} }
|
|
26
|
+
expose :castee, :castees, :as => :given
|
|
27
|
+
expose :time, :times, :as => Time
|
|
28
|
+
expose :regex, :regexen, :as => Regexp
|
|
29
|
+
expose :other_doc, :other_docs, :as => :reference
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
class ExegesisModelTest < Test::Unit::TestCase
|
|
33
|
+
|
|
34
|
+
context "class definitions" do
|
|
35
|
+
context "default objects" do
|
|
36
|
+
expect { WithDefaultTestModel.new['foo'].will == 'bar' }
|
|
37
|
+
expect { WithDefaultTestModel.new({'foo' => 'baz'})['foo'].will == 'baz' }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
context "exposing keys" do
|
|
41
|
+
context "regular declarations" do
|
|
42
|
+
before do
|
|
43
|
+
@obj = ExposeTestModel.new(:foo => 'bar', :bar => 'foo')
|
|
44
|
+
end
|
|
45
|
+
context "reading" do
|
|
46
|
+
expect { @obj.foo.will == 'bar' }
|
|
47
|
+
expect { @obj.bar.will == 'foo' }
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
context "writing" do
|
|
51
|
+
before do
|
|
52
|
+
@obj.bar = "bee"
|
|
53
|
+
end
|
|
54
|
+
expect { @obj.bar.will == "bee" }
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
context "with a custom writer" do
|
|
59
|
+
context "when false" do
|
|
60
|
+
before { @obj = ExposeTestModel.new(:read_only => 'value') }
|
|
61
|
+
expect { @obj.read_only.will == 'value' }
|
|
62
|
+
expect { lambda{@obj.read_only = "other value"}.will raise_error(NoMethodError) }
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
context "when lambda" do
|
|
66
|
+
before do
|
|
67
|
+
@obj = ExposeTestModel.new(:custom_writer => 'value')
|
|
68
|
+
@obj.custom_writer = 'other value'
|
|
69
|
+
@expected = {'value' => 'other value'}
|
|
70
|
+
end
|
|
71
|
+
expect { @obj.custom_writer.will == @expected }
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
context "when casting a value" do
|
|
76
|
+
context "when as given" do
|
|
77
|
+
before do
|
|
78
|
+
@obj = ExposeTestModel.new({
|
|
79
|
+
:castee => {'foo' => 'foo', 'class' => 'FooTestModel'},
|
|
80
|
+
:castees => [
|
|
81
|
+
{'foo' => 'foo', 'class' => 'FooTestModel'},
|
|
82
|
+
{'foo' => 'bar', 'class' => 'BarTestModel'}
|
|
83
|
+
]
|
|
84
|
+
})
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
expect { @obj.castee.class.will == FooTestModel }
|
|
88
|
+
expect { @obj.castee['foo'].will == 'foo' }
|
|
89
|
+
expect { @obj.castee.parent.will == @obj }
|
|
90
|
+
|
|
91
|
+
expect { @obj.castees.class.will == Array }
|
|
92
|
+
expect { @obj.castees[0].class.will == FooTestModel }
|
|
93
|
+
expect { @obj.castees[0]['foo'].will == 'foo' }
|
|
94
|
+
expect { @obj.castees[0].parent.will == @obj }
|
|
95
|
+
expect { @obj.castees[1].class.will == BarTestModel }
|
|
96
|
+
expect { @obj.castees[1]['foo'].will == 'bar' }
|
|
97
|
+
expect { @obj.castees[1].parent.will == @obj }
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context "when as time" do
|
|
101
|
+
before do
|
|
102
|
+
@obj = ExposeTestModel.new({:time => Time.now.to_json, :times => [Time.local(2009,3,1).to_json, Time.local(2009,2,1).to_json]})
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
expect { @obj.time.class.will == Time }
|
|
106
|
+
expect { @obj.time.to_f.will be_close(Time.now.to_f, 1) }
|
|
107
|
+
|
|
108
|
+
expect { @obj.times.class.will == Array }
|
|
109
|
+
expect { @obj.times[0].class.will == Time }
|
|
110
|
+
expect { @obj.times[0].will == Time.local(2009,3,1) }
|
|
111
|
+
expect { @obj.times[1].class.will == Time }
|
|
112
|
+
expect { @obj.times[1].will == Time.local(2009,2,1) }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context "when as non document class" do
|
|
116
|
+
before do
|
|
117
|
+
@obj = ExposeTestModel.new({
|
|
118
|
+
:regex => 'foo',
|
|
119
|
+
:regexen => ['foo', 'bar']
|
|
120
|
+
})
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
expect { @obj.regex.will == /foo/ }
|
|
124
|
+
|
|
125
|
+
expect { @obj.regexen.class.will == Array }
|
|
126
|
+
expect { @obj.regexen[0].will == /foo/ }
|
|
127
|
+
expect { @obj.regexen[1].will == /bar/ }
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context "when as reference" do
|
|
131
|
+
context "with a database present" do
|
|
132
|
+
before do
|
|
133
|
+
reset_db
|
|
134
|
+
@obj = ExposeTestModel.new(:other_doc => "other_doc",
|
|
135
|
+
:other_docs => ["other_docs_1", "other_docs_2"])
|
|
136
|
+
@doc = ModelTestDocument.new
|
|
137
|
+
@doc.database = @db
|
|
138
|
+
@obj.parent = @doc
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
context "when the referenced document exists" do
|
|
142
|
+
before do
|
|
143
|
+
[ {'class' => 'ModelTestDocument', '_id' => 'other_doc'},
|
|
144
|
+
{'class' => 'ModelTestDocument', '_id' => 'other_docs_1'},
|
|
145
|
+
{'class' => 'ModelTestDocument', '_id' => 'other_docs_2'}
|
|
146
|
+
].each {|doc| @db.put(doc.delete('_id'), doc) }
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
expect { @obj.other_doc['_rev'].will == @db.get('other_doc')['_rev'] }
|
|
150
|
+
expect { @obj.other_doc.class.will == ModelTestDocument }
|
|
151
|
+
expect { @obj.other_docs.class.will == Array }
|
|
152
|
+
expect { @obj.other_docs[0]['_rev'].will == @db.get('other_docs_1')['_rev'] }
|
|
153
|
+
expect { @obj.other_docs[0].class.will == ModelTestDocument }
|
|
154
|
+
expect { @obj.other_docs[1]['_rev'].will == @db.get('other_docs_2')['_rev'] }
|
|
155
|
+
expect { @obj.other_docs[1].class.will == ModelTestDocument }
|
|
156
|
+
|
|
157
|
+
context "caching" do
|
|
158
|
+
before do
|
|
159
|
+
@obj.other_doc # load it
|
|
160
|
+
doc = @db.get('other_doc')
|
|
161
|
+
doc.update('foo' => 'updated')
|
|
162
|
+
@db.put(doc['_id'], doc.attributes)
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
expect { @obj.other_doc['foo'].will be(nil) }
|
|
166
|
+
expect { @obj.other_doc(true)['foo'].will == 'updated' }
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
context "when the document is missing" do
|
|
171
|
+
expect { lambda{@obj.other_doc}.will raise_error(RestClient::ResourceNotFound) }
|
|
172
|
+
expect { lambda{@obj.other_docs}.will raise_error(RestClient::ResourceNotFound) }
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "when the model has a parent" do
|
|
176
|
+
before do
|
|
177
|
+
@obj.castee = {'class' => 'FooTestModel', 'ref' => 'other_doc'}
|
|
178
|
+
@db.put('other_doc', {'class' => 'ModelTestDocument', '_id' => 'other_doc'})
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
expect { @obj.castee.ref['_rev'].will == @db.get('other_doc')['_rev'] }
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
context "without any database present" do
|
|
186
|
+
before { @obj = ExposeTestModel.new(:other_doc => "some_doc_id") }
|
|
187
|
+
expect { lambda{@obj.other_doc}.will raise_error(ArgumentError) }
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
context "when the value is nil" do
|
|
192
|
+
before do
|
|
193
|
+
@obj = ExposeTestModel.new({:castee => nil, :castees => nil, :regexen => ['foo', nil]})
|
|
194
|
+
end
|
|
195
|
+
expect { @obj.castee.will be(nil) }
|
|
196
|
+
expect { @obj.castees.will be(nil) }
|
|
197
|
+
expect { @obj.regexen.will == [/foo/] }
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
context "instance methods" do
|
|
204
|
+
before do
|
|
205
|
+
@obj = ExposeTestModel.new({:read_only => 'bar'})
|
|
206
|
+
end
|
|
207
|
+
context "update" do
|
|
208
|
+
before do
|
|
209
|
+
@obj.update({:read_only => 'bee'})
|
|
210
|
+
end
|
|
211
|
+
|
|
212
|
+
expect { @obj.read_only.will == 'bee' }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context "update" do
|
|
216
|
+
context "with a writer" do
|
|
217
|
+
before do
|
|
218
|
+
@obj.update_attributes(:foo => 'foo')
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
expect { @obj.foo.will == "foo" }
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context "without a writer" do
|
|
225
|
+
expect { lambda{@obj.update_attributes({:read_only => 'bee'})}.will raise_error(NoMethodError) }
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
end
|
data/test/server_test.rb
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'test_helper.rb')
|
|
2
|
+
|
|
3
|
+
class ExegesisServerTest < Test::Unit::TestCase
|
|
4
|
+
|
|
5
|
+
before(:all) do
|
|
6
|
+
@db = 'http://localhost:5984/exegesis-test'
|
|
7
|
+
RestClient.delete @db rescue nil
|
|
8
|
+
RestClient.delete "#{@db}-2" rescue nil
|
|
9
|
+
RestClient.put @db, ''
|
|
10
|
+
|
|
11
|
+
@server = Exegesis::Server.new('http://localhost:5984')
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "listing databases" do
|
|
15
|
+
expect { @server.databases.include?('exegesis-test').will == true }
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
context "creating a database" do
|
|
19
|
+
before do
|
|
20
|
+
@response = @server.create_database('exegesis-test-2')
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
expect { @response['ok'].will == true }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
end
|
data/test/test_helper.rb
CHANGED
|
@@ -15,25 +15,29 @@ end
|
|
|
15
15
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
|
16
16
|
require 'lib/exegesis'
|
|
17
17
|
|
|
18
|
+
class TestingDatabase
|
|
19
|
+
include Exegesis::Database
|
|
20
|
+
end
|
|
21
|
+
|
|
18
22
|
class Test::Unit::TestCase
|
|
19
23
|
|
|
20
24
|
def fixtures_path fixtures
|
|
21
25
|
File.join(File.dirname(__FILE__), 'fixtures', fixtures)
|
|
22
26
|
end
|
|
23
27
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@db = CouchRest.database db(name) rescue nil
|
|
27
|
-
@db.delete! rescue nil
|
|
28
|
-
@db = CouchRest.database! db(name)
|
|
28
|
+
def db_server
|
|
29
|
+
@db_server ||= Exegesis::Server.new('http://localhost:5984')
|
|
29
30
|
end
|
|
30
31
|
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
# todo: extract to some helper methods to include ala RR, etc
|
|
33
|
+
def reset_db(name=nil)
|
|
34
|
+
RestClient.delete "http://localhost:5984/#{db(name)}" rescue nil
|
|
35
|
+
db_server.create_database(db(name))
|
|
36
|
+
@db = TestingDatabase.new(db_server, db(name))
|
|
33
37
|
end
|
|
34
38
|
|
|
35
39
|
def db(name)
|
|
36
|
-
"
|
|
40
|
+
"exegesis-test#{name.nil? ? '' : "-#{name}"}"
|
|
37
41
|
end
|
|
38
42
|
|
|
39
43
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mattly-exegesis
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.0
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Matt Lyon
|
|
@@ -9,11 +9,11 @@ autorequire:
|
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
11
|
|
|
12
|
-
date: 2009-
|
|
12
|
+
date: 2009-04-04 00:00:00 -07:00
|
|
13
13
|
default_executable:
|
|
14
14
|
dependencies:
|
|
15
15
|
- !ruby/object:Gem::Dependency
|
|
16
|
-
name:
|
|
16
|
+
name: rest-client
|
|
17
17
|
type: :runtime
|
|
18
18
|
version_requirement:
|
|
19
19
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -22,32 +22,45 @@ dependencies:
|
|
|
22
22
|
- !ruby/object:Gem::Version
|
|
23
23
|
version: 0.12.6
|
|
24
24
|
version:
|
|
25
|
-
description:
|
|
25
|
+
description: A Document <> Object Mapper for CouchDB Documents
|
|
26
26
|
email: matt@flowerpowered.com
|
|
27
27
|
executables: []
|
|
28
28
|
|
|
29
29
|
extensions: []
|
|
30
30
|
|
|
31
|
-
extra_rdoc_files:
|
|
32
|
-
|
|
31
|
+
extra_rdoc_files:
|
|
32
|
+
- README.rdoc
|
|
33
|
+
- LICENSE
|
|
33
34
|
files:
|
|
34
35
|
- README.rdoc
|
|
35
36
|
- VERSION.yml
|
|
36
37
|
- lib/exegesis
|
|
37
|
-
- lib/exegesis/
|
|
38
|
-
- lib/exegesis/design/design_docs.rb
|
|
38
|
+
- lib/exegesis/database.rb
|
|
39
39
|
- lib/exegesis/design.rb
|
|
40
40
|
- lib/exegesis/document.rb
|
|
41
|
+
- lib/exegesis/model.rb
|
|
42
|
+
- lib/exegesis/server.rb
|
|
43
|
+
- lib/exegesis/utils
|
|
44
|
+
- lib/exegesis/utils/http.rb
|
|
41
45
|
- lib/exegesis.rb
|
|
42
|
-
-
|
|
46
|
+
- lib/monkeypatches
|
|
47
|
+
- lib/monkeypatches/time.rb
|
|
48
|
+
- test/database_test.rb
|
|
43
49
|
- test/design_test.rb
|
|
44
|
-
- test/
|
|
45
|
-
- test/document_instance_methods_test.rb
|
|
46
|
-
- test/exegesis_test.rb
|
|
50
|
+
- test/document_test.rb
|
|
47
51
|
- test/fixtures
|
|
48
52
|
- test/fixtures/designs
|
|
49
53
|
- test/fixtures/designs/foos.js
|
|
54
|
+
- test/fixtures/designs/tags
|
|
55
|
+
- test/fixtures/designs/tags/views
|
|
56
|
+
- test/fixtures/designs/tags/views/by_tag
|
|
57
|
+
- test/fixtures/designs/tags/views/by_tag/map.js
|
|
58
|
+
- test/fixtures/designs/tags/views/by_tag/reduce.js
|
|
59
|
+
- test/http_test.rb
|
|
60
|
+
- test/model_test.rb
|
|
61
|
+
- test/server_test.rb
|
|
50
62
|
- test/test_helper.rb
|
|
63
|
+
- LICENSE
|
|
51
64
|
has_rdoc: true
|
|
52
65
|
homepage: http://github.com/mattly/exegesis
|
|
53
66
|
post_install_message:
|
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
require 'johnson'
|
|
2
|
-
require 'digest/md5'
|
|
3
|
-
|
|
4
|
-
module Exegesis
|
|
5
|
-
class Design
|
|
6
|
-
module DesignDocs
|
|
7
|
-
|
|
8
|
-
def self.included(base)
|
|
9
|
-
base.extend ClassMethods
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
module ClassMethods
|
|
13
|
-
def designs_directory dir=nil
|
|
14
|
-
if dir
|
|
15
|
-
@designs_directory = Pathname.new(dir)
|
|
16
|
-
else
|
|
17
|
-
@designs_directory || Exegesis.designs_directory
|
|
18
|
-
end
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def design_doc_path
|
|
22
|
-
designs_directory + "#{design_doc_name}.js"
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def design_doc
|
|
26
|
-
js_doc = Johnson.evaluate("v = #{File.read(design_doc_path)}");
|
|
27
|
-
views = js_doc['views'].entries.inject({}) do |memo, (name, mapreduce)|
|
|
28
|
-
memo[name] = mapreduce.entries.inject({}) do |view, (role, func)|
|
|
29
|
-
view.update role => func.toString
|
|
30
|
-
end
|
|
31
|
-
memo
|
|
32
|
-
end
|
|
33
|
-
composite_views = declared_views.dup.update(views)
|
|
34
|
-
{ '_id' => "_design/#{design_doc_name}",
|
|
35
|
-
'language' => 'javascript',
|
|
36
|
-
'views' => composite_views
|
|
37
|
-
}
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def declared_views
|
|
41
|
-
@declared_views ||= {}
|
|
42
|
-
end
|
|
43
|
-
|
|
44
|
-
def view_by *keys
|
|
45
|
-
view_name = "by_#{keys.join('_and_')}"
|
|
46
|
-
doc_keys = keys.map {|k| "doc['#{k}']" }
|
|
47
|
-
declared_views[view_name] = {
|
|
48
|
-
'map' => %|function(doc) {
|
|
49
|
-
if (doc['.kind'] == '#{name.sub(/Design$/,'')}' && #{doc_keys.join(' && ')}) {
|
|
50
|
-
emit(#{keys.length == 1 ? doc_keys.first : "[#{doc_keys.join(', ')}]" }, null);
|
|
51
|
-
}
|
|
52
|
-
}|
|
|
53
|
-
}
|
|
54
|
-
define_method view_name do |*args|
|
|
55
|
-
docs_for view_name, *args
|
|
56
|
-
end
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def design_doc_hash
|
|
60
|
-
hash_for_design design_doc
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def hash_for_design design
|
|
64
|
-
funcs = design['views'].map do |name, view|
|
|
65
|
-
"//view/#{name}/#{view['map']}/#{view['reduce']}"
|
|
66
|
-
end
|
|
67
|
-
Digest::MD5.hexdigest(funcs.sort.join)
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
end
|
|
71
|
-
|
|
72
|
-
def design_doc_hash
|
|
73
|
-
design_doc.nil? ? '' : self.class.hash_for_design(design_doc)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
def design_doc reload=false
|
|
77
|
-
@design_doc = nil if reload
|
|
78
|
-
@design_doc ||= database.get "_design/#{design_doc_name}" rescue nil
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
def push_design!
|
|
82
|
-
return if design_doc_hash == self.class.design_doc_hash
|
|
83
|
-
if design_doc
|
|
84
|
-
design_doc.update(self.class.design_doc)
|
|
85
|
-
design_doc.save
|
|
86
|
-
else
|
|
87
|
-
database.save_doc(self.class.design_doc)
|
|
88
|
-
end
|
|
89
|
-
end
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|